From 328429ff48d06e2cad4ebdd3568ab06de916a10a Mon Sep 17 00:00:00 2001 From: Artem Serov Date: Wed, 6 Jul 2016 16:23:04 +0100 Subject: ARM: Port instr simplification of array accesses. After changing the addressing mode for array accesses (in https://android-review.googlesource.com/248406) the 'add' instruction that calculates the base address for the array can be shared across accesses to the same array. Before https://android-review.googlesource.com/248406: add IP, r[Array], r[Index0], LSL #2 ldr r0, [IP, #12] add IP, r[Array], r[Index1], LSL #2 ldr r0, [IP, #12] Before this CL: add IP. r[Array], #12 ldr r0, [IP, r[Index0], LSL #2] add IP. r[Array], #12 ldr r0, [IP, r[Index1], LSL #2] After this CL: add IP. r[Array], #12 ldr r0, [IP, r[Index0], LSL #2] ldr r0, [IP, r[Index1], LSL #2] Link to the original optimization: https://android-review.googlesource.com/#/c/127310/ Test: Run ART test suite on Nexus 6. Change-Id: Iee26f9a0a7ca46abb90e3f60d19d22dc8dee4d8f --- test/527-checker-array-access-split/src/Main.java | 298 +++++++++++++++++++--- 1 file changed, 268 insertions(+), 30 deletions(-) (limited to 'test/527-checker-array-access-split/src/Main.java') diff --git a/test/527-checker-array-access-split/src/Main.java b/test/527-checker-array-access-split/src/Main.java index ead94464bf..3366f20cc5 100644 --- a/test/527-checker-array-access-split/src/Main.java +++ b/test/527-checker-array-access-split/src/Main.java @@ -34,9 +34,21 @@ public class Main { /// CHECK-START-ARM64: int Main.constantIndexGet(int[]) instruction_simplifier_arm64 (after) /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK-NOT: Arm64IntermediateAddress + /// CHECK-NOT: IntermediateAddress /// CHECK: ArrayGet [<>,<>] + + /// CHECK-START-ARM: int Main.constantIndexGet(int[]) instruction_simplifier_arm (before) + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: ArrayGet [<>,<>] + + /// CHECK-START-ARM: int Main.constantIndexGet(int[]) instruction_simplifier_arm (after) + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK-NOT: IntermediateAddress + /// CHECK: ArrayGet [<>,<>] + public static int constantIndexGet(int array[]) { return array[1]; } @@ -55,9 +67,22 @@ public class Main { /// CHECK: <> IntConstant 2 /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK-NOT: Arm64IntermediateAddress + /// CHECK-NOT: IntermediateAddress + /// CHECK: ArraySet [<>,<>,<>] + + + /// CHECK-START-ARM: void Main.constantIndexSet(int[]) instruction_simplifier_arm (before) + /// CHECK: <> IntConstant 2 + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck /// CHECK: ArraySet [<>,<>,<>] + /// CHECK-START-ARM: void Main.constantIndexSet(int[]) instruction_simplifier_arm (after) + /// CHECK: <> IntConstant 2 + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK-NOT: IntermediateAddress + /// CHECK: ArraySet [<>,<>,<>] public static void constantIndexSet(int array[]) { array[1] = 2; @@ -76,7 +101,20 @@ public class Main { /// CHECK: <> IntConstant /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: ArrayGet [<
>,<>] + + + /// CHECK-START-ARM: int Main.get(int[], int) instruction_simplifier_arm (before) + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: ArrayGet [<>,<>] + + /// CHECK-START-ARM: int Main.get(int[], int) instruction_simplifier_arm (after) + /// CHECK: <> IntConstant + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: ArrayGet [<
>,<>] public static int get(int array[], int index) { @@ -102,7 +140,26 @@ public class Main { /// CHECK: <> IntConstant /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: ArraySet [<
>,<>,<>] + + + /// CHECK-START-ARM: void Main.set(int[], int, int) instruction_simplifier_arm (before) + /// CHECK: ParameterValue + /// CHECK: ParameterValue + /// CHECK: <> ParameterValue + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: void Main.set(int[], int, int) instruction_simplifier_arm (after) + /// CHECK: ParameterValue + /// CHECK: ParameterValue + /// CHECK: <> ParameterValue + /// CHECK: <> IntConstant + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: ArraySet [<
>,<>,<>] public static void set(int array[], int index, int value) { @@ -126,10 +183,10 @@ public class Main { /// CHECK-DAG: <> IntConstant /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: <> ArrayGet [<>,<>] /// CHECK: <> Add [<>,<>] - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: ArraySet [<>,<>,<>] /// CHECK-START-ARM64: void Main.getSet(int[], int) GVN_after_arch (after) @@ -137,12 +194,42 @@ public class Main { /// CHECK-DAG: <> IntConstant /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK: <> ArrayGet [<
>,<>] /// CHECK: <> Add [<>,<>] - /// CHECK-NOT: Arm64IntermediateAddress + /// CHECK-NOT: IntermediateAddress /// CHECK: ArraySet [<
>,<>,<>] + + /// CHECK-START-ARM: void Main.getSet(int[], int) instruction_simplifier_arm (before) + /// CHECK: <> IntConstant 1 + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: void Main.getSet(int[], int) instruction_simplifier_arm (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: void Main.getSet(int[], int) GVN_after_arch (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK: <> ArrayGet [<
>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK-NOT: IntermediateAddress + /// CHECK: ArraySet [<
>,<>,<>] public static void getSet(int array[], int index) { array[index] = array[index] + 1; } @@ -166,11 +253,11 @@ public class Main { /// CHECK-DAG: <> IntConstant /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: <> ArrayGet [<>,<>] /// CHECK: <> Add [<>,<>] /// CHECK: NewArray - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: ArraySet [<>,<>,<>] /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) GVN_after_arch (after) @@ -178,11 +265,45 @@ public class Main { /// CHECK-DAG: <> IntConstant /// CHECK: <> NullCheck /// CHECK: <> BoundsCheck - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK: <> ArrayGet [<>,<>] /// CHECK: <> Add [<>,<>] /// CHECK: NewArray - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK: ArraySet [<>,<>,<>] + + + /// CHECK-START-ARM: int[] Main.accrossGC(int[], int) instruction_simplifier_arm (before) + /// CHECK: <> IntConstant 1 + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: NewArray + /// CHECK: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: int[] Main.accrossGC(int[], int) instruction_simplifier_arm (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: NewArray + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: int[] Main.accrossGC(int[], int) GVN_after_arch (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant + /// CHECK: <> NullCheck + /// CHECK: <> BoundsCheck + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: NewArray + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK: ArraySet [<>,<>,<>] public static int[] accrossGC(int array[], int index) { @@ -196,6 +317,14 @@ public class Main { * Test that the intermediate address is shared between array accesses after * the bounds check have been removed by BCE. */ + // For checker tests `instruction_simplifier_ (after)` below, by the time we reach + // the architecture-specific instruction simplifier, BCE has removed the bounds checks in + // the loop. + + // Note that we do not care that the `DataOffset` is `12`. But if we do not + // specify it and any other `IntConstant` appears before that instruction, + // checker will match the previous `IntConstant`, and we will thus fail the + // check. /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() instruction_simplifier_arm64 (before) /// CHECK: <> IntConstant 1 @@ -207,14 +336,6 @@ public class Main { /// CHECK: <> Add [<>,<>] /// CHECK: ArraySet [<>,<>,<>] - // By the time we reach the architecture-specific instruction simplifier, BCE - // has removed the bounds checks in the loop. - - // Note that we do not care that the `DataOffset` is `12`. But if we do not - // specify it and any other `IntConstant` appears before that instruction, - // checker will match the previous `IntConstant`, and we will thus fail the - // check. - /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() instruction_simplifier_arm64 (after) /// CHECK-DAG: <> IntConstant 1 /// CHECK-DAG: <> IntConstant 12 @@ -222,10 +343,10 @@ public class Main { /// CHECK: <> Phi /// CHECK: If // -------------- Loop - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: <> ArrayGet [<>,<>] /// CHECK: <> Add [<>,<>] - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK-NEXT: ArraySet [<>,<>,<>] /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() GVN_after_arch (after) @@ -235,10 +356,47 @@ public class Main { /// CHECK: <> Phi /// CHECK: If // -------------- Loop - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK: <> ArrayGet [<
>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK-NOT: IntermediateAddress + /// CHECK: ArraySet [<
>,<>,<>] + + + /// CHECK-START-ARM: int Main.canMergeAfterBCE1() instruction_simplifier_arm (before) + /// CHECK: <> IntConstant 1 + /// CHECK: <> NewArray + /// CHECK: <> Phi + /// CHECK: If + // -------------- Loop + /// CHECK: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: int Main.canMergeAfterBCE1() instruction_simplifier_arm (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant 12 + /// CHECK: <> NewArray + /// CHECK: <> Phi + /// CHECK: If + // -------------- Loop + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK-NEXT: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: int Main.canMergeAfterBCE1() GVN_after_arch (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant 12 + /// CHECK: <> NewArray + /// CHECK: <> Phi + /// CHECK: If + // -------------- Loop + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK: <> ArrayGet [<
>,<>] /// CHECK: <> Add [<>,<>] - /// CHECK-NOT: Arm64IntermediateAddress + /// CHECK-NOT: IntermediateAddress /// CHECK: ArraySet [<
>,<>,<>] public static int canMergeAfterBCE1() { @@ -279,12 +437,12 @@ public class Main { /// CHECK: If // -------------- Loop /// CHECK-DAG: <> Add [<>,<>] - /// CHECK-DAG: <> Arm64IntermediateAddress [<>,<>] + /// CHECK-DAG: <> IntermediateAddress [<>,<>] /// CHECK-DAG: <> ArrayGet [<>,<>] - /// CHECK-DAG: <> Arm64IntermediateAddress [<>,<>] + /// CHECK-DAG: <> IntermediateAddress [<>,<>] /// CHECK-DAG: <> ArrayGet [<>,<>] /// CHECK: <> Add [<>,<>] - /// CHECK: <> Arm64IntermediateAddress [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] /// CHECK: ArraySet [<>,<>,<>] /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() GVN_after_arch (after) @@ -295,7 +453,7 @@ public class Main { /// CHECK: If // -------------- Loop /// CHECK-DAG: <> Add [<>,<>] - /// CHECK-DAG: <> Arm64IntermediateAddress [<>,<>] + /// CHECK-DAG: <> IntermediateAddress [<>,<>] /// CHECK-DAG: <> ArrayGet [<
>,<>] /// CHECK-DAG: <> ArrayGet [<
>,<>] /// CHECK: <> Add [<>,<>] @@ -304,8 +462,55 @@ public class Main { // There should be only one intermediate address computation in the loop. /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() GVN_after_arch (after) - /// CHECK: Arm64IntermediateAddress - /// CHECK-NOT: Arm64IntermediateAddress + /// CHECK: IntermediateAddress + /// CHECK-NOT: IntermediateAddress + + + /// CHECK-START-ARM: int Main.canMergeAfterBCE2() instruction_simplifier_arm (before) + /// CHECK: <> IntConstant 1 + /// CHECK: <> NewArray + /// CHECK: <> Phi + /// CHECK: If + // -------------- Loop + /// CHECK-DAG: <> Add [<>,<>] + /// CHECK-DAG: <> ArrayGet [<>,<>] + /// CHECK-DAG: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: int Main.canMergeAfterBCE2() instruction_simplifier_arm (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant 12 + /// CHECK: <> NewArray + /// CHECK: <> Phi + /// CHECK: If + // -------------- Loop + /// CHECK-DAG: <> Add [<>,<>] + /// CHECK-DAG: <> IntermediateAddress [<>,<>] + /// CHECK-DAG: <> ArrayGet [<>,<>] + /// CHECK-DAG: <> IntermediateAddress [<>,<>] + /// CHECK-DAG: <> ArrayGet [<>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: <> IntermediateAddress [<>,<>] + /// CHECK: ArraySet [<>,<>,<>] + + /// CHECK-START-ARM: int Main.canMergeAfterBCE2() GVN_after_arch (after) + /// CHECK-DAG: <> IntConstant 1 + /// CHECK-DAG: <> IntConstant 12 + /// CHECK: <> NewArray + /// CHECK: <> Phi + /// CHECK: If + // -------------- Loop + /// CHECK-DAG: <> Add [<>,<>] + /// CHECK-DAG: <> IntermediateAddress [<>,<>] + /// CHECK-DAG: <> ArrayGet [<
>,<>] + /// CHECK-DAG: <> ArrayGet [<
>,<>] + /// CHECK: <> Add [<>,<>] + /// CHECK: ArraySet [<
>,<>,<>] + + /// CHECK-START-ARM: int Main.canMergeAfterBCE2() GVN_after_arch (after) + /// CHECK: IntermediateAddress + /// CHECK-NOT: IntermediateAddress public static int canMergeAfterBCE2() { int[] array = {0, 1, 2, 3}; @@ -315,6 +520,37 @@ public class Main { return array[array.length - 1]; } + /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (before) + /// CHECK-DAG: <> NewArray + /// CHECK-DAG: <> NewArray + /// CHECK-DAG: <> NewArray + /// CHECK-DAG: <> Phi + /// CHECK-DAG: ArrayGet [<>,<>] + /// CHECK-DAG: ArrayGet [<>,<>] + /// CHECK-DAG: ArrayGet [<>,<>] + + /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (after) + /// CHECK-DAG: <> NewArray + /// CHECK-DAG: <> NewArray + /// CHECK-DAG: <> NewArray + /// CHECK-DAG: <> Phi + /// CHECK-DAG: ArrayGet [<>,<>] + /// CHECK-DAG: ArrayGet [<>,<>] + /// CHECK-DAG: ArrayGet [<>,<>] + + /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (after) + /// CHECK-NOT: IntermediateAddress + public static int checkLongFloatDouble() { + long[] array_long = {0, 1, 2, 3}; + float[] array_float = {(float)0.0, (float)1.0, (float)2.0, (float)3.0}; + double[] array_double = {0.0, 1.0, 2.0, 3.0}; + double s = 0.0; + + for (int i = 0; i < 4; i++) { + s += (double)array_long[i] + (double)array_float[i] + array_double[i]; + } + return (int)s; + } public static void main(String[] args) { int[] array = {123, 456, 789}; @@ -337,5 +573,7 @@ public class Main { assertIntEquals(4, canMergeAfterBCE1()); assertIntEquals(6, canMergeAfterBCE2()); + + assertIntEquals(18, checkLongFloatDouble()); } } -- cgit v1.2.3-59-g8ed1b