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