Skip to content

Instantly share code, notes, and snippets.

@rednaxelafx
Last active April 8, 2018 02:10
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rednaxelafx/8964030 to your computer and use it in GitHub Desktop.
Save rednaxelafx/8964030 to your computer and use it in GitHub Desktop.
A quick-n-dirty patch to implement JDK-8003585: strength reduce or eliminate range checks for power-of-two sized arrays
diff -r 9d39e8a8ff61 src/share/vm/opto/subnode.cpp
--- a/src/share/vm/opto/subnode.cpp Fri Dec 27 07:51:07 2013 -0800
+++ b/src/share/vm/opto/subnode.cpp Wed Feb 12 14:59:00 2014 -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 phase->intcon(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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment