src/share/vm/opto/subnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Cdiff src/share/vm/opto/subnode.cpp

src/share/vm/opto/subnode.cpp

Print this page
rev 9116 : 8003585: strength reduce or eliminate range checks for power-of-two sized arrays
Summary: change ((x & m) u<= m) to always true and ((x & (m - 1)) u< m) into (m > 0)
Reviewed-by:

*** 1332,1341 **** --- 1332,1399 ---- _test._test == BoolTest::ne) ) { 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 + // 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(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) { + 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. Node *c2b = cmp1; if( cmp2_type == TypeInt::ZERO && cmp1_op == Op_Conv2B &&
src/share/vm/opto/subnode.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File