5057225: Remove useless I2L conversions

The optimizer should be told to normalize (AndL (ConvI2L x) 0xFF) to (ConvI2L (AndI x 0xFF)), and then the existing matcher rule will work for free.

Reviewed-by: kvn
This commit is contained in:
Christian Thalinger 2009-06-26 07:26:10 -07:00
parent 8f6070ce0e
commit a9ad90fa87
5 changed files with 541 additions and 59 deletions

View file

@ -430,31 +430,28 @@ Node *AndINode::Identity( PhaseTransform *phase ) {
// x & x => x
if (phase->eqv(in(1), in(2))) return in(1);
Node *load = in(1);
const TypeInt *t2 = phase->type( in(2) )->isa_int();
if( t2 && t2->is_con() ) {
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();
if (t1 != NULL && t1->_lo >= 0) {
jint t1_support = ((jint)1 << (1 + log2_intptr(t1->_hi))) - 1;
jint t1_support = right_n_bits(1 + log2_intptr(t1->_hi));
if ((t1_support & con) == t1_support)
return load;
return in1;
}
uint lop = load->Opcode();
if( lop == Op_LoadUS &&
con == 0x0000FFFF ) // Already zero-extended
return load;
// Masking off the high bits of a unsigned-shift-right is not
// needed either.
if( lop == Op_URShiftI ) {
const TypeInt *t12 = phase->type( load->in(2) )->isa_int();
if( t12 && t12->is_con() ) { // Shift is by a constant
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;
if( (mask&con) == mask ) // If AND is useless, skip it
return load;
if ((mask & con) == mask) // If AND is useless, skip it
return in1;
}
}
}
@ -476,26 +473,17 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) {
return new (phase->C, 3) AndINode(load,phase->intcon(mask&0xFFFF));
// Masking bits off of a Short? Loading a Character does some masking
if( lop == Op_LoadS &&
(mask & 0xFFFF0000) == 0 ) {
if (lop == Op_LoadS && (mask & 0xFFFF0000) == 0 ) {
Node *ldus = new (phase->C, 3) LoadUSNode(load->in(MemNode::Control),
load->in(MemNode::Memory),
load->in(MemNode::Address),
load->adr_type());
load->in(MemNode::Memory),
load->in(MemNode::Address),
load->adr_type());
ldus = phase->transform(ldus);
return new (phase->C, 3) AndINode(ldus, phase->intcon(mask&0xFFFF));
return new (phase->C, 3) AndINode(ldus, phase->intcon(mask & 0xFFFF));
}
// Masking sign bits off of a Byte? Do an unsigned byte load.
if (lop == Op_LoadB && mask == 0x000000FF) {
return new (phase->C, 3) LoadUBNode(load->in(MemNode::Control),
load->in(MemNode::Memory),
load->in(MemNode::Address),
load->adr_type());
}
// Masking sign bits off of a Byte plus additional lower bits? Do
// an unsigned byte load plus an and.
// Masking sign bits off of a Byte? Do an unsigned byte load plus
// an and.
if (lop == Op_LoadB && (mask & 0xFFFFFF00) == 0) {
Node* ldub = new (phase->C, 3) LoadUBNode(load->in(MemNode::Control),
load->in(MemNode::Memory),
@ -605,8 +593,13 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* in1 = in(1);
uint op = in1->Opcode();
// Masking sign bits off of an integer? Do an unsigned integer to long load.
if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == 0x00000000FFFFFFFFL) {
// Masking sign bits off of an integer? Do an unsigned integer to
// long load.
// NOTE: This check must be *before* we try to convert the AndLNode
// to an AndINode and commute it with ConvI2LNode because
// 0xFFFFFFFFL masks the whole integer and we get a sign extension,
// which is wrong.
if (op == Op_ConvI2L && in1->in(1)->Opcode() == Op_LoadI && mask == CONST64(0x00000000FFFFFFFF)) {
Node* load = in1->in(1);
return new (phase->C, 3) LoadUI2LNode(load->in(MemNode::Control),
load->in(MemNode::Memory),
@ -614,9 +607,22 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
load->adr_type());
}
// 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.
if (op == Op_ConvI2L && (mask & CONST64(0xFFFFFFFF00000000)) == 0) {
// If we are doing an UI2L conversion (i.e. the mask is
// 0x00000000FFFFFFFF) we cannot convert the AndL to an AndI
// because the AndI would be optimized away later in Identity.
if (mask != CONST64(0x00000000FFFFFFFF)) {
Node* andi = new (phase->C, 3) AndINode(in1->in(1), phase->intcon(mask));
andi = phase->transform(andi);
return new (phase->C, 2) ConvI2LNode(andi);
}
}
// Masking off sign bits? Dont make them!
if (op == Op_RShiftL) {
const TypeInt *t12 = phase->type(in1->in(2))->isa_int();
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
@ -626,7 +632,7 @@ Node *AndLNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if( (sign_bits_mask & mask) == 0 ) {
// Use zero-fill shift instead
Node *zshift = phase->transform(new (phase->C, 3) URShiftLNode(in1->in(1), in1->in(2)));
return new (phase->C, 3) AndLNode( zshift, in(2) );
return new (phase->C, 3) AndLNode(zshift, in(2));
}
}
}