--- old/src/share/vm/opto/subnode.cpp 2014-02-14 14:47:30.000000000 -0800 +++ new/src/share/vm/opto/subnode.cpp 2014-02-14 14:47:30.000000000 -0800 @@ -1206,6 +1206,55 @@ 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.