src/share/vm/opto/subnode.cpp
Print this page
*** 1205,1214 ****
--- 1205,1263 ----
phase->type( cmp1->in(2) )->higher_equal(TypeInt::SYMINT) ) {
Node *ncmp = phase->transform( new (phase->C) CmpINode(cmp1->in(2),cmp2));
return new (phase->C) BoolNode( ncmp, _test.commute() );
}
+ // Change ((x & m) u<= m) or ((m & x) u<= m) to always true
+ if ( cop == Op_CmpU &&
+ _test._test == BoolTest::le &&
+ cmp1->Opcode() == Op_AndI &&
+ (cmp1->in(2) == cmp2 || cmp1->in(1) == cmp2)) {
+ return ConINode::make(phase->C, 1);
+ }
+
+ // Change ((x & (m - 1)) u< m) into (m > 0)
+ // This is the off-by-one variant of the above
+ if ( cop == Op_CmpU &&
+ _test._test == BoolTest::lt &&
+ cmp1->Opcode() == Op_AndI) {
+ Node* l = cmp1->in(1);
+ Node* r = cmp1->in(2);
+ for (int repeat = 0; repeat < 2; repeat++) {
+ bool match = r->Opcode() == Op_AddI && r->in(2)->find_int_con(0) == -1 &&
+ r->in(1) == cmp2;
+ if (match) {
+ // arraylength known to be non-negative, so a (arraylength != 0) is sufficient,
+ // but to be compatible with the array range check pattern, use (arraylength u> 0)
+ Node* ncmp = cmp2->Opcode() == Op_LoadRange
+ ? phase->transform( new (phase->C) CmpUNode(cmp2, phase->intcon(0)))
+ : phase->transform( new (phase->C) CmpINode(cmp2, phase->intcon(0)));
+ return new (phase->C) BoolNode(ncmp, BoolTest::gt);
+ } else {
+ // commute and try again
+ l = cmp1->in(2);
+ r = cmp1->in(1);
+ }
+ }
+ }
+
+ // Change (arraylength <= 0) or (arraylength == 0)
+ // into (arraylength u<= 0)
+ // Also change (arraylength != 0) into (arraylength u> 0)
+ // The latter version matches the code pattern generated for
+ // array range checks, which will more likely be optimized later.
+ if ( cop == Op_CmpI &&
+ cmp1->Opcode() == Op_LoadRange &&
+ cmp2->find_int_con(-1) == 0) {
+ Node* ncmp = phase->transform( new (phase->C) CmpUNode(cmp1, cmp2));
+ if (_test._test == BoolTest::le || _test._test == BoolTest::eq) {
+ return new (phase->C) BoolNode(ncmp, BoolTest::le);
+ } else if (_test._test == BoolTest::ne) {
+ return new (phase->C) BoolNode(ncmp, BoolTest::gt);
+ }
+ }
+
// 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.