RFR: 8332856: C2: Add new transform for bool eq/ne (cmp (and (urshift X const1) const2) 0)

Emanuel Peter epeter at openjdk.org
Tue May 28 16:29:06 UTC 2024


On Mon, 20 May 2024 14:15:46 GMT, Tobias Hotz <duke at openjdk.org> wrote:

> This PR adds a new ideal optimization for the following pattern:
> 
> public boolean testFunc(int a) {
>     int mask = 0b101;
>     int shift = 12;
>     return ((a >> shift) & mask) == 0;
> }
> 
> Where the mask and shift are constant values and a is a variable. For this optimization to work, the right shift has to be idealized to a unsinged right shift earlier in the pipeline, which here: https://github.com/openjdk/jdk/blob/b92bd671835c37cff58e2cdcecd0fe4277557d7f/src/hotspot/share/opto/mulnode.cpp#L731
> If the shift is already an unsiged bit shift, it works as well.
> On AMD64 CPUs, this means that this whole line computation can be reduced to a simple `test` instruction.

I'm looking at `AndINode::Ideal`.

`AndIL_add_shift_and_mask` seems to do something similar, but not exactly this. Maybe it could be extended.

Ha, what about this?

  // Masking off sign bits?  Dont make them!
  if( lop == Op_RShiftI ) {
    const TypeInt *t12 = phase->type(load->in(2))->isa_int();
    if( t12 && t12->is_con() ) { // Shift is by a constant
      int shift = t12->get_con();
      shift &= BitsPerJavaInteger-1;  // semantics of Java shifts
      const int sign_bits_mask = ~right_n_bits(BitsPerJavaInteger - shift);
      // If the AND'ing of the 2 masks has no bits, then only original shifted
      // bits survive.  NO sign-extension bits survive the maskings.
      if( (sign_bits_mask & mask) == 0 ) {
        // Use zero-fill shift instead
        Node *zshift = phase->transform(new URShiftINode(load->in(1),load->in(2)));
        return new AndINode( zshift, in(2) );
      }
    }
  }

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

PR Comment: https://git.openjdk.org/jdk/pull/19310#issuecomment-2135667137


More information about the hotspot-compiler-dev mailing list