< prev index next >

src/share/vm/opto/mulnode.cpp

Print this page

        

*** 39,49 **** //------------------------------hash------------------------------------------- // Hash function over MulNodes. Needs to be commutative; i.e., I swap // (commute) inputs to MulNodes willy-nilly so the hash function must return // the same value in the presence of edge swapping. uint MulNode::hash() const { ! return (uintptr_t)in(1) + (uintptr_t)in(2) + Opcode(); } //------------------------------Identity--------------------------------------- // Multiplying a one preserves the other argument Node* MulNode::Identity(PhaseGVN* phase) { --- 39,49 ---- //------------------------------hash------------------------------------------- // Hash function over MulNodes. Needs to be commutative; i.e., I swap // (commute) inputs to MulNodes willy-nilly so the hash function must return // the same value in the presence of edge swapping. uint MulNode::hash() const { ! return (uintptr_t)in(1) + (uintptr_t)in(2) + static_cast<uint>(Opcode()); } //------------------------------Identity--------------------------------------- // Multiplying a one preserves the other argument Node* MulNode::Identity(PhaseGVN* phase) {
*** 76,94 **** } } // If the right input is a constant, and the left input is a product of a // constant, flatten the expression tree. ! uint op = Opcode(); if( t2->singleton() && // Right input is a constant? ! op != Op_MulF && // Float & double cannot reassociate ! op != Op_MulD ) { if( t2 == Type::TOP ) return NULL; Node *mul1 = in(1); #ifdef ASSERT // Check for dead loop ! int op1 = mul1->Opcode(); if( phase->eqv( mul1, this ) || phase->eqv( in(2), this ) || ( op1 == mul_opcode() || op1 == add_opcode() ) && ( phase->eqv( mul1->in(1), this ) || phase->eqv( mul1->in(2), this ) || phase->eqv( mul1->in(1), mul1 ) || phase->eqv( mul1->in(2), mul1 ) ) ) assert(false, "dead loop in MulNode::Ideal"); --- 76,94 ---- } } // If the right input is a constant, and the left input is a product of a // constant, flatten the expression tree. ! Opcodes op = Opcode(); if( t2->singleton() && // Right input is a constant? ! op != Opcodes::Op_MulF && // Float & double cannot reassociate ! op != Opcodes::Op_MulD ) { if( t2 == Type::TOP ) return NULL; Node *mul1 = in(1); #ifdef ASSERT // Check for dead loop ! Opcodes op1 = mul1->Opcode(); if( phase->eqv( mul1, this ) || phase->eqv( in(2), this ) || ( op1 == mul_opcode() || op1 == add_opcode() ) && ( phase->eqv( mul1->in(1), this ) || phase->eqv( mul1->in(2), this ) || phase->eqv( mul1->in(1), mul1 ) || phase->eqv( mul1->in(2), mul1 ) ) ) assert(false, "dead loop in MulNode::Ideal");
*** 146,157 **** if( t1 == Type::TOP ) return Type::TOP; if( t2 == Type::TOP ) return Type::TOP; // Either input is ZERO ==> the result is ZERO. // Not valid for floats or doubles since +0.0 * -0.0 --> +0.0 ! int op = Opcode(); ! if( op == Op_MulI || op == Op_AndI || op == Op_MulL || op == Op_AndL ) { const Type *zero = add_id(); // The multiplicative zero if( t1->higher_equal( zero ) ) return zero; if( t2->higher_equal( zero ) ) return zero; } --- 146,157 ---- if( t1 == Type::TOP ) return Type::TOP; if( t2 == Type::TOP ) return Type::TOP; // Either input is ZERO ==> the result is ZERO. // Not valid for floats or doubles since +0.0 * -0.0 --> +0.0 ! Opcodes op = Opcode(); ! if( op == Opcodes::Op_MulI || op == Opcodes::Op_AndI || op == Opcodes::Op_MulL || op == Opcodes::Op_AndL ) { const Type *zero = add_id(); // The multiplicative zero if( t1->higher_equal( zero ) ) return zero; if( t2->higher_equal( zero ) ) return zero; }
*** 160,170 **** return bottom_type(); #if defined(IA32) // Can't trust native compilers to properly fold strict double // multiplication with round-to-zero on this platform. ! if (op == Op_MulD && phase->C->method()->is_strict()) { return TypeD::DOUBLE; } #endif return mul_ring(t1,t2); // Local flavor of type multiplication --- 160,170 ---- return bottom_type(); #if defined(IA32) // Can't trust native compilers to properly fold strict double // multiplication with round-to-zero on this platform. ! if (op == Opcodes::Op_MulD && phase->C->method()->is_strict()) { return TypeD::DOUBLE; } #endif return mul_ring(t1,t2); // Local flavor of type multiplication
*** 436,446 **** // x & x => x if (phase->eqv(in(1), in(2))) return in(1); Node* in1 = in(1); ! uint op = in1->Opcode(); const TypeInt* t2 = phase->type(in(2))->isa_int(); if (t2 && t2->is_con()) { int con = t2->get_con(); // Masking off high bits which are always zero is useless. const TypeInt* t1 = phase->type( in(1) )->isa_int(); --- 436,446 ---- // x & x => x if (phase->eqv(in(1), in(2))) return in(1); Node* in1 = in(1); ! Opcodes op = in1->Opcode(); const TypeInt* t2 = phase->type(in(2))->isa_int(); if (t2 && t2->is_con()) { int con = t2->get_con(); // Masking off high bits which are always zero is useless. const TypeInt* t1 = phase->type( in(1) )->isa_int();
*** 449,459 **** if ((t1_support & con) == t1_support) return in1; } // Masking off the high bits of a unsigned-shift-right is not // needed either. ! if (op == Op_URShiftI) { const TypeInt* t12 = phase->type(in1->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 int mask = max_juint >> shift; --- 449,459 ---- if ((t1_support & con) == t1_support) return in1; } // Masking off the high bits of a unsigned-shift-right is not // needed either. ! if (op == Opcodes::Op_URShiftI) { const TypeInt* t12 = phase->type(in1->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 int mask = max_juint >> shift;
*** 470,506 **** // Special case constant AND mask const TypeInt *t2 = phase->type( in(2) )->isa_int(); if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape); const int mask = t2->get_con(); Node *load = in(1); ! uint lop = load->Opcode(); // Masking bits off of a Character? Hi bits are already zero. ! if( lop == Op_LoadUS && (mask & 0xFFFF0000) ) // Can we make a smaller mask? return new AndINode(load,phase->intcon(mask&0xFFFF)); // Masking bits off of a Short? Loading a Character does some masking if (can_reshape && load->outcnt() == 1 && load->unique_out() == this) { ! if (lop == Op_LoadS && (mask & 0xFFFF0000) == 0 ) { Node* ldus = load->as_Load()->convert_to_unsigned_load(*phase); ldus = phase->transform(ldus); return new AndINode(ldus, phase->intcon(mask & 0xFFFF)); } // Masking sign bits off of a Byte? Do an unsigned byte load plus // an and. ! if (lop == Op_LoadB && (mask & 0xFFFFFF00) == 0) { Node* ldub = load->as_Load()->convert_to_unsigned_load(*phase); ldub = phase->transform(ldub); return new AndINode(ldub, phase->intcon(mask)); } } // 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); --- 470,506 ---- // Special case constant AND mask const TypeInt *t2 = phase->type( in(2) )->isa_int(); if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape); const int mask = t2->get_con(); Node *load = in(1); ! Opcodes lop = load->Opcode(); // Masking bits off of a Character? Hi bits are already zero. ! if( lop == Opcodes::Op_LoadUS && (mask & 0xFFFF0000) ) // Can we make a smaller mask? return new AndINode(load,phase->intcon(mask&0xFFFF)); // Masking bits off of a Short? Loading a Character does some masking if (can_reshape && load->outcnt() == 1 && load->unique_out() == this) { ! if (lop == Opcodes::Op_LoadS && (mask & 0xFFFF0000) == 0 ) { Node* ldus = load->as_Load()->convert_to_unsigned_load(*phase); ldus = phase->transform(ldus); return new AndINode(ldus, phase->intcon(mask & 0xFFFF)); } // Masking sign bits off of a Byte? Do an unsigned byte load plus // an and. ! if (lop == Opcodes::Op_LoadB && (mask & 0xFFFFFF00) == 0) { Node* ldub = load->as_Load()->convert_to_unsigned_load(*phase); ldub = phase->transform(ldub); return new AndINode(ldub, phase->intcon(mask)); } } // Masking off sign bits? Dont make them! ! if( lop == Opcodes::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);
*** 515,525 **** } // Check for 'negate/and-1', a pattern emitted when someone asks for // 'mod 2'. Negate leaves the low order bit unchanged (think: complement // plus 1) and the mask is of the low order bit. Skip the negate. ! if( lop == Op_SubI && mask == 1 && load->in(1) && phase->type(load->in(1)) == TypeInt::ZERO ) return new AndINode( load->in(2), in(2) ); return MulNode::Ideal(phase, can_reshape); } --- 515,525 ---- } // Check for 'negate/and-1', a pattern emitted when someone asks for // 'mod 2'. Negate leaves the low order bit unchanged (think: complement // plus 1) and the mask is of the low order bit. Skip the negate. ! if( lop == Opcodes::Op_SubI && mask == 1 && load->in(1) && phase->type(load->in(1)) == TypeInt::ZERO ) return new AndINode( load->in(2), in(2) ); return MulNode::Ideal(phase, can_reshape); }
*** 569,582 **** int bit_count = log2_long(t1->_hi) + 1; jlong t1_support = jlong(max_julong >> (BitsPerJavaLong - bit_count)); if ((t1_support & con) == t1_support) return usr; } ! uint lop = usr->Opcode(); // Masking off the high bits of a unsigned-shift-right is not // needed either. ! if( lop == Op_URShiftL ) { const TypeInt *t12 = phase->type( usr->in(2) )->isa_int(); if( t12 && t12->is_con() ) { // Shift is by a constant int shift = t12->get_con(); shift &= BitsPerJavaLong - 1; // semantics of Java shifts jlong mask = max_julong >> shift; --- 569,582 ---- int bit_count = log2_long(t1->_hi) + 1; jlong t1_support = jlong(max_julong >> (BitsPerJavaLong - bit_count)); if ((t1_support & con) == t1_support) return usr; } ! Opcodes lop = usr->Opcode(); // Masking off the high bits of a unsigned-shift-right is not // needed either. ! if( lop == Opcodes::Op_URShiftL ) { const TypeInt *t12 = phase->type( usr->in(2) )->isa_int(); if( t12 && t12->is_con() ) { // Shift is by a constant int shift = t12->get_con(); shift &= BitsPerJavaLong - 1; // semantics of Java shifts jlong mask = max_julong >> shift;
*** 594,618 **** const TypeLong *t2 = phase->type( in(2) )->isa_long(); if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape); const jlong mask = t2->get_con(); Node* in1 = in(1); ! uint op = in1->Opcode(); // Are we masking a long that was converted from an int with a mask // that fits in 32-bits? Commute them and use an AndINode. Don't // convert masks which would cause a sign extension of the integer // value. This check includes UI2L masks (0x00000000FFFFFFFF) which // would be optimized away later in Identity. ! if (op == Op_ConvI2L && (mask & UCONST64(0xFFFFFFFF80000000)) == 0) { Node* andi = new AndINode(in1->in(1), phase->intcon(mask)); andi = phase->transform(andi); return new ConvI2LNode(andi); } // Masking off sign bits? Dont make them! ! if (op == Op_RShiftL) { const TypeInt* t12 = phase->type(in1->in(2))->isa_int(); if( t12 && t12->is_con() ) { // Shift is by a constant int shift = t12->get_con(); shift &= BitsPerJavaLong - 1; // semantics of Java shifts const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - shift)) -1); --- 594,618 ---- const TypeLong *t2 = phase->type( in(2) )->isa_long(); if( !t2 || !t2->is_con() ) return MulNode::Ideal(phase, can_reshape); const jlong mask = t2->get_con(); Node* in1 = in(1); ! Opcodes op = in1->Opcode(); // Are we masking a long that was converted from an int with a mask // that fits in 32-bits? Commute them and use an AndINode. Don't // convert masks which would cause a sign extension of the integer // value. This check includes UI2L masks (0x00000000FFFFFFFF) which // would be optimized away later in Identity. ! if (op == Opcodes::Op_ConvI2L && (mask & UCONST64(0xFFFFFFFF80000000)) == 0) { Node* andi = new AndINode(in1->in(1), phase->intcon(mask)); andi = phase->transform(andi); return new ConvI2LNode(andi); } // Masking off sign bits? Dont make them! ! if (op == Opcodes::Op_RShiftL) { const TypeInt* t12 = phase->type(in1->in(2))->isa_int(); if( t12 && t12->is_con() ) { // Shift is by a constant int shift = t12->get_con(); shift &= BitsPerJavaLong - 1; // semantics of Java shifts const jlong sign_bits_mask = ~(((jlong)CONST64(1) << (jlong)(BitsPerJavaLong - shift)) -1);
*** 648,659 **** if ( con == 0 ) return NULL; // let Identity() handle 0 shift count // Left input is an add of a constant? Node *add1 = in(1); ! int add1_op = add1->Opcode(); ! if( add1_op == Op_AddI ) { // Left input is an add? assert( add1 != add1->in(1), "dead loop in LShiftINode::Ideal" ); const TypeInt *t12 = phase->type(add1->in(2))->isa_int(); if( t12 && t12->is_con() ){ // Left input is an add of a con? // Transform is legal, but check for profit. Avoid breaking 'i2s' // and 'i2b' patterns which typically fold into 'StoreC/StoreB'. --- 648,659 ---- if ( con == 0 ) return NULL; // let Identity() handle 0 shift count // Left input is an add of a constant? Node *add1 = in(1); ! Opcodes add1_op = add1->Opcode(); ! if( add1_op == Opcodes::Op_AddI ) { // Left input is an add? assert( add1 != add1->in(1), "dead loop in LShiftINode::Ideal" ); const TypeInt *t12 = phase->type(add1->in(2))->isa_int(); if( t12 && t12->is_con() ){ // Left input is an add of a con? // Transform is legal, but check for profit. Avoid breaking 'i2s' // and 'i2b' patterns which typically fold into 'StoreC/StoreB'.
*** 665,695 **** } } } // Check for "(x>>c0)<<c0" which just masks off low bits ! if( (add1_op == Op_RShiftI || add1_op == Op_URShiftI ) && add1->in(2) == in(2) ) // Convert to "(x & -(1<<c0))" return new AndINode(add1->in(1),phase->intcon( -(1<<con))); // Check for "((x>>c0) & Y)<<c0" which just masks off more low bits ! if( add1_op == Op_AndI ) { Node *add2 = add1->in(1); ! int add2_op = add2->Opcode(); ! if( (add2_op == Op_RShiftI || add2_op == Op_URShiftI ) && add2->in(2) == in(2) ) { // Convert to "(x & (Y<<c0))" Node *y_sh = phase->transform( new LShiftINode( add1->in(2), in(2) ) ); return new AndINode( add2->in(1), y_sh ); } } // Check for ((x & ((1<<(32-c0))-1)) << c0) which ANDs off high bits // before shifting them away. const jint bits_mask = right_n_bits(BitsPerJavaInteger-con); ! if( add1_op == Op_AndI && phase->type(add1->in(2)) == TypeInt::make( bits_mask ) ) return new LShiftINode( add1->in(1), in(2) ); return NULL; } --- 665,695 ---- } } } // Check for "(x>>c0)<<c0" which just masks off low bits ! if( (add1_op == Opcodes::Op_RShiftI || add1_op == Opcodes::Op_URShiftI ) && add1->in(2) == in(2) ) // Convert to "(x & -(1<<c0))" return new AndINode(add1->in(1),phase->intcon( -(1<<con))); // Check for "((x>>c0) & Y)<<c0" which just masks off more low bits ! if( add1_op == Opcodes::Op_AndI ) { Node *add2 = add1->in(1); ! Opcodes add2_op = add2->Opcode(); ! if( (add2_op == Opcodes::Op_RShiftI || add2_op == Opcodes::Op_URShiftI ) && add2->in(2) == in(2) ) { // Convert to "(x & (Y<<c0))" Node *y_sh = phase->transform( new LShiftINode( add1->in(2), in(2) ) ); return new AndINode( add2->in(1), y_sh ); } } // Check for ((x & ((1<<(32-c0))-1)) << c0) which ANDs off high bits // before shifting them away. const jint bits_mask = right_n_bits(BitsPerJavaInteger-con); ! if( add1_op == Opcodes::Op_AndI && phase->type(add1->in(2)) == TypeInt::make( bits_mask ) ) return new LShiftINode( add1->in(1), in(2) ); return NULL; }
*** 760,771 **** if ( con == 0 ) return NULL; // let Identity() handle 0 shift count // Left input is an add of a constant? Node *add1 = in(1); ! int add1_op = add1->Opcode(); ! if( add1_op == Op_AddL ) { // Left input is an add? // Avoid dead data cycles from dead loops assert( add1 != add1->in(1), "dead loop in LShiftLNode::Ideal" ); const TypeLong *t12 = phase->type(add1->in(2))->isa_long(); if( t12 && t12->is_con() ){ // Left input is an add of a con? // Compute X << con0 --- 760,771 ---- if ( con == 0 ) return NULL; // let Identity() handle 0 shift count // Left input is an add of a constant? Node *add1 = in(1); ! Opcodes add1_op = add1->Opcode(); ! if( add1_op == Opcodes::Op_AddL ) { // Left input is an add? // Avoid dead data cycles from dead loops assert( add1 != add1->in(1), "dead loop in LShiftLNode::Ideal" ); const TypeLong *t12 = phase->type(add1->in(2))->isa_long(); if( t12 && t12->is_con() ){ // Left input is an add of a con? // Compute X << con0
*** 774,804 **** return new AddLNode( lsh, phase->longcon(t12->get_con() << con)); } } // Check for "(x>>c0)<<c0" which just masks off low bits ! if( (add1_op == Op_RShiftL || add1_op == Op_URShiftL ) && add1->in(2) == in(2) ) // Convert to "(x & -(1<<c0))" return new AndLNode(add1->in(1),phase->longcon( -(CONST64(1)<<con))); // Check for "((x>>c0) & Y)<<c0" which just masks off more low bits ! if( add1_op == Op_AndL ) { Node *add2 = add1->in(1); ! int add2_op = add2->Opcode(); ! if( (add2_op == Op_RShiftL || add2_op == Op_URShiftL ) && add2->in(2) == in(2) ) { // Convert to "(x & (Y<<c0))" Node *y_sh = phase->transform( new LShiftLNode( add1->in(2), in(2) ) ); return new AndLNode( add2->in(1), y_sh ); } } // Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits // before shifting them away. const jlong bits_mask = jlong(max_julong >> con); ! if( add1_op == Op_AndL && phase->type(add1->in(2)) == TypeLong::make( bits_mask ) ) return new LShiftLNode( add1->in(1), in(2) ); return NULL; } --- 774,804 ---- return new AddLNode( lsh, phase->longcon(t12->get_con() << con)); } } // Check for "(x>>c0)<<c0" which just masks off low bits ! if( (add1_op == Opcodes::Op_RShiftL || add1_op == Opcodes::Op_URShiftL ) && add1->in(2) == in(2) ) // Convert to "(x & -(1<<c0))" return new AndLNode(add1->in(1),phase->longcon( -(CONST64(1)<<con))); // Check for "((x>>c0) & Y)<<c0" which just masks off more low bits ! if( add1_op == Opcodes::Op_AndL ) { Node *add2 = add1->in(1); ! Opcodes add2_op = add2->Opcode(); ! if( (add2_op == Opcodes::Op_RShiftL || add2_op == Opcodes::Op_URShiftL ) && add2->in(2) == in(2) ) { // Convert to "(x & (Y<<c0))" Node *y_sh = phase->transform( new LShiftLNode( add1->in(2), in(2) ) ); return new AndLNode( add2->in(1), y_sh ); } } // Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits // before shifting them away. const jlong bits_mask = jlong(max_julong >> con); ! if( add1_op == Opcodes::Op_AndL && phase->type(add1->in(2)) == TypeLong::make( bits_mask ) ) return new LShiftLNode( add1->in(1), in(2) ); return NULL; }
*** 857,867 **** if( !t2 ) return this; if ( t2->is_con() && ( t2->get_con() & ( BitsPerInt - 1 ) ) == 0 ) return in(1); // Check for useless sign-masking ! if( in(1)->Opcode() == Op_LShiftI && in(1)->req() == 3 && in(1)->in(2) == in(2) && t2->is_con() ) { uint shift = t2->get_con(); shift &= BitsPerJavaInteger-1; // semantics of Java shifts --- 857,867 ---- if( !t2 ) return this; if ( t2->is_con() && ( t2->get_con() & ( BitsPerInt - 1 ) ) == 0 ) return in(1); // Check for useless sign-masking ! if( in(1)->Opcode() == Opcodes::Op_LShiftI && in(1)->req() == 3 && in(1)->in(2) == in(2) && t2->is_con() ) { uint shift = t2->get_con(); shift &= BitsPerJavaInteger-1; // semantics of Java shifts
*** 892,902 **** if ( shift == 0 ) return NULL; // let Identity() handle 0 shift count // Check for (x & 0xFF000000) >> 24, whose mask can be made smaller. // Such expressions arise normally from shift chains like (byte)(x >> 24). const Node *mask = in(1); ! if( mask->Opcode() == Op_AndI && (t3 = phase->type(mask->in(2))->isa_int()) && t3->is_con() ) { Node *x = mask->in(1); jint maskbits = t3->get_con(); // Convert to "(x >> shift) & (mask >> shift)" --- 892,902 ---- if ( shift == 0 ) return NULL; // let Identity() handle 0 shift count // Check for (x & 0xFF000000) >> 24, whose mask can be made smaller. // Such expressions arise normally from shift chains like (byte)(x >> 24). const Node *mask = in(1); ! if( mask->Opcode() == Opcodes::Op_AndI && (t3 = phase->type(mask->in(2))->isa_int()) && t3->is_con() ) { Node *x = mask->in(1); jint maskbits = t3->get_con(); // Convert to "(x >> shift) & (mask >> shift)"
*** 904,942 **** return new AndINode(shr_nomask, phase->intcon( maskbits >> shift)); } // Check for "(short[i] <<16)>>16" which simply sign-extends const Node *shl = in(1); ! if( shl->Opcode() != Op_LShiftI ) return NULL; if( shift == 16 && (t3 = phase->type(shl->in(2))->isa_int()) && t3->is_con(16) ) { Node *ld = shl->in(1); ! if( ld->Opcode() == Op_LoadS ) { // Sign extension is just useless here. Return a RShiftI of zero instead // returning 'ld' directly. We cannot return an old Node directly as // that is the job of 'Identity' calls and Identity calls only work on // direct inputs ('ld' is an extra Node removed from 'this'). The // combined optimization requires Identity only return direct inputs. set_req(1, ld); set_req(2, phase->intcon(0)); return this; } else if( can_reshape && ! ld->Opcode() == Op_LoadUS && ld->outcnt() == 1 && ld->unique_out() == shl) // Replace zero-extension-load with sign-extension-load return ld->as_Load()->convert_to_signed_load(*phase); } // Check for "(byte[i] <<24)>>24" which simply sign-extends if( shift == 24 && (t3 = phase->type(shl->in(2))->isa_int()) && t3->is_con(24) ) { Node *ld = shl->in(1); ! if( ld->Opcode() == Op_LoadB ) { // Sign extension is just useless here set_req(1, ld); set_req(2, phase->intcon(0)); return this; } --- 904,942 ---- return new AndINode(shr_nomask, phase->intcon( maskbits >> shift)); } // Check for "(short[i] <<16)>>16" which simply sign-extends const Node *shl = in(1); ! if( shl->Opcode() != Opcodes::Op_LShiftI ) return NULL; if( shift == 16 && (t3 = phase->type(shl->in(2))->isa_int()) && t3->is_con(16) ) { Node *ld = shl->in(1); ! if( ld->Opcode() == Opcodes::Op_LoadS ) { // Sign extension is just useless here. Return a RShiftI of zero instead // returning 'ld' directly. We cannot return an old Node directly as // that is the job of 'Identity' calls and Identity calls only work on // direct inputs ('ld' is an extra Node removed from 'this'). The // combined optimization requires Identity only return direct inputs. set_req(1, ld); set_req(2, phase->intcon(0)); return this; } else if( can_reshape && ! ld->Opcode() == Opcodes::Op_LoadUS && ld->outcnt() == 1 && ld->unique_out() == shl) // Replace zero-extension-load with sign-extension-load return ld->as_Load()->convert_to_signed_load(*phase); } // Check for "(byte[i] <<24)>>24" which simply sign-extends if( shift == 24 && (t3 = phase->type(shl->in(2))->isa_int()) && t3->is_con(24) ) { Node *ld = shl->in(1); ! if( ld->Opcode() == Opcodes::Op_LoadB ) { // Sign extension is just useless here set_req(1, ld); set_req(2, phase->intcon(0)); return this; }
*** 1066,1079 **** // Check for "((x << LogBytesPerWord) + (wordSize-1)) >> LogBytesPerWord" which is just "x". // Happens during new-array length computation. // Safe if 'x' is in the range [0..(max_int>>LogBytesPerWord)] Node *add = in(1); ! if( add->Opcode() == Op_AddI ) { const TypeInt *t2 = phase->type(add->in(2))->isa_int(); if( t2 && t2->is_con(wordSize - 1) && ! add->in(1)->Opcode() == Op_LShiftI ) { // Check that shift_counts are LogBytesPerWord Node *lshift_count = add->in(1)->in(2); const TypeInt *t_lshift_count = phase->type(lshift_count)->isa_int(); if( t_lshift_count && t_lshift_count->is_con(LogBytesPerWord) && t_lshift_count == phase->type(in(2)) ) { --- 1066,1079 ---- // Check for "((x << LogBytesPerWord) + (wordSize-1)) >> LogBytesPerWord" which is just "x". // Happens during new-array length computation. // Safe if 'x' is in the range [0..(max_int>>LogBytesPerWord)] Node *add = in(1); ! if( add->Opcode() == Opcodes::Op_AddI ) { const TypeInt *t2 = phase->type(add->in(2))->isa_int(); if( t2 && t2->is_con(wordSize - 1) && ! add->in(1)->Opcode() == Opcodes::Op_LShiftI ) { // Check that shift_counts are LogBytesPerWord Node *lshift_count = add->in(1)->in(2); const TypeInt *t_lshift_count = phase->type(lshift_count)->isa_int(); if( t_lshift_count && t_lshift_count->is_con(LogBytesPerWord) && t_lshift_count == phase->type(in(2)) ) {
*** 1096,1109 **** const int con = t2->get_con() & 31; // Shift count is always masked if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count // We'll be wanting the right-shift amount as a mask of that many bits const int mask = right_n_bits(BitsPerJavaInteger - con); ! int in1_op = in(1)->Opcode(); // Check for ((x>>>a)>>>b) and replace with (x>>>(a+b)) when a+b < 32 ! if( in1_op == Op_URShiftI ) { const TypeInt *t12 = phase->type( in(1)->in(2) )->isa_int(); if( t12 && t12->is_con() ) { // Right input is a constant assert( in(1) != in(1)->in(1), "dead loop in URShiftINode::Ideal" ); const int con2 = t12->get_con() & 31; // Shift count is always masked const int con3 = con+con2; --- 1096,1109 ---- const int con = t2->get_con() & 31; // Shift count is always masked if ( con == 0 ) return NULL; // let Identity() handle a 0 shift count // We'll be wanting the right-shift amount as a mask of that many bits const int mask = right_n_bits(BitsPerJavaInteger - con); ! Opcodes in1_op = in(1)->Opcode(); // Check for ((x>>>a)>>>b) and replace with (x>>>(a+b)) when a+b < 32 ! if( in1_op == Opcodes::Op_URShiftI ) { const TypeInt *t12 = phase->type( in(1)->in(2) )->isa_int(); if( t12 && t12->is_con() ) { // Right input is a constant assert( in(1) != in(1)->in(1), "dead loop in URShiftINode::Ideal" ); const int con2 = t12->get_con() & 31; // Shift count is always masked const int con3 = con+con2;
*** 1115,1127 **** // Check for ((x << z) + Y) >>> z. Replace with x + con>>>z // The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z". // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<<Z) + Y) >>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); ! if( in1_op == Op_AddI ) { Node *lshl = add->in(1); ! if( lshl->Opcode() == Op_LShiftI && phase->type(lshl->in(2)) == t2 ) { Node *y_z = phase->transform( new URShiftINode(add->in(2),in(2)) ); Node *sum = phase->transform( new AddINode( lshl->in(1), y_z ) ); return new AndINode( sum, phase->intcon(mask) ); } --- 1115,1127 ---- // Check for ((x << z) + Y) >>> z. Replace with x + con>>>z // The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z". // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<<Z) + Y) >>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); ! if( in1_op == Opcodes::Op_AddI ) { Node *lshl = add->in(1); ! if( lshl->Opcode() == Opcodes::Op_LShiftI && phase->type(lshl->in(2)) == t2 ) { Node *y_z = phase->transform( new URShiftINode(add->in(2),in(2)) ); Node *sum = phase->transform( new AddINode( lshl->in(1), y_z ) ); return new AndINode( sum, phase->intcon(mask) ); }
*** 1129,1139 **** // Check for (x & mask) >>> z. Replace with (x >>> z) & (mask >>> z) // This shortens the mask. Also, if we are extracting a high byte and // storing it to a buffer, the mask will be removed completely. Node *andi = in(1); ! if( in1_op == Op_AndI ) { const TypeInt *t3 = phase->type( andi->in(2) )->isa_int(); if( t3 && t3->is_con() ) { // Right input is a constant jint mask2 = t3->get_con(); mask2 >>= con; // *signed* shift downward (high-order zeroes do not help) Node *newshr = phase->transform( new URShiftINode(andi->in(1), in(2)) ); --- 1129,1139 ---- // Check for (x & mask) >>> z. Replace with (x >>> z) & (mask >>> z) // This shortens the mask. Also, if we are extracting a high byte and // storing it to a buffer, the mask will be removed completely. Node *andi = in(1); ! if( in1_op == Opcodes::Op_AndI ) { const TypeInt *t3 = phase->type( andi->in(2) )->isa_int(); if( t3 && t3->is_con() ) { // Right input is a constant jint mask2 = t3->get_con(); mask2 >>= con; // *signed* shift downward (high-order zeroes do not help) Node *newshr = phase->transform( new URShiftINode(andi->in(1), in(2)) );
*** 1145,1155 **** } } // Check for "(X << z ) >>> z" which simply zero-extends Node *shl = in(1); ! if( in1_op == Op_LShiftI && phase->type(shl->in(2)) == t2 ) return new AndINode( shl->in(1), phase->intcon(mask) ); return NULL; } --- 1145,1155 ---- } } // Check for "(X << z ) >>> z" which simply zero-extends Node *shl = in(1); ! if( in1_op == Opcodes::Op_LShiftI && phase->type(shl->in(2)) == t2 ) return new AndINode( shl->in(1), phase->intcon(mask) ); return NULL; }
*** 1248,1260 **** // Check for ((x << z) + Y) >>> z. Replace with x + con>>>z // The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z". // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<<Z) + Y) >>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); ! if( add->Opcode() == Op_AddL ) { Node *lshl = add->in(1); ! if( lshl->Opcode() == Op_LShiftL && phase->type(lshl->in(2)) == t2 ) { Node *y_z = phase->transform( new URShiftLNode(add->in(2),in(2)) ); Node *sum = phase->transform( new AddLNode( lshl->in(1), y_z ) ); return new AndLNode( sum, phase->longcon(mask) ); } --- 1248,1260 ---- // Check for ((x << z) + Y) >>> z. Replace with x + con>>>z // The idiom for rounding to a power of 2 is "(Q+(2^z-1)) >>> z". // If Q is "X << z" the rounding is useless. Look for patterns like // ((X<<Z) + Y) >>> Z and replace with (X + Y>>>Z) & Z-mask. Node *add = in(1); ! if( add->Opcode() == Opcodes::Op_AddL ) { Node *lshl = add->in(1); ! if( lshl->Opcode() == Opcodes::Op_LShiftL && phase->type(lshl->in(2)) == t2 ) { Node *y_z = phase->transform( new URShiftLNode(add->in(2),in(2)) ); Node *sum = phase->transform( new AddLNode( lshl->in(1), y_z ) ); return new AndLNode( sum, phase->longcon(mask) ); }
*** 1262,1272 **** // Check for (x & mask) >>> z. Replace with (x >>> z) & (mask >>> z) // This shortens the mask. Also, if we are extracting a high byte and // storing it to a buffer, the mask will be removed completely. Node *andi = in(1); ! if( andi->Opcode() == Op_AndL ) { const TypeLong *t3 = phase->type( andi->in(2) )->isa_long(); if( t3 && t3->is_con() ) { // Right input is a constant jlong mask2 = t3->get_con(); mask2 >>= con; // *signed* shift downward (high-order zeroes do not help) Node *newshr = phase->transform( new URShiftLNode(andi->in(1), in(2)) ); --- 1262,1272 ---- // Check for (x & mask) >>> z. Replace with (x >>> z) & (mask >>> z) // This shortens the mask. Also, if we are extracting a high byte and // storing it to a buffer, the mask will be removed completely. Node *andi = in(1); ! if( andi->Opcode() == Opcodes::Op_AndL ) { const TypeLong *t3 = phase->type( andi->in(2) )->isa_long(); if( t3 && t3->is_con() ) { // Right input is a constant jlong mask2 = t3->get_con(); mask2 >>= con; // *signed* shift downward (high-order zeroes do not help) Node *newshr = phase->transform( new URShiftLNode(andi->in(1), in(2)) );
*** 1274,1284 **** } } // Check for "(X << z ) >>> z" which simply zero-extends Node *shl = in(1); ! if( shl->Opcode() == Op_LShiftL && phase->type(shl->in(2)) == t2 ) return new AndLNode( shl->in(1), phase->longcon(mask) ); return NULL; } --- 1274,1284 ---- } } // Check for "(X << z ) >>> z" which simply zero-extends Node *shl = in(1); ! if( shl->Opcode() == Opcodes::Op_LShiftL && phase->type(shl->in(2)) == t2 ) return new AndLNode( shl->in(1), phase->longcon(mask) ); return NULL; }
< prev index next >