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 Tue Aug 5 09:48:32 2014
--- new/src/share/vm/opto/subnode.cpp Tue Aug 5 09:48:32 2014
*** 1201,1210 ****
--- 1201,1258 ----
BoolNode* BoolNode::negate(PhaseGVN* phase) {
Compile* C = phase->C;
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, Node* cmp, Node* cmp1, Node* cmp2,
+ 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->as_Sub()->sub(tr1, cmp2_type);
+ const Type* sub_tr2 = cmp->as_Sub()->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(phase->C, (_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.
*** 1294,1303 ****
--- 1342,1354 ----
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, cmp1, cmp2, 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.
*** 1338,1349 ****
--- 1389,1398 ----
// 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.
src/share/vm/opto/subnode.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File