# HG changeset patch # User goetz # Date 1485512392 -3600 # Node ID c62fe313f18632e91441bc6959ba93825caf732f # Parent 1ec2a0e4b789bead52283ec5647b4d41e0fa796d 8173470: [C2] Mask shift operands in ideal graph. Reviewed-by: lucy, kvn diff --git a/src/cpu/s390/vm/s390.ad b/src/cpu/s390/vm/s390.ad --- a/src/cpu/s390/vm/s390.ad +++ b/src/cpu/s390/vm/s390.ad @@ -6770,6 +6770,7 @@ format %{ "SLL $dst,$src,$nbits\t# use RISC-like SLLG also for int" %} ins_encode %{ int Nbit = $nbits$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sllg($dst$$Register, $src$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6843,6 +6844,7 @@ format %{ "SRA $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_sra($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); @@ -6895,6 +6897,7 @@ format %{ "SRL $dst,$src" %} ins_encode %{ int Nbit = $src$$constant; + assert((Nbit & (BitsPerJavaInteger - 1)) == Nbit, "Check shift mask in ideal graph"); __ z_srl($dst$$Register, Nbit & (BitsPerJavaInteger - 1), Z_R0); %} ins_pipe(pipe_class_dummy); diff --git a/src/share/vm/opto/mulnode.cpp b/src/share/vm/opto/mulnode.cpp --- a/src/share/vm/opto/mulnode.cpp +++ b/src/share/vm/opto/mulnode.cpp @@ -630,23 +630,39 @@ } //============================================================================= + +static int maskShiftAmount(PhaseGVN *phase, Node *shiftNode, int nBits) { + const Type *t = phase->type(shiftNode->in(2)); + if (t == Type::TOP) return 0; // Right input is dead. + const TypeInt *t2 = t->isa_int(); + if (!t2 || !t2->is_con()) return 0; // Right input is a constant. + + int shift = t2->get_con(); + int maskedShift = shift & (nBits - 1); + + if (maskedShift == 0) return 0; // Let Identity() handle 0 shift count. + + if (shift != maskedShift) { + shiftNode->set_req(2, phase->intcon(maskedShift)); // Replace shift count with masked value. + } + + return maskedShift; +} + //------------------------------Identity--------------------------------------- Node* LShiftINode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerInt - 1 ) ) == 0 ) ? in(1) : this; + const TypeInt *ti = phase->type(in(2))->isa_int(); // shift count is an int + return (ti && ti->is_con() && (ti->get_con() & (BitsPerJavaInteger - 1)) == 0) ? in(1) : this; } //------------------------------Ideal------------------------------------------ // If the right input is a constant, and the left input is an add of a // constant, flatten the tree: (X+con1)< X<type( in(2) ); - if( t == Type::TOP ) return NULL; // Right input is dead - const TypeInt *t2 = t->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & ( BitsPerInt - 1 ); // masked shift count - - if ( con == 0 ) return NULL; // let Identity() handle 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaInteger); + if (con == 0) { + return NULL; + } // Left input is an add of a constant? Node *add1 = in(1); @@ -744,21 +760,18 @@ //============================================================================= //------------------------------Identity--------------------------------------- Node* LShiftLNode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerLong - 1 ) ) == 0 ) ? in(1) : this; + const TypeInt *ti = phase->type(in(2))->isa_int(); // Shift count is an int. + return (ti && ti->is_con() && (ti->get_con() & (BitsPerJavaLong - 1)) == 0) ? in(1) : this; } //------------------------------Ideal------------------------------------------ // If the right input is a constant, and the left input is an add of a // constant, flatten the tree: (X+con1)< X<type( in(2) ); - if( t == Type::TOP ) return NULL; // Right input is dead - const TypeInt *t2 = t->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & ( BitsPerLong - 1 ); // masked shift count - - if ( con == 0 ) return NULL; // let Identity() handle 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaLong); + if (con == 0) { + return NULL; + } // Left input is an add of a constant? Node *add1 = in(1); @@ -853,10 +866,9 @@ //============================================================================= //------------------------------Identity--------------------------------------- Node* RShiftINode::Identity(PhaseGVN* phase) { - const TypeInt *t2 = phase->type(in(2))->isa_int(); - if( !t2 ) return this; - if ( t2->is_con() && ( t2->get_con() & ( BitsPerInt - 1 ) ) == 0 ) - return in(1); + const TypeInt *t2 = phase->type(in(2))->isa_int(); // Shift count is an int. + if (!t2) return this; + if (t2->is_con() && (t2->get_con() & (BitsPerJavaInteger - 1)) == 0) return in(1); // Check for useless sign-masking if( in(1)->Opcode() == Op_LShiftI && @@ -881,15 +893,13 @@ //------------------------------Ideal------------------------------------------ Node *RShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { // Inputs may be TOP if they are dead. - const TypeInt *t1 = phase->type( in(1) )->isa_int(); - if( !t1 ) return NULL; // Left input is an integer - const TypeInt *t2 = phase->type( in(2) )->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant + const TypeInt *t1 = phase->type(in(1))->isa_int(); + if (!t1) return NULL; // Left input is an integer const TypeInt *t3; // type of in(1).in(2) - int shift = t2->get_con(); - shift &= BitsPerJavaInteger-1; // semantics of Java shifts - - if ( shift == 0 ) return NULL; // let Identity() handle 0 shift count + int shift = maskShiftAmount(phase, this, BitsPerJavaInteger); + if (shift == 0) { + return NULL; + } // Check for (x & 0xFF000000) >> 24, whose mask can be made smaller. // Such expressions arise normally from shift chains like (byte)(x >> 24). @@ -1003,8 +1013,8 @@ //============================================================================= //------------------------------Identity--------------------------------------- Node* RShiftLNode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerLong - 1 ) ) == 0 ) ? in(1) : this; + const TypeInt *ti = phase->type(in(2))->isa_int(); // Shift count is an int. + return (ti && ti->is_con() && (ti->get_con() & (BitsPerJavaLong - 1)) == 0) ? in(1) : this; } //------------------------------Value------------------------------------------ @@ -1061,8 +1071,8 @@ //============================================================================= //------------------------------Identity--------------------------------------- Node* URShiftINode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); - if ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerInt - 1 ) ) == 0 ) return in(1); + const TypeInt *ti = phase->type(in(2))->isa_int(); + if (ti && ti->is_con() && (ti->get_con() & (BitsPerJavaInteger - 1)) == 0) return in(1); // Check for "((x << LogBytesPerWord) + (wordSize-1)) >> LogBytesPerWord" which is just "x". // Happens during new-array length computation. @@ -1091,10 +1101,11 @@ //------------------------------Ideal------------------------------------------ Node *URShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { - const TypeInt *t2 = phase->type( in(2) )->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & 31; // Shift count is always masked - if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaInteger); + if (con == 0) { + return NULL; + } + // We'll be wanting the right-shift amount as a mask of that many bits const int mask = right_n_bits(BitsPerJavaInteger - con); @@ -1117,7 +1128,8 @@ // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); - if( in1_op == Op_AddI ) { + const TypeInt *t2 = phase->type(in(2))->isa_int(); + if (in1_op == Op_AddI) { Node *lshl = add->in(1); if( lshl->Opcode() == Op_LShiftI && phase->type(lshl->in(2)) == t2 ) { @@ -1231,17 +1243,17 @@ //============================================================================= //------------------------------Identity--------------------------------------- Node* URShiftLNode::Identity(PhaseGVN* phase) { - const TypeInt *ti = phase->type( in(2) )->isa_int(); // shift count is an int - return ( ti && ti->is_con() && ( ti->get_con() & ( BitsPerLong - 1 ) ) == 0 ) ? in(1) : this; + const TypeInt *ti = phase->type(in(2))->isa_int(); // shift count is an int + return (ti && ti->is_con() && (ti->get_con() & (BitsPerJavaLong - 1)) == 0) ? in(1) : this; } //------------------------------Ideal------------------------------------------ Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { - const TypeInt *t2 = phase->type( in(2) )->isa_int(); - if( !t2 || !t2->is_con() ) return NULL; // Right input is a constant - const int con = t2->get_con() & ( BitsPerLong - 1 ); // Shift count is always masked - if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count - // note: mask computation below does not work for 0 shift count + int con = maskShiftAmount(phase, this, BitsPerJavaLong); + if (con == 0) { + return NULL; + } + // We'll be wanting the right-shift amount as a mask of that many bits const jlong mask = jlong(max_julong >> con); @@ -1250,7 +1262,8 @@ // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); - if( add->Opcode() == Op_AddL ) { + const TypeInt *t2 = phase->type(in(2))->isa_int(); + if (add->Opcode() == Op_AddL) { Node *lshl = add->in(1); if( lshl->Opcode() == Op_LShiftL && phase->type(lshl->in(2)) == t2 ) {