--- a/hotspot/src/share/vm/opto/subnode.cpp Mon Feb 01 19:45:26 2016 +0300
+++ b/hotspot/src/share/vm/opto/subnode.cpp Tue Jan 19 14:52:33 2016 +0100
@@ -1334,6 +1334,65 @@
return new BoolNode( ncmp, _test.negate() );
}
+ // Change ((x & m) u<= m) or ((m & x) u<= m) to always true
+ // Same with ((x & m) u< m+1) and ((m & x) u< m+1)
+ if (cop == Op_CmpU &&
+ cmp1->Opcode() == Op_AndI) {
+ Node* bound = NULL;
+ if (_test._test == BoolTest::le) {
+ bound = cmp2;
+ } else if (_test._test == BoolTest::lt &&
+ cmp2->Opcode() == Op_AddI &&
+ cmp2->in(2)->find_int_con(0) == 1) {
+ bound = cmp2->in(1);
+ }
+ if (cmp1->in(2) == bound || cmp1->in(1) == bound) {
+ return ConINode::make(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 CmpUNode(cmp2, phase->intcon(0)))
+ : phase->transform(new CmpINode(cmp2, phase->intcon(0)));
+ return new 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) {
+ if (_test._test == BoolTest::le || _test._test == BoolTest::eq) {
+ Node* ncmp = phase->transform(new CmpUNode(cmp1, cmp2));
+ return new BoolNode(ncmp, BoolTest::le);
+ } else if (_test._test == BoolTest::ne) {
+ Node* ncmp = phase->transform(new CmpUNode(cmp1, cmp2));
+ return new BoolNode(ncmp, BoolTest::gt);
+ }
+ }
+
// Change "bool eq/ne (cmp (Conv2B X) 0)" into "bool eq/ne (cmp X 0)".
// This is a standard idiom for branching on a boolean value.
Node *c2b = cmp1;
@@ -1496,4 +1555,3 @@
double d = t1->getd();
return TypeD::make( StubRoutines::intrinsic_log10( d ) );
}
-