--- old/src/share/vm/opto/subnode.cpp 2014-02-12 15:42:10.000000000 -0800 +++ new/src/share/vm/opto/subnode.cpp 2014-02-12 15:42:10.000000000 -0800 @@ -1206,6 +1206,40 @@ Node *ncmp = phase->transform( new (phase->C) CmpINode(cmp1->in(2),cmp2)); return new (phase->C) BoolNode( ncmp, _test.commute() ); } + + // Change ((x & m) <= m) into (m >= 0) + // Integer expressions which perform bitwise and can be proven to + // be less than or equal to either operand, as long as the compared + // operand is non-negative. + if ( cop == Op_CmpI && + _test._test == BoolTest::le && + cmp1->Opcode() == Op_AndI && + cmp1->in(2) == cmp2) { + Node* ncmp = phase->transform( new (phase->C) CmpINode(cmp2, phase->intcon(0))); + return new (phase->C) BoolNode(ncmp, BoolTest::ge); + } + + // Change ((x & m) u<= m) to always true + if ( cop == Op_CmpU && + _test._test == BoolTest::le && + cmp1->Opcode() == Op_AndI && + cmp1->in(2) == cmp2) { + return ConINode::make(phase->C, 1); + } + + // Change ((x & m - 1) < m) or ((x & m - 1) u< m) into (m > 0) + // This is the off-by-one variant of the two patterns above + if ((cop == Op_CmpU || cop == Op_CmpI) && + _test._test == BoolTest::lt && + cmp1->Opcode() == Op_AndI && + (cmp1->in(2)->Opcode() == Op_AddI && cmp1->in(2)->in(2)->find_int_con(0) == -1 || + cmp1->in(2)->Opcode() == Op_SubI && cmp1->in(2)->in(2)->find_int_con(0) == 1) && + cmp1->in(2)->in(1) == cmp2) { + Node* ncmp = phase->transform( new (phase->C) CmpINode(cmp2, phase->intcon(0))); + return cmp2->Opcode() == Op_LoadRange + ? new (phase->C) BoolNode(ncmp, BoolTest::ne) // arraylength known to be non-negative + : 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.