src/share/vm/opto/subnode.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File
*** old/src/share/vm/opto/subnode.cpp	Wed May 14 16:33:39 2014
--- new/src/share/vm/opto/subnode.cpp	Wed May 14 16:33:39 2014

*** 78,88 **** --- 78,88 ---- return ( phase->type( in(2) )->higher_equal( zero ) ) ? in(1) : this; } //------------------------------Value------------------------------------------ // A subtract node differences it's two inputs. ! const Type *SubNode::Value( PhaseTransform *phase ) const { ! const Type* SubNode::Value_common(PhaseTransform *phase) const { const Node* in1 = in(1); const Node* in2 = in(2); // Either input is TOP ==> the result is TOP const Type* t1 = (in1 == this) ? Type::TOP : phase->type(in1); if( t1 == Type::TOP ) return Type::TOP;
*** 95,104 **** --- 95,114 ---- // Either input is BOTTOM ==> the result is the local BOTTOM if( t1 == Type::BOTTOM || t2 == Type::BOTTOM ) return bottom_type(); + return NULL; + } + + const Type* SubNode::Value(PhaseTransform *phase) const { + const Type* t = Value_common(phase); + if (t != NULL) { + return t; + } + const Type* t1 = phase->type(in(1)); + const Type* t2 = phase->type(in(2)); return sub(t1,t2); // Local flavor of type subtraction } //=============================================================================
*** 568,577 **** --- 578,659 ---- if ((jint)lo0 >= 0 && (jint)lo1 >= 0 && is_index_range_check()) return TypeInt::CC_LT; return TypeInt::CC; // else use worst case results } + const Type* CmpUNode::Value(PhaseTransform *phase) const { + const Type* t = SubNode::Value_common(phase); + if (t != NULL) { + return t; + } + const Node* in1 = in(1); + const Node* in2 = in(2); + const Type* t1 = phase->type(in1); + const Type* t2 = phase->type(in2); + assert(t1->isa_int(), "CmpU has only Int type inputs"); + if (t2 == TypeInt::INT) { // Compare to bottom? + return bottom_type(); + } + uint in1_op = in1->Opcode(); + if (in1_op == Op_AddI || in1_op == Op_SubI) { + // The problem rise when result of AddI(SubI) may overflow + // signed integer value. Let say the input type is + // [256, maxint] then +128 will create 2 ranges due to + // overflow: [minint, minint+127] and [384, maxint]. + // But C2 type system keep only 1 type range and as result + // it use general [minint, maxint] for this case which we + // can't optimize. + // + // Make 2 separate type ranges based on types of AddI(SubI) inputs + // and compare results of their compare. If results are the same + // CmpU node can be optimized. + const Node* in11 = in1->in(1); + const Node* in12 = in1->in(2); + const Type* t11 = (in11 == in1) ? Type::TOP : phase->type(in11); + const Type* t12 = (in12 == in1) ? Type::TOP : phase->type(in12); + // Skip cases when input types are top or bottom. + if ((t11 != Type::TOP) && (t11 != TypeInt::INT) && + (t12 != Type::TOP) && (t12 != TypeInt::INT)) { + const TypeInt *r0 = t11->is_int(); + const TypeInt *r1 = t12->is_int(); + jlong lo0 = r0->_lo; + jlong hi0 = r0->_hi; + jlong lo1 = r1->_lo; + jlong hi1 = r1->_hi; + if (in1_op == Op_SubI) { + jlong tmp = hi1; + hi1 = -lo1; + lo1 = -tmp; + } + jlong lol = lo0 + lo1; + jlong hil = hi0 + hi1; + bool underflow = lol != (int)lol; + bool overflow = hil != (int)hil; + // Use sub(t1, t2) when there is no overflow (one type range) + // or when both overflow and underflow (too complex). + if (underflow != overflow) { + // Overflow only on one boundary, compare 2 type ranges. + int lo_r1 = min_jint; + int hi_r1 = (int)hil; + int lo_r2 = (int)lol; + int hi_r2 = max_jint; + + int w = MAX2(r0->_widen, r1->_widen); // _widen does not matter here + const TypeInt* tr1 = TypeInt::make(lo_r1, hi_r1, w); + const TypeInt* tr2 = TypeInt::make(lo_r2, hi_r2, w); + const Type* cmp1 = sub(tr1, t2); + const Type* cmp2 = sub(tr2, t2); + if (cmp1 == cmp2) { + return cmp1; // Hit! + } + } + } + } + + return sub(t1, t2); // Local flavor of type subtraction + } + bool CmpUNode::is_index_range_check() const { // Check for the "(X ModI Y) CmpU Y" shape return (in(1)->Opcode() == Op_ModI && in(1)->in(2)->eqv_uncast(in(2))); }

src/share/vm/opto/subnode.cpp
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File