# HG changeset patch # User kvn # Date 1277747570 25200 # Node ID d678e327704837faf5f4c58567c8326abb10ea35 # Parent 5f249b39009408720bb1ba1d71e40621fb63e243 6964479: widen normalization of small int and long values should be symmetric Summary: normalize widen value in xmeet() and xdual() methods for types Int and Long so the type meet will be symmetric. Reviewed-by: jrose diff -r 5f249b390094 -r d678e3277048 src/share/vm/opto/type.cpp --- a/src/share/vm/opto/type.cpp Wed Jun 23 09:40:11 2010 -0700 +++ b/src/share/vm/opto/type.cpp Mon Jun 28 10:52:50 2010 -0700 @@ -182,6 +182,8 @@ return t->hash(); } +#define SMALLINT ((juint)3) // a value too insignificant to consider widening + //--------------------------Initialize_shared---------------------------------- void Type::Initialize_shared(Compile* current) { // This method does not need to be locked because the first system @@ -240,6 +242,7 @@ assert( TypeInt::CC_GT == TypeInt::ONE, "types must match for CmpL to work" ); assert( TypeInt::CC_EQ == TypeInt::ZERO, "types must match for CmpL to work" ); assert( TypeInt::CC_GE == TypeInt::BOOL, "types must match for CmpL to work" ); + assert( (juint)(TypeInt::CC->_hi - TypeInt::CC->_lo) <= SMALLINT, "CC is truly small"); TypeLong::MINUS_1 = TypeLong::make(-1); // -1 TypeLong::ZERO = TypeLong::make( 0); // 0 @@ -1054,16 +1057,21 @@ return (TypeInt*)(new TypeInt(lo,lo,WidenMin))->hashcons(); } -#define SMALLINT ((juint)3) // a value too insignificant to consider widening - -const TypeInt *TypeInt::make( jint lo, jint hi, int w ) { +static int normalize_int_widen( jint lo, jint hi, int w ) { // Certain normalizations keep us sane when comparing types. // The 'SMALLINT' covers constants and also CC and its relatives. - assert(CC == NULL || (juint)(CC->_hi - CC->_lo) <= SMALLINT, "CC is truly small"); if (lo <= hi) { - if ((juint)(hi - lo) <= SMALLINT) w = Type::WidenMin; - if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // plain int + if ((juint)(hi - lo) <= SMALLINT) w = Type::WidenMin; + if ((juint)(hi - lo) >= max_juint) w = Type::WidenMax; // TypeInt::INT + } else { + if ((juint)(lo - hi) <= SMALLINT) w = Type::WidenMin; + if ((juint)(lo - hi) >= max_juint) w = Type::WidenMin; // dual TypeInt::INT } + return w; +} + +const TypeInt *TypeInt::make( jint lo, jint hi, int w ) { + w = normalize_int_widen(lo, hi, w); return (TypeInt*)(new TypeInt(lo,hi,w))->hashcons(); } @@ -1103,14 +1111,14 @@ // Expand covered set const TypeInt *r = t->is_int(); - // (Avoid TypeInt::make, to avoid the argument normalizations it enforces.) - return (new TypeInt( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons(); + return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ); } //------------------------------xdual------------------------------------------ // Dual: reverse hi & lo; flip widen const Type *TypeInt::xdual() const { - return new TypeInt(_hi,_lo,WidenMax-_widen); + int w = normalize_int_widen(_hi,_lo, WidenMax-_widen); + return new TypeInt(_hi,_lo,w); } //------------------------------widen------------------------------------------ @@ -1202,7 +1210,7 @@ //-----------------------------filter------------------------------------------ const Type *TypeInt::filter( const Type *kills ) const { const TypeInt* ft = join(kills)->isa_int(); - if (ft == NULL || ft->_lo > ft->_hi) + if (ft == NULL || ft->empty()) return Type::TOP; // Canonical empty value if (ft->_widen < this->_widen) { // Do not allow the value of kill->_widen to affect the outcome. @@ -1304,13 +1312,21 @@ return (TypeLong*)(new TypeLong(lo,lo,WidenMin))->hashcons(); } -const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) { +static int normalize_long_widen( jlong lo, jlong hi, int w ) { // Certain normalizations keep us sane when comparing types. - // The '1' covers constants. + // The 'SMALLINT' covers constants. if (lo <= hi) { - if ((julong)(hi - lo) <= SMALLINT) w = Type::WidenMin; - if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // plain long + if ((julong)(hi - lo) <= SMALLINT) w = Type::WidenMin; + if ((julong)(hi - lo) >= max_julong) w = Type::WidenMax; // TypeLong::LONG + } else { + if ((julong)(lo - hi) <= SMALLINT) w = Type::WidenMin; + if ((julong)(lo - hi) >= max_julong) w = Type::WidenMin; // dual TypeLong::LONG } + return w; +} + +const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) { + w = normalize_long_widen(lo, hi, w); return (TypeLong*)(new TypeLong(lo,hi,w))->hashcons(); } @@ -1351,14 +1367,14 @@ // Expand covered set const TypeLong *r = t->is_long(); // Turn into a TypeLong - // (Avoid TypeLong::make, to avoid the argument normalizations it enforces.) - return (new TypeLong( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ))->hashcons(); + return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ); } //------------------------------xdual------------------------------------------ // Dual: reverse hi & lo; flip widen const Type *TypeLong::xdual() const { - return new TypeLong(_hi,_lo,WidenMax-_widen); + int w = normalize_long_widen(_hi,_lo, WidenMax-_widen); + return new TypeLong(_hi,_lo,w); } //------------------------------widen------------------------------------------ @@ -1453,7 +1469,7 @@ //-----------------------------filter------------------------------------------ const Type *TypeLong::filter( const Type *kills ) const { const TypeLong* ft = join(kills)->isa_long(); - if (ft == NULL || ft->_lo > ft->_hi) + if (ft == NULL || ft->empty()) return Type::TOP; // Canonical empty value if (ft->_widen < this->_widen) { // Do not allow the value of kill->_widen to affect the outcome.