8230382: Clean up ConvI2L, CastII and CastLL::Ideal methods
Reviewed-by: thartmann, roland
This commit is contained in:
parent
efd3967b54
commit
06cadb36e0
src/hotspot/share/opto
@ -194,6 +194,40 @@ void ConstraintCastNode::dump_spec(outputStream *st) const {
|
||||
|
||||
const Type* CastIINode::Value(PhaseGVN* phase) const {
|
||||
const Type *res = ConstraintCastNode::Value(phase);
|
||||
if (res == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
assert(res->isa_int(), "res must be int");
|
||||
|
||||
// Similar to ConvI2LNode::Value() for the same reasons
|
||||
// see if we can remove type assertion after loop opts
|
||||
// But here we have to pay extra attention:
|
||||
// Do not narrow the type of range check dependent CastIINodes to
|
||||
// avoid corruption of the graph if a CastII is replaced by TOP but
|
||||
// the corresponding range check is not removed.
|
||||
if (!_range_check_dependency && phase->C->post_loop_opts_phase()) {
|
||||
const TypeInt* this_type = res->is_int();
|
||||
const TypeInt* in_type = phase->type(in(1))->isa_int();
|
||||
if (in_type != NULL &&
|
||||
(in_type->_lo != this_type->_lo ||
|
||||
in_type->_hi != this_type->_hi)) {
|
||||
jint lo1 = this_type->_lo;
|
||||
jint hi1 = this_type->_hi;
|
||||
int w1 = this_type->_widen;
|
||||
if (lo1 >= 0) {
|
||||
// Keep a range assertion of >=0.
|
||||
lo1 = 0; hi1 = max_jint;
|
||||
} else if (hi1 < 0) {
|
||||
// Keep a range assertion of <0.
|
||||
lo1 = min_jint; hi1 = -1;
|
||||
} else {
|
||||
lo1 = min_jint; hi1 = max_jint;
|
||||
}
|
||||
res = TypeInt::make(MAX2(in_type->_lo, lo1),
|
||||
MIN2(in_type->_hi, hi1),
|
||||
MAX2((int)in_type->_widen, w1));
|
||||
}
|
||||
}
|
||||
|
||||
// Try to improve the type of the CastII if we recognize a CmpI/If
|
||||
// pattern.
|
||||
@ -248,7 +282,6 @@ const Type* CastIINode::Value(PhaseGVN* phase) const {
|
||||
t = TypeInt::make(lo_int, hi_int, Type::WidenMax);
|
||||
|
||||
res = res->filter_speculative(t);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
@ -274,8 +307,11 @@ Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
if (progress != NULL) {
|
||||
return progress;
|
||||
}
|
||||
|
||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||
if (can_reshape && !_range_check_dependency && !phase->C->post_loop_opts_phase()) {
|
||||
// makes sure we run ::Value to potentially remove type assertion after loop opts
|
||||
phase->C->record_for_post_loop_opts_igvn(this);
|
||||
}
|
||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||
const TypeInt* this_type = this->type()->is_int();
|
||||
Node* z = in(1);
|
||||
const TypeInteger* rx = NULL;
|
||||
@ -300,43 +336,6 @@ Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
default: ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
// Similar to ConvI2LNode::Ideal() for the same reasons
|
||||
// Do not narrow the type of range check dependent CastIINodes to
|
||||
// avoid corruption of the graph if a CastII is replaced by TOP but
|
||||
// the corresponding range check is not removed.
|
||||
if (can_reshape && !_range_check_dependency) {
|
||||
if (phase->C->post_loop_opts_phase()) {
|
||||
const TypeInt* this_type = this->type()->is_int();
|
||||
const TypeInt* in_type = phase->type(in(1))->isa_int();
|
||||
if (in_type != NULL && this_type != NULL &&
|
||||
(in_type->_lo != this_type->_lo ||
|
||||
in_type->_hi != this_type->_hi)) {
|
||||
jint lo1 = this_type->_lo;
|
||||
jint hi1 = this_type->_hi;
|
||||
int w1 = this_type->_widen;
|
||||
|
||||
if (lo1 >= 0) {
|
||||
// Keep a range assertion of >=0.
|
||||
lo1 = 0; hi1 = max_jint;
|
||||
} else if (hi1 < 0) {
|
||||
// Keep a range assertion of <0.
|
||||
lo1 = min_jint; hi1 = -1;
|
||||
} else {
|
||||
lo1 = min_jint; hi1 = max_jint;
|
||||
}
|
||||
const TypeInt* wtype = TypeInt::make(MAX2(in_type->_lo, lo1),
|
||||
MIN2(in_type->_hi, hi1),
|
||||
MAX2((int)in_type->_widen, w1));
|
||||
if (wtype != type()) {
|
||||
set_type(wtype);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
phase->C->record_for_post_loop_opts_igvn(this);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -252,12 +252,47 @@ Node* ConvI2FNode::Identity(PhaseGVN* phase) {
|
||||
//------------------------------Value------------------------------------------
|
||||
const Type* ConvI2LNode::Value(PhaseGVN* phase) const {
|
||||
const Type *t = phase->type( in(1) );
|
||||
if( t == Type::TOP ) return Type::TOP;
|
||||
if (t == Type::TOP) {
|
||||
return Type::TOP;
|
||||
}
|
||||
const TypeInt *ti = t->is_int();
|
||||
const Type* tl = TypeLong::make(ti->_lo, ti->_hi, ti->_widen);
|
||||
// Join my declared type against my incoming type.
|
||||
tl = tl->filter(_type);
|
||||
return tl;
|
||||
if (!tl->isa_long()) {
|
||||
return tl;
|
||||
}
|
||||
const TypeLong* this_type = tl->is_long();
|
||||
// Do NOT remove this node's type assertion until no more loop ops can happen.
|
||||
if (phase->C->post_loop_opts_phase()) {
|
||||
const TypeInt* in_type = phase->type(in(1))->isa_int();
|
||||
if (in_type != NULL &&
|
||||
(in_type->_lo != this_type->_lo ||
|
||||
in_type->_hi != this_type->_hi)) {
|
||||
// Although this WORSENS the type, it increases GVN opportunities,
|
||||
// because I2L nodes with the same input will common up, regardless
|
||||
// of slightly differing type assertions. Such slight differences
|
||||
// arise routinely as a result of loop unrolling, so this is a
|
||||
// post-unrolling graph cleanup. Choose a type which depends only
|
||||
// on my input. (Exception: Keep a range assertion of >=0 or <0.)
|
||||
jlong lo1 = this_type->_lo;
|
||||
jlong hi1 = this_type->_hi;
|
||||
int w1 = this_type->_widen;
|
||||
if (lo1 >= 0) {
|
||||
// Keep a range assertion of >=0.
|
||||
lo1 = 0; hi1 = max_jint;
|
||||
} else if (hi1 < 0) {
|
||||
// Keep a range assertion of <0.
|
||||
lo1 = min_jint; hi1 = -1;
|
||||
} else {
|
||||
lo1 = min_jint; hi1 = max_jint;
|
||||
}
|
||||
return TypeLong::make(MAX2((jlong)in_type->_lo, lo1),
|
||||
MIN2((jlong)in_type->_hi, hi1),
|
||||
MAX2((int)in_type->_widen, w1));
|
||||
}
|
||||
}
|
||||
return this_type;
|
||||
}
|
||||
|
||||
static inline bool long_ranges_overlap(jlong lo1, jlong hi1,
|
||||
@ -359,52 +394,10 @@ bool Compile::push_thru_add(PhaseGVN* phase, Node* z, const TypeInteger* tz, con
|
||||
|
||||
//------------------------------Ideal------------------------------------------
|
||||
Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
PhaseIterGVN *igvn = phase->is_IterGVN();
|
||||
const TypeLong* this_type = this->type()->is_long();
|
||||
Node* this_changed = NULL;
|
||||
|
||||
if (igvn != NULL) {
|
||||
// Do NOT remove this node's type assertion until no more loop ops can happen.
|
||||
if (phase->C->post_loop_opts_phase()) {
|
||||
const TypeInt* in_type = phase->type(in(1))->isa_int();
|
||||
if (in_type != NULL && this_type != NULL &&
|
||||
(in_type->_lo != this_type->_lo ||
|
||||
in_type->_hi != this_type->_hi)) {
|
||||
// Although this WORSENS the type, it increases GVN opportunities,
|
||||
// because I2L nodes with the same input will common up, regardless
|
||||
// of slightly differing type assertions. Such slight differences
|
||||
// arise routinely as a result of loop unrolling, so this is a
|
||||
// post-unrolling graph cleanup. Choose a type which depends only
|
||||
// on my input. (Exception: Keep a range assertion of >=0 or <0.)
|
||||
jlong lo1 = this_type->_lo;
|
||||
jlong hi1 = this_type->_hi;
|
||||
int w1 = this_type->_widen;
|
||||
if (lo1 != (jint)lo1 ||
|
||||
hi1 != (jint)hi1 ||
|
||||
lo1 > hi1) {
|
||||
// Overflow leads to wraparound, wraparound leads to range saturation.
|
||||
lo1 = min_jint; hi1 = max_jint;
|
||||
} else if (lo1 >= 0) {
|
||||
// Keep a range assertion of >=0.
|
||||
lo1 = 0; hi1 = max_jint;
|
||||
} else if (hi1 < 0) {
|
||||
// Keep a range assertion of <0.
|
||||
lo1 = min_jint; hi1 = -1;
|
||||
} else {
|
||||
lo1 = min_jint; hi1 = max_jint;
|
||||
}
|
||||
const TypeLong* wtype = TypeLong::make(MAX2((jlong)in_type->_lo, lo1),
|
||||
MIN2((jlong)in_type->_hi, hi1),
|
||||
MAX2((int)in_type->_widen, w1));
|
||||
if (wtype != type()) {
|
||||
set_type(wtype);
|
||||
// Note: this_type still has old type value, for the logic below.
|
||||
this_changed = this;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
phase->C->record_for_post_loop_opts_igvn(this);
|
||||
}
|
||||
if (can_reshape && !phase->C->post_loop_opts_phase()) {
|
||||
// makes sure we run ::Value to potentially remove type assertion after loop opts
|
||||
phase->C->record_for_post_loop_opts_igvn(this);
|
||||
}
|
||||
#ifdef _LP64
|
||||
// Convert ConvI2L(AddI(x, y)) to AddL(ConvI2L(x), ConvI2L(y))
|
||||
@ -428,7 +421,7 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
// possible before the I2L conversion, because 32-bit math is cheaper.
|
||||
// There's no common reason to "leak" a constant offset through the I2L.
|
||||
// Addressing arithmetic will not absorb it as part of a 64-bit AddL.
|
||||
|
||||
PhaseIterGVN* igvn = phase->is_IterGVN();
|
||||
Node* z = in(1);
|
||||
const TypeInteger* rx = NULL;
|
||||
const TypeInteger* ry = NULL;
|
||||
@ -437,7 +430,7 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
// Postpone this optimization to iterative GVN, where we can handle deep
|
||||
// AddI chains without an exponential number of recursive Ideal() calls.
|
||||
phase->record_for_igvn(this);
|
||||
return this_changed;
|
||||
return NULL;
|
||||
}
|
||||
int op = z->Opcode();
|
||||
Node* x = z->in(1);
|
||||
@ -453,7 +446,7 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
||||
}
|
||||
#endif //_LP64
|
||||
|
||||
return this_changed;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
Loading…
x
Reference in New Issue
Block a user