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

src/share/vm/opto/subnode.cpp

Print this page

        

*** 1199,1208 **** --- 1199,1256 ---- //----------------------------------negate------------------------------------- BoolNode* BoolNode::negate(PhaseGVN* phase) { return new BoolNode(in(1), _test.negate()); } + // Change "bool eq/ne (cmp (add/sub A B) C)" into false/true if add/sub + // overflows and we can prove that C is not in the two resulting ranges. + // This optimization is similar to the one performed by CmpUNode::Value(). + Node* BoolNode::fold_cmpI(PhaseGVN* phase, SubNode* cmp, Node* cmp1, int cmp_op, + int cmp1_op, const TypeInt* cmp2_type) { + // Only optimize eq/ne integer comparison of add/sub + if((_test._test == BoolTest::eq || _test._test == BoolTest::ne) && + (cmp_op == Op_CmpI) && (cmp1_op == Op_AddI || cmp1_op == Op_SubI)) { + // Skip cases were inputs of add/sub are not integers or of bottom type + const TypeInt* r0 = phase->type(cmp1->in(1))->isa_int(); + const TypeInt* r1 = phase->type(cmp1->in(2))->isa_int(); + if ((r0 != NULL) && (r0 != TypeInt::INT) && + (r1 != NULL) && (r1 != TypeInt::INT) && + (cmp2_type != TypeInt::INT)) { + // Compute exact (long) type range of add/sub result + jlong lo_long = r0->_lo; + jlong hi_long = r0->_hi; + if (cmp1_op == Op_AddI) { + lo_long += r1->_lo; + hi_long += r1->_hi; + } else { + lo_long -= r1->_hi; + hi_long -= r1->_lo; + } + // Check for over-/underflow by casting to integer + int lo_int = (int)lo_long; + int hi_int = (int)hi_long; + bool underflow = lo_long != (jlong)lo_int; + bool overflow = hi_long != (jlong)hi_int; + if ((underflow != overflow) && (hi_int < lo_int)) { + // Overflow on one boundary, compute resulting type ranges: + // tr1 [MIN_INT, hi_int] and tr2 [lo_int, MAX_INT] + int w = MAX2(r0->_widen, r1->_widen); // _widen does not matter here + const TypeInt* tr1 = TypeInt::make(min_jint, hi_int, w); + const TypeInt* tr2 = TypeInt::make(lo_int, max_jint, w); + // Compare second input of cmp to both type ranges + const Type* sub_tr1 = cmp->sub(tr1, cmp2_type); + const Type* sub_tr2 = cmp->sub(tr2, cmp2_type); + if (sub_tr1 == TypeInt::CC_LT && sub_tr2 == TypeInt::CC_GT) { + // The result of the add/sub will never equal cmp2. Replace BoolNode + // by false (0) if it tests for equality and by true (1) otherwise. + return ConINode::make((_test._test == BoolTest::eq) ? 0 : 1); + } + } + } + } + return NULL; + } //------------------------------Ideal------------------------------------------ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Change "bool tst (cmp con x)" into "bool ~tst (cmp x con)". // This moves the constant to the right. Helps value-numbering.
*** 1292,1301 **** --- 1340,1352 ---- phase->type( cmp1->in(2) )->higher_equal(TypeInt::SYMINT) ) { Node *ncmp = phase->transform( new CmpINode(cmp1->in(2),cmp2)); return new BoolNode( ncmp, _test.commute() ); } + // Try to optimize signed integer comparison + return fold_cmpI(phase, cmp->as_Sub(), cmp1, cop, cmp1_op, cmp2_type); + // The transformation below is not valid for either signed or unsigned // comparisons due to wraparound concerns at MAX_VALUE and MIN_VALUE. // This transformation can be resurrected when we are able to // make inferences about the range of values being subtracted from // (or added to) relative to the wraparound point.
*** 1336,1347 **** // return clone_cmp( cmp, cmp1->in(1), cmp2, phase, BoolTest::le ); // else if( cmp2_op == Op_AddI && // phase->type( cmp2->in(2) ) == TypeInt::ONE ) // return clone_cmp( cmp, cmp1, cmp2->in(1), phase, BoolTest::le ); // } - - return NULL; } //------------------------------Value------------------------------------------ // Simplify a Bool (convert condition codes to boolean (1 or 0)) node, // based on local information. If the input is constant, do it. --- 1387,1396 ----
src/share/vm/opto/subnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File