RFR: 8283894: Intrinsify compress and expand bits on x86

John R Rose jrose at openjdk.java.net
Mon May 2 23:50:22 UTC 2022


On Mon, 2 May 2022 08:19:53 GMT, Jatin Bhateja <jbhateja at openjdk.org> wrote:

> Summary of changes:
> 
> - Patch intrinsifies following newly added Java SE APIs
>   - Integer.compress
>   - Integer.expand
>   - Long.compress
>   - Long.expand
>   
> - Adds C2 IR nodes and corresponding ideal transformations for new operations.
> - We see around ~10x performance speedup due to intrinsification over X86 target. 
> - Adds an IR framework based test to validate newly introduced IR transformations.
> 
> Kindly review and share your feedback.
> 
> Best Regards,
> Jatin

src/hotspot/share/opto/intrinsicnode.cpp line 213:

> 211: }
> 212: 
> 213: Node* ExpandBitsNode::Identity(PhaseGVN* phase) {

I also suggest adding a boolean if `compress_expand_identity` if you add rules which don't apply to both equally.

Here is possible type-propagation logic for compress and expand:


let SIGN_BIT = (((IntOrLong)-1)>>>1)+1  (bit 31 or 63)
let MAX_POS  = (((IntOrLong)-1)>>>1)
lot BITS = 1+bitCount(MAX_POS)  (32 or 64)
if (both x, m are con) {
  // maybe use these rules, by porting the Java code to C++
  compress(CON[x], CON[m]) ] = CON[portable_compress(x,m)]
  expand(CON[x], CON[m]) ] = CON[portable_expand(x,m)]
  // see also https://stackoverflow.com/questions/38938911/portable-efficient-alternative-to-pdep-without-using-bmi2
} else if (m is CON[m] && m != -1) {
  //compress(x, -1) = x   //identity handled elsewhere
  //expand(x, -1) = x     //identity handled elsewhere
  let bitc = bitCount(m)
  LO[ compress(x, CON[m]) ] = 0  //sign bit is never set
  HI[ compress(x, CON[m]) ] = ((1L<<bitc)-1)  //unsigned bit-support
  LO[ expand(x, CON[m]) ] = (m >= 0) ? 0 : SIGN_BIT //sign bit might be set alone
  HI[ expand(x, CON[m]) ] = (m >= 0) ? m : m ^ SIGN_BIT
  // could improve a little by looking TYPE[x], but do not bother
} else {
  // estimate maximum possible weight of m (in 0..63)
  let  maxbitc = BITS   if (LO[m] < 0 && HI[m] >= -1)  // could be -1
  else maxbitc = BITS-1 if (LO[m] < 0 || HI[m] == MAX_POS)  // <0 or maxint
  else maxbitc = BITS-1 - numberOfLeadingZeros(HI[m])
  LO[ compress(x, m) ] = (maxbitc == 64 && LO[x] < 0) ? SIGN_BIT : 0
  HI[ compress(x, m) ] = (maxbitc >= 63) ? HI[x] : MIN(HI[x], (1L<<maxbitc)-1)
  LO[ expand(x, m) ] = (LO[m] >= 0) ? 0 : SIGN_BIT
  HI[ expand(x, m) ] = (LO[m] >= 0) ? HI[m] : MAX_POS
}


The operands of compress and expand are inherently unsigned bitmasks, so the signed type system of C2 gets in the way.  In the future, a somewhat more thorough job could be done if we had bitwise types as well in C2.  For that that would mean, see https://bugs.openjdk.java.net/browse/JDK-8001436

-------------

PR: https://git.openjdk.java.net/jdk/pull/8498


More information about the hotspot-compiler-dev mailing list