diff -r ca593686a4f0 src/share/vm/opto/subnode.cpp --- a/src/share/vm/opto/subnode.cpp Fri Jul 31 12:42:12 2015 +0200 +++ b/src/share/vm/opto/subnode.cpp Fri Jul 31 13:33:36 2015 +0200 @@ -1302,6 +1302,55 @@ Node *ncmp = phase->transform(new CmpINode(j_xor->in(1),cmp2)); return new BoolNode( ncmp, _test.negate() ); } + + // 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(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) { + Node* ncmp = phase->transform( new CmpUNode(cmp1, cmp2)); + if (_test._test == BoolTest::le || _test._test == BoolTest::eq) { + return new BoolNode(ncmp, BoolTest::le); + } else if (_test._test == BoolTest::ne) { + 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.