diff options
Diffstat (limited to 'test')
| -rw-r--r-- | test/458-checker-instruction-simplification/smali/SmaliTests.smali | 136 | ||||
| -rw-r--r-- | test/458-checker-instruction-simplification/src/Main.java | 122 | ||||
| -rw-r--r-- | test/478-checker-clinit-check-pruning/src/Main.java | 53 | ||||
| -rw-r--r-- | test/530-checker-loops1/src/Main.java | 36 | ||||
| -rw-r--r-- | test/530-checker-loops2/src/Main.java | 133 | ||||
| -rw-r--r-- | test/548-checker-inlining-and-dce/src/Main.java | 10 | ||||
| -rw-r--r-- | test/609-checker-inline-interface/expected.txt | 0 | ||||
| -rw-r--r-- | test/609-checker-inline-interface/info.txt | 2 | ||||
| -rw-r--r-- | test/609-checker-inline-interface/src/Main.java | 70 | ||||
| -rw-r--r-- | test/610-arraycopy/expected.txt | 0 | ||||
| -rw-r--r-- | test/610-arraycopy/info.txt | 2 | ||||
| -rw-r--r-- | test/610-arraycopy/src/Main.java | 44 |
12 files changed, 554 insertions, 54 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/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java index 6fc12f138c..c2982b48db 100644 --- a/test/478-checker-clinit-check-pruning/src/Main.java +++ b/test/478-checker-clinit-check-pruning/src/Main.java @@ -103,10 +103,8 @@ public class Main { static boolean doThrow = false; static void $noinline$staticMethod() { - if (doThrow) { - // Try defeating inlining. - throw new Error(); - } + // Try defeating inlining. + if (doThrow) { throw new Error(); } } } @@ -181,10 +179,8 @@ public class Main { static boolean doThrow = false; static void $noinline$staticMethod() { - if (doThrow) { // Try defeating inlining. - throw new Error(); - } + if (doThrow) { throw new Error(); } } } @@ -245,10 +241,8 @@ public class Main { static boolean doThrow = false; static void $noinline$staticMethod() { - if (doThrow) { // Try defeating inlining. - throw new Error(); - } + if (doThrow) { throw new Error(); } } static { @@ -314,7 +308,7 @@ public class Main { static void constClassAndInvokeStatic(Iterable<?> it) { $opt$inline$ignoreClass(ClassWithClinit7.class); - ClassWithClinit7.someStaticMethod(it); + ClassWithClinit7.$noinline$someStaticMethod(it); } static void $opt$inline$ignoreClass(Class<?> c) { @@ -325,10 +319,10 @@ public class Main { System.out.println("Main$ClassWithClinit7's static initializer"); } - // Note: not inlined from constClassAndInvokeStatic() but fully inlined from main(). - static void someStaticMethod(Iterable<?> it) { - // We're not inlining invoke-interface at the moment. + static void $noinline$someStaticMethod(Iterable<?> it) { it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } @@ -345,7 +339,7 @@ public class Main { static void sgetAndInvokeStatic(Iterable<?> it) { $opt$inline$ignoreInt(ClassWithClinit8.value); - ClassWithClinit8.someStaticMethod(it); + ClassWithClinit8.$noinline$someStaticMethod(it); } static void $opt$inline$ignoreInt(int i) { @@ -357,10 +351,10 @@ public class Main { System.out.println("Main$ClassWithClinit8's static initializer"); } - // Note: not inlined from sgetAndInvokeStatic() but fully inlined from main(). - static void someStaticMethod(Iterable<?> it) { - // We're not inlining invoke-interface at the moment. + static void $noinline$someStaticMethod(Iterable<?> it) { it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } @@ -377,7 +371,7 @@ public class Main { static void constClassSgetAndInvokeStatic(Iterable<?> it) { $opt$inline$ignoreClass(ClassWithClinit9.class); $opt$inline$ignoreInt(ClassWithClinit9.value); - ClassWithClinit9.someStaticMethod(it); + ClassWithClinit9.$noinline$someStaticMethod(it); } static class ClassWithClinit9 { @@ -386,10 +380,10 @@ public class Main { System.out.println("Main$ClassWithClinit9's static initializer"); } - // Note: not inlined from constClassSgetAndInvokeStatic() but fully inlined from main(). - static void someStaticMethod(Iterable<?> it) { - // We're not inlining invoke-interface at the moment. + static void $noinline$someStaticMethod(Iterable<?> it) { it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } @@ -422,8 +416,9 @@ public class Main { static void inlinedForNull(Iterable<?> it) { if (it != null) { - // We're not inlining invoke-interface at the moment. it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } } @@ -460,8 +455,11 @@ public class Main { } static void inlinedForNull(Iterable<?> it) { - // We're not inlining invoke-interface at the moment. it.iterator(); + if (it != null) { + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } + } } } @@ -494,8 +492,8 @@ public class Main { static void inlinedForNull(Iterable<?> it) { if (it != null) { - // We're not inlining invoke-interface at the moment. - it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } } @@ -510,8 +508,9 @@ public class Main { } public static void $noinline$getIterator(Iterable<?> it) { - // We're not inlining invoke-interface at the moment. it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } 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 }; diff --git a/test/548-checker-inlining-and-dce/src/Main.java b/test/548-checker-inlining-and-dce/src/Main.java index 38fdcc0b94..bf64c3bb36 100644 --- a/test/548-checker-inlining-and-dce/src/Main.java +++ b/test/548-checker-inlining-and-dce/src/Main.java @@ -16,17 +16,19 @@ public class Main { + static boolean doThrow = false; + private void inlinedForNull(Iterable it) { if (it != null) { - // We're not inlining invoke-interface at the moment. - it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } private void inlinedForFalse(boolean value, Iterable it) { if (value) { - // We're not inlining invoke-interface at the moment. - it.iterator(); + // We're not inlining throw at the moment. + if (doThrow) { throw new Error(""); } } } diff --git a/test/609-checker-inline-interface/expected.txt b/test/609-checker-inline-interface/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/609-checker-inline-interface/expected.txt diff --git a/test/609-checker-inline-interface/info.txt b/test/609-checker-inline-interface/info.txt new file mode 100644 index 0000000000..35eee08985 --- /dev/null +++ b/test/609-checker-inline-interface/info.txt @@ -0,0 +1,2 @@ +Checker test that we inline interface calls and if we can't inline +them, we can turn them into a virtual invoke. diff --git a/test/609-checker-inline-interface/src/Main.java b/test/609-checker-inline-interface/src/Main.java new file mode 100644 index 0000000000..413f2dd51d --- /dev/null +++ b/test/609-checker-inline-interface/src/Main.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public final class Main implements Interface { + + static void methodWithInvokeInterface(Interface interf) { + interf.doCall(); + } + + public void doCall() { + if (doThrow) throw new Error(""); + } + + public static void main(String[] args) { + testInlineInterfaceCall(); + testInterfaceToVirtualCall(); + } + + /// CHECK-START: void Main.testInlineInterfaceCall() inliner (before) + /// CHECK: InvokeStaticOrDirect method_name:Main.methodWithInvokeInterface + + /// CHECK-START: void Main.testInlineInterfaceCall() inliner (before) + /// CHECK-NOT: InvokeInterface + + /// CHECK-START: void Main.testInlineInterfaceCall() inliner (after) + /// CHECK: InvokeInterface method_name:Interface.doCall + + /// CHECK-START: void Main.testInlineInterfaceCall() inliner (after) + /// CHECK-NOT: InvokeStaticOrDirect + public static void testInlineInterfaceCall() { + methodWithInvokeInterface(itf); + } + + /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (before) + /// CHECK: InvokeStaticOrDirect method_name:Main.methodWithInvokeInterface + + /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (before) + /// CHECK-NOT: InvokeInterface + + /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (after) + /// CHECK: InvokeVirtual method_name:Main.doCall + + /// CHECK-START: void Main.testInterfaceToVirtualCall() inliner (after) + /// CHECK-NOT: InvokeStaticOrDirect + /// CHECK-NOT: InvokeInterface + public static void testInterfaceToVirtualCall() { + methodWithInvokeInterface(m); + } + + static Interface itf = new Main(); + static Main m = new Main(); + static boolean doThrow = false; +} + +interface Interface { + public void doCall(); +} diff --git a/test/610-arraycopy/expected.txt b/test/610-arraycopy/expected.txt new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/test/610-arraycopy/expected.txt diff --git a/test/610-arraycopy/info.txt b/test/610-arraycopy/info.txt new file mode 100644 index 0000000000..a77190d8fa --- /dev/null +++ b/test/610-arraycopy/info.txt @@ -0,0 +1,2 @@ +Regression test for the System.arraycopy intrinsic, which had a bug +when doing the copy on the same array. diff --git a/test/610-arraycopy/src/Main.java b/test/610-arraycopy/src/Main.java new file mode 100644 index 0000000000..ee11c8ee2a --- /dev/null +++ b/test/610-arraycopy/src/Main.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +public class Main { + public static void main(String[] args) { + Object[] a = new Object[5]; + for (int i = 0; i < 5; i++) { + a[i] = new Integer(i); + } + $noinline$callArrayCopy(a, a); + + expectEquals(0, ((Integer)a[0]).intValue()); + expectEquals(0, ((Integer)a[1]).intValue()); + expectEquals(1, ((Integer)a[2]).intValue()); + expectEquals(2, ((Integer)a[3]).intValue()); + expectEquals(4, ((Integer)a[4]).intValue()); + } + + public static void expectEquals(int expected, int actual) { + if (expected != actual) { + throw new Error("Expected " + expected + ", got " + actual); + } + } + + public static void $noinline$callArrayCopy(Object[] a, Object[] b) { + System.arraycopy(a, 0, b, 1, 3); + if (doThrow) { throw new Error(); } + } + + static boolean doThrow = false; +} |