summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/458-checker-instruction-simplification/smali/SmaliTests.smali136
-rw-r--r--test/458-checker-instruction-simplification/src/Main.java122
-rw-r--r--test/530-checker-loops1/src/Main.java36
-rw-r--r--test/530-checker-loops2/src/Main.java133
4 files changed, 404 insertions, 23 deletions
diff --git a/test/458-checker-instruction-simplification/smali/SmaliTests.smali b/test/458-checker-instruction-simplification/smali/SmaliTests.smali
index ede599b213..6845961f39 100644
--- a/test/458-checker-instruction-simplification/smali/SmaliTests.smali
+++ b/test/458-checker-instruction-simplification/smali/SmaliTests.smali
@@ -191,3 +191,139 @@
.end method
+## CHECK-START: int SmaliTests.AddSubConst(int) instruction_simplifier (before)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<Const7:i\d+>> IntConstant 7
+## CHECK-DAG: <<Const8:i\d+>> IntConstant 8
+## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const7>>]
+## CHECK-DAG: <<Sub:i\d+>> Sub [<<Add>>,<<Const8>>]
+## CHECK-DAG: Return [<<Sub>>]
+
+## CHECK-START: int SmaliTests.AddSubConst(int) instruction_simplifier (after)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1
+## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<ConstM1>>]
+## CHECK-DAG: Return [<<Add>>]
+
+.method public static AddSubConst(I)I
+ .registers 3
+
+ .prologue
+ add-int/lit8 v0, p0, 7
+
+ const/16 v1, 8
+
+ sub-int v0, v0, v1
+
+ return v0
+.end method
+
+## CHECK-START: int SmaliTests.SubAddConst(int) instruction_simplifier (before)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+## CHECK-DAG: <<Const4:i\d+>> IntConstant 4
+## CHECK-DAG: <<Sub:i\d+>> Sub [<<ArgValue>>,<<Const3>>]
+## CHECK-DAG: <<Add:i\d+>> Add [<<Sub>>,<<Const4>>]
+## CHECK-DAG: Return [<<Add>>]
+
+## CHECK-START: int SmaliTests.SubAddConst(int) instruction_simplifier (after)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const1>>]
+## CHECK-DAG: Return [<<Add>>]
+
+.method public static SubAddConst(I)I
+ .registers 2
+
+ .prologue
+ const/4 v0, 3
+
+ sub-int v0, p0, v0
+
+ add-int/lit8 v0, v0, 4
+
+ return v0
+.end method
+
+## CHECK-START: int SmaliTests.SubSubConst1(int) instruction_simplifier (before)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<Const9:i\d+>> IntConstant 9
+## CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+## CHECK-DAG: <<Sub1:i\d+>> Sub [<<ArgValue>>,<<Const9>>]
+## CHECK-DAG: <<Sub2:i\d+>> Sub [<<Sub1>>,<<Const10>>]
+## CHECK-DAG: Return [<<Sub2>>]
+
+## CHECK-START: int SmaliTests.SubSubConst1(int) instruction_simplifier (after)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<ConstM19:i\d+>> IntConstant -19
+## CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<ConstM19>>]
+## CHECK-DAG: Return [<<Add>>]
+
+.method public static SubSubConst1(I)I
+ .registers 3
+
+ .prologue
+ const/16 v1, 9
+
+ sub-int v0, p0, v1
+
+ const/16 v1, 10
+
+ sub-int v0, v0, v1
+
+ return v0
+.end method
+
+## CHECK-START: int SmaliTests.SubSubConst2(int) instruction_simplifier (before)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<Const11:i\d+>> IntConstant 11
+## CHECK-DAG: <<Const12:i\d+>> IntConstant 12
+## CHECK-DAG: <<Sub1:i\d+>> Sub [<<Const11>>,<<ArgValue>>]
+## CHECK-DAG: <<Sub2:i\d+>> Sub [<<Sub1>>,<<Const12>>]
+## CHECK-DAG: Return [<<Sub2>>]
+
+## CHECK-START: int SmaliTests.SubSubConst2(int) instruction_simplifier (after)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<ConstM1:i\d+>> IntConstant -1
+## CHECK-DAG: <<Sub:i\d+>> Sub [<<ConstM1>>,<<ArgValue>>]
+## CHECK-DAG: Return [<<Sub>>]
+
+.method public static SubSubConst2(I)I
+ .registers 3
+
+ .prologue
+ rsub-int/lit8 v0, p0, 11
+
+ const/16 v1, 12
+
+ sub-int v0, v0, v1
+
+ return v0
+.end method
+
+## CHECK-START: int SmaliTests.SubSubConst3(int) instruction_simplifier (before)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<Const15:i\d+>> IntConstant 15
+## CHECK-DAG: <<Const16:i\d+>> IntConstant 16
+## CHECK-DAG: <<Sub1:i\d+>> Sub [<<ArgValue>>,<<Const16>>]
+## CHECK-DAG: <<Sub2:i\d+>> Sub [<<Const15>>,<<Sub1>>]
+## CHECK-DAG: Return [<<Sub2>>]
+
+## CHECK-START: int SmaliTests.SubSubConst3(int) instruction_simplifier (after)
+## CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+## CHECK-DAG: <<Const31:i\d+>> IntConstant 31
+## CHECK-DAG: <<Sub:i\d+>> Sub [<<Const31>>,<<ArgValue>>]
+## CHECK-DAG: Return [<<Sub>>]
+
+.method public static SubSubConst3(I)I
+ .registers 2
+
+ .prologue
+ const/16 v0, 16
+
+ sub-int v0, p0, v0
+
+ rsub-int/lit8 v0, v0, 15
+
+ return v0
+.end method
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index ffce49d2e1..c717eaa85e 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -78,6 +78,29 @@ public class Main {
return 0 + arg;
}
+ /// CHECK-START: int Main.$noinline$AddAddSubAddConst(int) instruction_simplifier (before)
+ /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+ /// CHECK-DAG: <<ConstM3:i\d+>> IntConstant -3
+ /// CHECK-DAG: <<Const4:i\d+>> IntConstant 4
+ /// CHECK-DAG: <<Add1:i\d+>> Add [<<ArgValue>>,<<Const1>>]
+ /// CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<Const2>>]
+ /// CHECK-DAG: <<Add3:i\d+>> Add [<<Add2>>,<<ConstM3>>]
+ /// CHECK-DAG: <<Add4:i\d+>> Add [<<Add3>>,<<Const4>>]
+ /// CHECK-DAG: Return [<<Add4>>]
+
+ /// CHECK-START: int Main.$noinline$AddAddSubAddConst(int) instruction_simplifier (after)
+ /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const4:i\d+>> IntConstant 4
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const4>>]
+ /// CHECK-DAG: Return [<<Add>>]
+
+ public static int $noinline$AddAddSubAddConst(int arg) {
+ if (doThrow) { throw new Error(); }
+ return arg + 1 + 2 - 3 + 4;
+ }
+
/// CHECK-START: int Main.$noinline$AndAllOnes(int) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:i\d+>> ParameterValue
/// CHECK-DAG: <<ConstF:i\d+>> IntConstant -1
@@ -364,6 +387,27 @@ public class Main {
return arg * 128;
}
+ /// CHECK-START: long Main.$noinline$MulMulMulConst(long) instruction_simplifier (before)
+ /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:j\d+>> LongConstant 10
+ /// CHECK-DAG: <<Const11:j\d+>> LongConstant 11
+ /// CHECK-DAG: <<Const12:j\d+>> LongConstant 12
+ /// CHECK-DAG: <<Mul1:j\d+>> Mul [<<Const10>>,<<ArgValue>>]
+ /// CHECK-DAG: <<Mul2:j\d+>> Mul [<<Mul1>>,<<Const11>>]
+ /// CHECK-DAG: <<Mul3:j\d+>> Mul [<<Mul2>>,<<Const12>>]
+ /// CHECK-DAG: Return [<<Mul3>>]
+
+ /// CHECK-START: long Main.$noinline$MulMulMulConst(long) instruction_simplifier (after)
+ /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue
+ /// CHECK-DAG: <<Const1320:j\d+>> LongConstant 1320
+ /// CHECK-DAG: <<Mul:j\d+>> Mul [<<ArgValue>>,<<Const1320>>]
+ /// CHECK-DAG: Return [<<Mul>>]
+
+ public static long $noinline$MulMulMulConst(long arg) {
+ if (doThrow) { throw new Error(); }
+ return 10 * arg * 11 * 12;
+ }
+
/// CHECK-START: int Main.$noinline$Or0(int) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:i\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
@@ -490,6 +534,63 @@ public class Main {
return 0 - arg;
}
+ /// CHECK-START: int Main.$noinline$SubAddConst1(int) instruction_simplifier (before)
+ /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Const6:i\d+>> IntConstant 6
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const5>>,<<ArgValue>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Sub>>,<<Const6>>]
+ /// CHECK-DAG: Return [<<Add>>]
+
+ /// CHECK-START: int Main.$noinline$SubAddConst1(int) instruction_simplifier (after)
+ /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const11:i\d+>> IntConstant 11
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const11>>,<<ArgValue>>]
+ /// CHECK-DAG: Return [<<Sub>>]
+
+ public static int $noinline$SubAddConst1(int arg) {
+ if (doThrow) { throw new Error(); }
+ return 5 - arg + 6;
+ }
+
+ /// CHECK-START: int Main.$noinline$SubAddConst2(int) instruction_simplifier (before)
+ /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const14:i\d+>> IntConstant 14
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<ArgValue>>,<<Const13>>]
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const14>>,<<Add>>]
+ /// CHECK-DAG: Return [<<Sub>>]
+
+ /// CHECK-START: int Main.$noinline$SubAddConst2(int) instruction_simplifier (after)
+ /// CHECK-DAG: <<ArgValue:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Sub:i\d+>> Sub [<<Const1>>,<<ArgValue>>]
+ /// CHECK-DAG: Return [<<Sub>>]
+
+ public static int $noinline$SubAddConst2(int arg) {
+ if (doThrow) { throw new Error(); }
+ return 14 - (arg + 13);
+ }
+
+ /// CHECK-START: long Main.$noinline$SubSubConst(long) instruction_simplifier (before)
+ /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue
+ /// CHECK-DAG: <<Const17:j\d+>> LongConstant 17
+ /// CHECK-DAG: <<Const18:j\d+>> LongConstant 18
+ /// CHECK-DAG: <<Sub1:j\d+>> Sub [<<Const18>>,<<ArgValue>>]
+ /// CHECK-DAG: <<Sub2:j\d+>> Sub [<<Const17>>,<<Sub1>>]
+ /// CHECK-DAG: Return [<<Sub2>>]
+
+ /// CHECK-START: long Main.$noinline$SubSubConst(long) instruction_simplifier (after)
+ /// CHECK-DAG: <<ArgValue:j\d+>> ParameterValue
+ /// CHECK-DAG: <<ConstM1:j\d+>> LongConstant -1
+ /// CHECK-DAG: <<Add:j\d+>> Add [<<ArgValue>>,<<ConstM1>>]
+ /// CHECK-DAG: Return [<<Add>>]
+
+ public static long $noinline$SubSubConst(long arg) {
+ if (doThrow) { throw new Error(); }
+ return 17 - (18 - arg);
+ }
+
/// CHECK-START: long Main.$noinline$UShr0(long) instruction_simplifier (before)
/// CHECK-DAG: <<Arg:j\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
@@ -1757,6 +1858,17 @@ public class Main {
}
}
+ public static int $noinline$runSmaliTestConst(String name, int arg) {
+ if (doThrow) { throw new Error(); }
+ try {
+ Class<?> c = Class.forName("SmaliTests");
+ Method m = c.getMethod(name, int.class);
+ return (Integer) m.invoke(null, arg);
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+
/// CHECK-START: int Main.$noinline$intUnnecessaryShiftMasking(int, int) instruction_simplifier (before)
/// CHECK: <<Value:i\d+>> ParameterValue
/// CHECK: <<Shift:i\d+>> ParameterValue
@@ -1863,12 +1975,14 @@ public static void main(String[] args) {
int arg = 123456;
assertLongEquals(arg, $noinline$Add0(arg));
+ assertIntEquals(5, $noinline$AddAddSubAddConst(1));
assertIntEquals(arg, $noinline$AndAllOnes(arg));
assertLongEquals(arg, $noinline$Div1(arg));
assertIntEquals(-arg, $noinline$DivN1(arg));
assertLongEquals(arg, $noinline$Mul1(arg));
assertIntEquals(-arg, $noinline$MulN1(arg));
assertLongEquals((128 * arg), $noinline$MulPowerOfTwo128(arg));
+ assertLongEquals(2640, $noinline$MulMulMulConst(2));
assertIntEquals(arg, $noinline$Or0(arg));
assertLongEquals(arg, $noinline$OrSame(arg));
assertIntEquals(arg, $noinline$Shl0(arg));
@@ -1876,6 +1990,9 @@ public static void main(String[] args) {
assertLongEquals(arg, $noinline$Shr64(arg));
assertLongEquals(arg, $noinline$Sub0(arg));
assertIntEquals(-arg, $noinline$SubAliasNeg(arg));
+ assertIntEquals(9, $noinline$SubAddConst1(2));
+ assertIntEquals(-2, $noinline$SubAddConst2(3));
+ assertLongEquals(3, $noinline$SubSubConst(4));
assertLongEquals(arg, $noinline$UShr0(arg));
assertIntEquals(arg, $noinline$Xor0(arg));
assertIntEquals(~arg, $noinline$XorAllOnes(arg));
@@ -2011,6 +2128,11 @@ public static void main(String[] args) {
}
}
+ assertIntEquals(0, $noinline$runSmaliTestConst("AddSubConst", 1));
+ assertIntEquals(3, $noinline$runSmaliTestConst("SubAddConst", 2));
+ assertIntEquals(-16, $noinline$runSmaliTestConst("SubSubConst1", 3));
+ assertIntEquals(-5, $noinline$runSmaliTestConst("SubSubConst2", 4));
+ assertIntEquals(26, $noinline$runSmaliTestConst("SubSubConst3", 5));
assertIntEquals(0x5e6f7808, $noinline$intUnnecessaryShiftMasking(0xabcdef01, 3));
assertIntEquals(0x5e6f7808, $noinline$intUnnecessaryShiftMasking(0xabcdef01, 3 + 32));
assertLongEquals(0xffffffffffffeaf3L, $noinline$longUnnecessaryShiftMasking(0xabcdef0123456789L, 50));
diff --git a/test/530-checker-loops1/src/Main.java b/test/530-checker-loops1/src/Main.java
index 948a7b7dcc..dde4d62475 100644
--- a/test/530-checker-loops1/src/Main.java
+++ b/test/530-checker-loops1/src/Main.java
@@ -562,7 +562,7 @@ public class Main {
//
/// CHECK-START: void Main.linearTriangularOnTwoArrayLengths(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- // TODO: also CHECK-NOT: Deoptimize, see b/27151190
+ /// CHECK-NOT: Deoptimize
private static void linearTriangularOnTwoArrayLengths(int n) {
int[] a = new int[n];
for (int i = 0; i < a.length; i++) {
@@ -604,7 +604,7 @@ public class Main {
//
/// CHECK-START: void Main.linearTriangularOnParameter(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- // TODO: also CHECK-NOT: Deoptimize, see b/27151190
+ /// CHECK-NOT: Deoptimize
private static void linearTriangularOnParameter(int n) {
int[] a = new int[n];
for (int i = 0; i < n; i++) {
@@ -619,56 +619,56 @@ public class Main {
}
}
- /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (before)
+ /// CHECK-START: void Main.linearTriangularStrictLower(int) BCE (before)
/// CHECK-DAG: BoundsCheck
/// CHECK-DAG: BoundsCheck
/// CHECK-DAG: BoundsCheck
/// CHECK-DAG: BoundsCheck
//
- /// CHECK-START: void Main.linearTriangularVariationsInnerStrict(int) BCE (after)
+ /// CHECK-START: void Main.linearTriangularStrictLower(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- // TODO: also CHECK-NOT: Deoptimize, see b/27151190
- private static void linearTriangularVariationsInnerStrict(int n) {
+ /// CHECK-NOT: Deoptimize
+ private static void linearTriangularStrictLower(int n) {
int[] a = new int[n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
a[j] += 1;
}
- for (int j = i - 1; j > -1; j--) {
+ for (int j = i - 1; j >= 0; j--) {
a[j] += 1;
}
for (int j = i; j < n; j++) {
a[j] += 1;
}
- for (int j = n - 1; j > i - 1; j--) {
+ for (int j = n - 1; j >= i; j--) {
a[j] += 1;
}
}
verifyTriangular(a);
}
- /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (before)
+ /// CHECK-START: void Main.linearTriangularStrictUpper(int) BCE (before)
/// CHECK-DAG: BoundsCheck
/// CHECK-DAG: BoundsCheck
/// CHECK-DAG: BoundsCheck
/// CHECK-DAG: BoundsCheck
//
- /// CHECK-START: void Main.linearTriangularVariationsInnerNonStrict(int) BCE (after)
+ /// CHECK-START: void Main.linearTriangularStrictUpper(int) BCE (after)
/// CHECK-NOT: BoundsCheck
- // TODO: also CHECK-NOT: Deoptimize, see b/27151190
- private static void linearTriangularVariationsInnerNonStrict(int n) {
+ /// CHECK-NOT: Deoptimize
+ private static void linearTriangularStrictUpper(int n) {
int[] a = new int[n];
for (int i = 0; i < n; i++) {
- for (int j = 0; j <= i - 1; j++) {
+ for (int j = 0; j <= i; j++) {
a[j] += 1;
}
- for (int j = i - 1; j >= 0; j--) {
+ for (int j = i; j >= 0; j--) {
a[j] += 1;
}
- for (int j = i; j <= n - 1; j++) {
+ for (int j = i + 1; j < n; j++) {
a[j] += 1;
}
- for (int j = n - 1; j >= i; j--) {
+ for (int j = n - 1; j >= i + 1; j--) {
a[j] += 1;
}
}
@@ -802,8 +802,8 @@ public class Main {
linearTriangularOnTwoArrayLengths(10);
linearTriangularOnOneArrayLength(10);
linearTriangularOnParameter(10);
- linearTriangularVariationsInnerStrict(10);
- linearTriangularVariationsInnerNonStrict(10);
+ linearTriangularStrictLower(10);
+ linearTriangularStrictUpper(10);
{
int[] t = linearTriangularOOB();
for (int i = 0; i < 200; i++) {
diff --git a/test/530-checker-loops2/src/Main.java b/test/530-checker-loops2/src/Main.java
index b12fbd6091..7acf0080f8 100644
--- a/test/530-checker-loops2/src/Main.java
+++ b/test/530-checker-loops2/src/Main.java
@@ -31,7 +31,7 @@ public class Main {
//
/// CHECK-START: void Main.bubble(int[]) BCE (after)
/// CHECK-NOT: BoundsCheck
- // TODO: also CHECK-NOT: Deoptimize, see b/27151190
+ /// CHECK-NOT: Deoptimize
private static void bubble(int[] a) {
for (int i = a.length; --i >= 0;) {
for (int j = 0; j < i; j++) {
@@ -301,6 +301,53 @@ public class Main {
} while (-1 <= i);
}
+ /// CHECK-START: void Main.justRightTriangular1() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.justRightTriangular1() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static void justRightTriangular1() {
+ int[] a = { 1 } ;
+ for (int i = Integer.MIN_VALUE + 5; i <= Integer.MIN_VALUE + 10; i++) {
+ for (int j = Integer.MIN_VALUE + 4; j < i - 5; j++) {
+ sResult += a[j - (Integer.MIN_VALUE + 4)];
+ }
+ }
+ }
+
+ /// CHECK-START: void Main.justRightTriangular2() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.justRightTriangular2() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static void justRightTriangular2() {
+ int[] a = { 1 } ;
+ for (int i = Integer.MIN_VALUE + 5; i <= 10; i++) {
+ for (int j = 4; j < i - 5; j++) {
+ sResult += a[j - 4];
+ }
+ }
+ }
+
+ /// CHECK-START: void Main.justOOBTriangular() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.justOOBTriangular() BCE (after)
+ /// CHECK-DAG: Deoptimize
+ //
+ /// CHECK-START: void Main.justOOBTriangular() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static void justOOBTriangular() {
+ int[] a = { 1 } ;
+ for (int i = Integer.MIN_VALUE + 4; i <= 10; i++) {
+ for (int j = 4; j < i - 5; j++) {
+ sResult += a[j - 4];
+ }
+ }
+ }
+
/// CHECK-START: void Main.hiddenOOB1(int) BCE (before)
/// CHECK-DAG: BoundsCheck
//
@@ -315,7 +362,6 @@ public class Main {
// Dangerous loop where careless static range analysis would yield strict upper bound
// on index j of 5. When, for instance, lo and thus i = -2147483648, the upper bound
// becomes really positive due to arithmetic wrap-around, causing OOB.
- // Dynamic BCE is feasible though, since it checks the range.
for (int j = 4; j < i - 5; j++) {
sResult += a[j - 4];
}
@@ -336,13 +382,32 @@ public class Main {
// Dangerous loop where careless static range analysis would yield strict lower bound
// on index j of 5. When, for instance, hi and thus i = 2147483647, the upper bound
// becomes really negative due to arithmetic wrap-around, causing OOB.
- // Dynamic BCE is feasible though, since it checks the range.
for (int j = 6; j > i + 5; j--) {
sResult += a[j - 6];
}
}
}
+ /// CHECK-START: void Main.hiddenOOB3(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.hiddenOOB3(int) BCE (after)
+ /// CHECK-DAG: Deoptimize
+ //
+ /// CHECK-START: void Main.hiddenOOB3(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static void hiddenOOB3(int hi) {
+ int[] a = { 11 } ;
+ for (int i = -1; i <= hi; i++) {
+ // Dangerous loop where careless static range analysis would yield strict lower bound
+ // on index j of 0. For large i, the initial value of j becomes really negative due
+ // to arithmetic wrap-around, causing OOB.
+ for (int j = i + 1; j < 1; j++) {
+ sResult += a[j];
+ }
+ }
+ }
+
/// CHECK-START: void Main.hiddenInfiniteOOB() BCE (before)
/// CHECK-DAG: BoundsCheck
//
@@ -376,7 +441,6 @@ public class Main {
for (int i = -1; i <= 0; i++) {
// Dangerous loop similar as above where the loop is now finite, but the
// loop still goes out of bounds for i = -1 due to the large upper bound.
- // Dynamic BCE is feasible though, since it checks the range.
for (int j = -4; j < 2147483646 * i - 3; j++) {
sResult += a[j + 4];
}
@@ -432,6 +496,25 @@ public class Main {
}
}
+ /// CHECK-START: int Main.doNotHoist(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.doNotHoist(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ public static int doNotHoist(int[] a) {
+ int n = a.length;
+ int x = 0;
+ // BCE applies, but hoisting would crash the loop.
+ for (int i = -10000; i < 10000; i++) {
+ for (int j = 0; j <= 1; j++) {
+ if (0 <= i && i < n)
+ x += a[i];
+ }
+ }
+ return x;
+ }
+
+
/// CHECK-START: int[] Main.add() BCE (before)
/// CHECK-DAG: BoundsCheck
//
@@ -687,7 +770,7 @@ public class Main {
/// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
// Order matters:
/// CHECK: Deoptimize loop:<<Loop:B\d+>>
- // CHECK-NOT: Goto loop:<<Loop>>
+ /// CHECK-NOT: Goto loop:<<Loop>>
/// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
/// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
/// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
@@ -839,6 +922,8 @@ public class Main {
expectEquals(55, justRightDown1());
expectEquals(55, justRightDown2());
expectEquals(55, justRightDown3());
+
+ // Large bounds OOB.
sResult = 0;
try {
justOOBUp();
@@ -890,6 +975,23 @@ public class Main {
}
expectEquals(1055, sResult);
+ // Triangular.
+ sResult = 0;
+ justRightTriangular1();
+ expectEquals(1, sResult);
+ if (HEAVY) {
+ sResult = 0;
+ justRightTriangular2();
+ expectEquals(1, sResult);
+ }
+ sResult = 0;
+ try {
+ justOOBTriangular();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1001, sResult);
+
// Hidden OOB.
sResult = 0;
try {
@@ -912,6 +1014,15 @@ public class Main {
sResult += 1000;
}
expectEquals(1, sResult);
+ sResult = 0;
+ try {
+ hiddenOOB3(-1); // no OOB
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(11, sResult);
+
+ // Expensive hidden OOB test.
if (HEAVY) {
sResult = 0;
try {
@@ -920,7 +1031,16 @@ public class Main {
sResult += 1000;
}
expectEquals(1002, sResult);
+ sResult = 0;
+ try {
+ hiddenOOB3(2147483647); // OOB
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1011, sResult);
}
+
+ // More hidden OOB.
sResult = 0;
try {
hiddenInfiniteOOB();
@@ -966,6 +1086,9 @@ public class Main {
expectEquals(i < 128 ? i : 0, a200[i]);
}
+ // No hoisting after BCE.
+ expectEquals(110, doNotHoist(x));
+
// Addition.
{
int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 };