src/share/vm/opto/subnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/share/vm/opto/subnode.cpp Thu Jul 31 14:08:59 2014
--- new/src/share/vm/opto/subnode.cpp Thu Jul 31 14:08:59 2014
*** 1294,1303 ****
--- 1294,1347 ----
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() );
}
+ // 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().
+ if((_test._test == BoolTest::eq || _test._test == BoolTest::ne) &&
+ (cmp1_op == Op_AddI || cmp1_op == Op_SubI)) {
+ // Skip cases were inputs of add/sub are not of integer type
+ const TypeInt* r0 = phase->type(cmp1->in(1))->isa_int();
+ const TypeInt* r1 = phase->type(cmp1->in(2))->isa_int();
+ if ((r0 != NULL) && (r1 != NULL)) {
+ // 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* t2 = phase->type(cmp2);
+ const Type* sub_tr1 = cmp->isa_Sub()->sub(tr1, t2);
+ const Type* sub_tr2 = cmp->isa_Sub()->sub(tr2, t2);
+ if ((sub_tr1 == TypeInt::CC_LT && sub_tr2 == TypeInt::CC_GT) ||
+ (sub_tr1 == TypeInt::CC_GT && sub_tr2 == TypeInt::CC_LT)) {
+ // 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(phase->C, (_test._test == BoolTest::eq) ? 0 : 1);
+ }
+ }
+ }
+ }
+
// 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.
src/share/vm/opto/subnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File