Merge "Revert "ART: Support interpreter switching in x86 mterp""
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 6348dda..478b164 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -126,6 +126,8 @@
has_done_full_collection_(false),
last_update_time_ns_(0),
garbage_collect_code_(garbage_collect_code),
+ used_memory_for_data_(0),
+ used_memory_for_code_(0),
number_of_compilations_(0) {
DCHECK_GE(max_capacity, initial_code_capacity + initial_data_capacity);
diff --git a/test/530-checker-loops/src/Main.java b/test/530-checker-loops/src/Main.java
index 9f344dd..8633745 100644
--- a/test/530-checker-loops/src/Main.java
+++ b/test/530-checker-loops/src/Main.java
@@ -605,725 +605,6 @@
}
}
- /// CHECK-START: void Main.bubble(int[]) BCE (before)
- /// CHECK-DAG: BoundsCheck
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.bubble(int[]) BCE (after)
- /// CHECK-NOT: BoundsCheck
- // TODO: also CHECK-NOT: Deoptimize, see b/27151190
- private static void bubble(int[] a) {
- for (int i = a.length; --i >= 0;) {
- for (int j = 0; j < i; j++) {
- if (a[j] > a[j+1]) {
- int tmp = a[j];
- a[j] = a[j+1];
- a[j+1] = tmp;
- }
- }
- }
- }
-
- /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int periodicIdiom(int tc) {
- int[] x = { 1, 3 };
- // Loop with periodic sequence (0, 1).
- int k = 0;
- int result = 0;
- for (int i = 0; i < tc; i++) {
- result += x[k];
- k = 1 - k;
- }
- return result;
- }
-
- /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int periodicSequence2(int tc) {
- int[] x = { 1, 3 };
- // Loop with periodic sequence (0, 1).
- int k = 0;
- int l = 1;
- int result = 0;
- for (int i = 0; i < tc; i++) {
- result += x[k];
- int t = l;
- l = k;
- k = t;
- }
- return result;
- }
-
- /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
- /// CHECK-DAG: BoundsCheck
- /// CHECK-DAG: BoundsCheck
- /// CHECK-DAG: BoundsCheck
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int periodicSequence4(int tc) {
- int[] x = { 1, 3, 5, 7 };
- // Loop with periodic sequence (0, 1, 2, 3).
- int k = 0;
- int l = 1;
- int m = 2;
- int n = 3;
- int result = 0;
- for (int i = 0; i < tc; i++) {
- result += x[k] + x[l] + x[m] + x[n]; // all used at once
- int t = n;
- n = k;
- k = l;
- l = m;
- m = t;
- }
- return result;
- }
-
- /// CHECK-START: int Main.justRightUp1() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justRightUp1() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int justRightUp1() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- for (int i = Integer.MAX_VALUE - 10, k = 0; i < Integer.MAX_VALUE; i++) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: int Main.justRightUp2() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justRightUp2() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int justRightUp2() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- for (int i = Integer.MAX_VALUE - 10; i < Integer.MAX_VALUE; i++) {
- result += x[i - Integer.MAX_VALUE + 10];
- }
- return result;
- }
-
- /// CHECK-START: int Main.justRightUp3() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justRightUp3() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int justRightUp3() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- for (int i = Integer.MAX_VALUE - 10, k = 0; i <= Integer.MAX_VALUE - 1; i++) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: int Main.justOOBUp() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justOOBUp() BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justOOBUp() BCE (after)
- /// CHECK-NOT: Deoptimize
- private static int justOOBUp() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- // Infinite loop!
- for (int i = Integer.MAX_VALUE - 9, k = 0; i <= Integer.MAX_VALUE; i++) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: int Main.justRightDown1() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justRightDown1() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int justRightDown1() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- for (int i = Integer.MIN_VALUE + 10, k = 0; i > Integer.MIN_VALUE; i--) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: int Main.justRightDown2() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justRightDown2() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int justRightDown2() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- for (int i = Integer.MIN_VALUE + 10; i > Integer.MIN_VALUE; i--) {
- result += x[Integer.MAX_VALUE + i];
- }
- return result;
- }
-
- /// CHECK-START: int Main.justRightDown3() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justRightDown3() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int justRightDown3() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- for (int i = Integer.MIN_VALUE + 10, k = 0; i >= Integer.MIN_VALUE + 1; i--) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: int Main.justOOBDown() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justOOBDown() BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int Main.justOOBDown() BCE (after)
- /// CHECK-NOT: Deoptimize
- private static int justOOBDown() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int result = 0;
- // Infinite loop!
- for (int i = Integer.MIN_VALUE + 9, k = 0; i >= Integer.MIN_VALUE; i--) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
- /// CHECK-NOT: Deoptimize
- private static void lowerOOB(int[] x) {
- // OOB!
- for (int i = -1; i < x.length; i++) {
- sResult += x[i];
- }
- }
-
- /// CHECK-START: void Main.upperOOB(int[]) BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
- /// CHECK-NOT: Deoptimize
- private static void upperOOB(int[] x) {
- // OOB!
- for (int i = 0; i <= x.length; i++) {
- sResult += x[i];
- }
- }
-
- /// CHECK-START: void Main.doWhileUpOOB() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
- /// CHECK-NOT: Deoptimize
- private static void doWhileUpOOB() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int i = 0;
- // OOB!
- do {
- sResult += x[i++];
- } while (i <= x.length);
- }
-
- /// CHECK-START: void Main.doWhileDownOOB() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
- /// CHECK-NOT: Deoptimize
- private static void doWhileDownOOB() {
- int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
- int i = x.length - 1;
- // OOB!
- do {
- sResult += x[i--];
- } while (-1 <= i);
- }
-
- /// CHECK-START: void Main.hiddenOOB1(int) BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
- /// CHECK-DAG: Deoptimize
- //
- /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
- /// CHECK-NOT: BoundsCheck
- private static void hiddenOOB1(int lo) {
- int[] a = { 1 } ;
- for (int i = lo; i <= 10; i++) {
- // 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];
- }
- }
- }
-
- /// CHECK-START: void Main.hiddenOOB2(int) BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
- /// CHECK-DAG: Deoptimize
- //
- /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
- /// CHECK-NOT: BoundsCheck
- private static void hiddenOOB2(int hi) {
- int[] a = { 1 } ;
- for (int i = 0; i < hi; i++) {
- // Dangerous loop where careless static range analysis would yield strict lower bound
- // on index j of 5. When, for instance, lo 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.hiddenInfiniteOOB() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
- /// CHECK-NOT: Deoptimize
- private static void hiddenInfiniteOOB() {
- int[] a = { 11 } ;
- for (int i = -1; i <= 0; i++) {
- // Dangerous loop where careless static range analysis would yield a safe upper bound
- // of -3. In reality, due to arithmetic wrap-around (when i = -1, j <= 2147483647;
- // whereas when i = 0, j <= -3), this is an infinite loop that goes OOB.
- for (int j = -3; j <= 2147483646 * i - 3; j++) {
- sResult += a[j + 3];
- }
- }
- }
-
- /// CHECK-START: void Main.hiddenFiniteOOB() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
- /// CHECK-DAG: Deoptimize
- //
- /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
- /// CHECK-NOT: BoundsCheck
- private static void hiddenFiniteOOB() {
- int[] a = { 111 } ;
- 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];
- }
- }
- }
-
- /// CHECK-START: int[] Main.add() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int[] Main.add() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int[] add() {
- int[] a = new int[10];
- for (int i = 0; i <= 3; i++) {
- for (int j = 0; j <= 6; j++) {
- a[i + j] += 1;
- }
- }
- return a;
- }
-
- /// CHECK-START: int[] Main.multiply1() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int[] Main.multiply1() BCE (after)
- /// CHECK-NOT: BoundsCheck
- /// CHECK-NOT: Deoptimize
- private static int[] multiply1() {
- int[] a = new int[10];
- try {
- for (int i = 0; i <= 3; i++) {
- for (int j = 0; j <= 3; j++) {
- // Range [0,9]: safe.
- a[i * j] += 1;
- }
- }
- } catch (Exception e) {
- a[0] += 1000;
- }
- return a;
- }
-
- /// CHECK-START: int[] Main.multiply2() BCE (before)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int[] Main.multiply2() BCE (after)
- /// CHECK-DAG: BoundsCheck
- //
- /// CHECK-START: int[] Main.multiply2() BCE (after)
- /// CHECK-NOT: Deoptimize
- static int[] multiply2() {
- int[] a = new int[10];
- try {
- for (int i = -3; i <= 3; i++) {
- for (int j = -3; j <= 3; j++) {
- // Range [-9,9]: unsafe.
- a[i * j] += 1;
- }
- }
- } catch (Exception e) {
- a[0] += 1000;
- }
- return a;
- }
-
- /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: Deoptimize loop:none
- //
- /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
- /// CHECK-NOT: NullCheck loop:{{B\d+}}
- /// CHECK-NOT: ArrayLength loop:{{B\d+}}
- /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
- private static int linearDynamicBCE1(int[] x, int lo, int hi) {
- int result = 0;
- for (int i = lo; i < hi; i++) {
- sResult += x[i];
- }
- return result;
- }
-
- /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: Deoptimize loop:none
- //
- /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
- /// CHECK-NOT: NullCheck loop:{{B\d+}}
- /// CHECK-NOT: ArrayLength loop:{{B\d+}}
- /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
- private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
- int result = 0;
- for (int i = lo; i < hi; i++) {
- sResult += x[offset + i];
- }
- return result;
- }
-
- /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: Deoptimize loop:none
- //
- /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
- /// CHECK-NOT: NullCheck loop:{{B\d+}}
- /// CHECK-NOT: ArrayLength loop:{{B\d+}}
- /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
- private static int wrapAroundDynamicBCE(int[] x) {
- int w = 9;
- int result = 0;
- for (int i = 0; i < 10; i++) {
- result += x[w];
- w = i;
- }
- return result;
- }
-
- /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: Deoptimize loop:none
- //
- /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
- /// CHECK-NOT: NullCheck loop:{{B\d+}}
- /// CHECK-NOT: ArrayLength loop:{{B\d+}}
- /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
- private static int periodicDynamicBCE(int[] x) {
- int k = 0;
- int result = 0;
- for (int i = 0; i < 10; i++) {
- result += x[k];
- k = 1 - k;
- }
- return result;
- }
-
- /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
- /// CHECK-DAG: ArrayGet loop:{{B\d+}}
- /// CHECK-DAG: Deoptimize loop:none
- //
- /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
- /// CHECK-NOT: NullCheck loop:{{B\d+}}
- /// CHECK-NOT: ArrayLength loop:{{B\d+}}
- /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
- static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
- // This loop could be infinite for hi = max int. Since i is also used
- // as subscript, however, dynamic bce can proceed.
- int result = 0;
- for (int i = lo; i <= hi; i++) {
- result += x[i];
- }
- return result;
- }
-
- /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
- /// CHECK-NOT: Deoptimize
- static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
- // As above, but now the index is not used as subscript,
- // and dynamic bce is not applied.
- int result = 0;
- for (int k = 0, i = lo; i <= hi; i++) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
- /// CHECK-NOT: Deoptimize
- static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
- int result = 0;
- // Mix of int and long induction.
- int k = 0;
- for (long i = lo; i < hi; i++) {
- result += x[k++];
- }
- return result;
- }
-
- /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (before)
- /// CHECK-DAG: BoundsCheck loop:<<InnerLoop:B\d+>>
- /// CHECK-DAG: ArrayGet loop:<<InnerLoop>>
- /// CHECK-DAG: If loop:<<InnerLoop>>
- /// CHECK-DAG: If loop:<<OuterLoop:B\d+>>
- /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
- //
- /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
- /// CHECK-DAG: ArrayGet loop:<<InnerLoop:B\d+>>
- /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
- /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
- //
- /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
- /// CHECK-NOT: BoundsCheck
- //
- // No additional top tests were introduced.
- /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
- /// CHECK-DAG: If
- /// CHECK-DAG: If
- /// CHECK-NOT: If
- static int dynamicBCEConstantRange(int[] x) {
- int result = 0;
- for (int i = 2; i <= 6; i++) {
- // Range analysis sees that innermost loop is finite and always taken.
- for (int j = i - 2; j <= i + 2; j++) {
- result += x[j];
- }
- }
- return result;
- }
-
- /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
- /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
- /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
- //
- /// 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-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
- /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
- /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
- /// CHECK: Goto loop:<<Loop>>
- //
- /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
- /// CHECK-DAG: Deoptimize loop:none
- static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
- // Deliberately test array length on a before the loop so that only bounds checks
- // on constant subscripts remain, making them a viable candidate for hoisting.
- if (a.length == 0) {
- return -1;
- }
- // Loop that allows BCE on x[i].
- int result = 0;
- for (int i = lo; i < hi; i++) {
- result += x[i];
- if ((i % 10) != 0) {
- // None of the subscripts inside a conditional are removed by dynamic bce,
- // making them a candidate for deoptimization based on constant indices.
- // Compiler should ensure the array loads are not subsequently hoisted
- // "above" the deoptimization "barrier" on the bounds.
- a[0][i] = 1;
- a[1][i] = 2;
- a[99][i] = 3;
- }
- }
- return result;
- }
-
- /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- // For brevity, just test occurrence of at least one of each in the loop:
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-NOT: ArrayGet loop:<<Loop>>
- //
- /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
- /// CHECK-NOT: NullCheck loop:{{B\d+}}
- /// CHECK-NOT: ArrayLength loop:{{B\d+}}
- /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
- //
- /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
- /// CHECK-DAG: Deoptimize loop:none
- static int dynamicBCEAndConstantIndicesAllPrimTypes(int[] q,
- boolean[] r,
- byte[] s,
- char[] t,
- short[] u,
- int[] v,
- long[] w,
- float[] x,
- double[] y, int lo, int hi) {
- int result = 0;
- for (int i = lo; i < hi; i++) {
- // All constant index array references can be hoisted out of the loop during BCE on q[i].
- result += q[i] + (r[0] ? 1 : 0) + (int) s[0] + (int) t[0] + (int) u[0] + (int) v[0] +
- (int) w[0] + (int) x[0] + (int) y[0];
- }
- return result;
- }
-
- /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (before)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayGet loop:<<Loop>>
- /// CHECK-DAG: NullCheck loop:<<Loop>>
- /// CHECK-DAG: ArrayLength loop:<<Loop>>
- /// CHECK-DAG: BoundsCheck loop:<<Loop>>
- //
- /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
- /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
- /// CHECK-DAG: Deoptimize loop:none
- //
- /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
- /// CHECK-NOT: ArrayLength loop:{{B\d+}}
- /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
- static int dynamicBCEAndConstantIndexRefType(int[] q, Integer[] z, int lo, int hi) {
- int result = 0;
- for (int i = lo; i < hi; i++) {
- // Similar to above, but now implicit call to intValue() may prevent hoisting
- // z[0] itself during BCE on q[i]. Therefore, we just check BCE on q[i].
- result += q[i] + z[0];
- }
- return result;
- }
-
- //
- // Verifier.
- //
-
public static void main(String[] args) {
int[] empty = { };
int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
@@ -1398,244 +679,6 @@
linearTriangularOnParameter(10);
linearTriangularVariationsInnerStrict(10);
linearTriangularVariationsInnerNonStrict(10);
-
- // Sorting.
- int[] sort = { 5, 4, 1, 9, 10, 2, 7, 6, 3, 8 };
- bubble(sort);
- for (int i = 0; i < 10; i++) {
- expectEquals(sort[i], x[i]);
- }
-
- // Periodic adds (1, 3), one at the time.
- expectEquals(0, periodicIdiom(-1));
- for (int tc = 0; tc < 32; tc++) {
- int expected = (tc >> 1) << 2;
- if ((tc & 1) != 0)
- expected += 1;
- expectEquals(expected, periodicIdiom(tc));
- }
-
- // Periodic adds (1, 3), one at the time.
- expectEquals(0, periodicSequence2(-1));
- for (int tc = 0; tc < 32; tc++) {
- int expected = (tc >> 1) << 2;
- if ((tc & 1) != 0)
- expected += 1;
- expectEquals(expected, periodicSequence2(tc));
- }
-
- // Periodic adds (1, 3, 5, 7), all at once.
- expectEquals(0, periodicSequence4(-1));
- for (int tc = 0; tc < 32; tc++) {
- expectEquals(tc * 16, periodicSequence4(tc));
- }
-
- // Large bounds.
- expectEquals(55, justRightUp1());
- expectEquals(55, justRightUp2());
- expectEquals(55, justRightUp3());
- expectEquals(55, justRightDown1());
- expectEquals(55, justRightDown2());
- expectEquals(55, justRightDown3());
- sResult = 0;
- try {
- justOOBUp();
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult = 1;
- }
- expectEquals(1, sResult);
- sResult = 0;
- try {
- justOOBDown();
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult = 1;
- }
- expectEquals(1, sResult);
-
- // Lower bound goes OOB.
- sResult = 0;
- try {
- lowerOOB(x);
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1000, sResult);
-
- // Upper bound goes OOB.
- sResult = 0;
- try {
- upperOOB(x);
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1055, sResult);
-
- // Do while up goes OOB.
- sResult = 0;
- try {
- doWhileUpOOB();
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1055, sResult);
-
- // Do while down goes OOB.
- sResult = 0;
- try {
- doWhileDownOOB();
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1055, sResult);
-
- // Hidden OOB.
- sResult = 0;
- try {
- hiddenOOB1(10); // no OOB
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1, sResult);
- sResult = 0;
- try {
- hiddenOOB1(-2147483648); // OOB
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1001, sResult);
- sResult = 0;
- try {
- hiddenOOB2(1); // no OOB
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1, sResult);
- sResult = 0;
- try {
- hiddenOOB2(2147483647); // OOB
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1002, sResult);
- sResult = 0;
- try {
- hiddenInfiniteOOB();
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1011, sResult);
- sResult = 0;
- try {
- hiddenFiniteOOB();
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1111, sResult);
-
- // Addition.
- {
- int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 };
- int[] a1 = add();
- for (int i = 0; i < 10; i++) {
- expectEquals(a1[i], e1[i]);
- }
- }
-
- // Multiplication.
- {
- int[] e1 = { 7, 1, 2, 2, 1, 0, 2, 0, 0, 1 };
- int[] a1 = multiply1();
- for (int i = 0; i < 10; i++) {
- expectEquals(a1[i], e1[i]);
- }
- int[] e2 = { 1001, 0, 0, 1, 0, 0, 1, 0, 0, 1 };
- int[] a2 = multiply2();
- for (int i = 0; i < 10; i++) {
- expectEquals(a2[i], e2[i]);
- }
- }
-
- // Dynamic BCE.
- sResult = 0;
- try {
- linearDynamicBCE1(x, -1, x.length);
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1000, sResult);
- sResult = 0;
- linearDynamicBCE1(x, 0, x.length);
- expectEquals(55, sResult);
- sResult = 0;
- try {
- linearDynamicBCE1(x, 0, x.length + 1);
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1055, sResult);
-
- // Dynamic BCE with offset.
- sResult = 0;
- try {
- linearDynamicBCE2(x, 0, x.length, -1);
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1000, sResult);
- sResult = 0;
- linearDynamicBCE2(x, 0, x.length, 0);
- expectEquals(55, sResult);
- sResult = 0;
- try {
- linearDynamicBCE2(x, 0, x.length, 1);
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult += 1000;
- }
- expectEquals(1054, sResult);
-
- // Dynamic BCE candidates.
- expectEquals(55, wrapAroundDynamicBCE(x));
- expectEquals(15, periodicDynamicBCE(x));
- expectEquals(55, dynamicBCEPossiblyInfiniteLoop(x, 0, 9));
- expectEquals(55, noDynamicBCEPossiblyInfiniteLoop(x, 0, 9));
- expectEquals(55, noDynamicBCEMixedInductionTypes(x, 0, 10));
- expectEquals(125, dynamicBCEConstantRange(x));
-
- // Dynamic BCE combined with constant indices.
- int[][] a;
- a = new int[0][0];
- expectEquals(-1, dynamicBCEAndConstantIndices(x, a, 0, 10));
- a = new int[100][10];
- expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
- for (int i = 0; i < 10; i++) {
- expectEquals((i % 10) != 0 ? 1 : 0, a[0][i]);
- expectEquals((i % 10) != 0 ? 2 : 0, a[1][i]);
- expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
- }
- a = new int[2][10];
- sResult = 0;
- try {
- expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
- } catch (ArrayIndexOutOfBoundsException e) {
- sResult = 1;
- }
- expectEquals(1, sResult);
- expectEquals(a[0][1], 1);
- expectEquals(a[1][1], 2);
-
- // Dynamic BCE combined with constant indices of all types.
- boolean[] x1 = { true };
- byte[] x2 = { 2 };
- char[] x3 = { 3 };
- short[] x4 = { 4 };
- int[] x5 = { 5 };
- long[] x6 = { 6 };
- float[] x7 = { 7 };
- double[] x8 = { 8 };
- expectEquals(415,
- dynamicBCEAndConstantIndicesAllPrimTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, 0, 10));
- Integer[] x9 = { 9 };
- expectEquals(145, dynamicBCEAndConstantIndexRefType(x, x9, 0, 10));
}
private static void expectEquals(int expected, int result) {
diff --git a/test/530-checker-loops2/expected.txt b/test/530-checker-loops2/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/530-checker-loops2/expected.txt
diff --git a/test/530-checker-loops2/info.txt b/test/530-checker-loops2/info.txt
new file mode 100644
index 0000000..f5d334d
--- /dev/null
+++ b/test/530-checker-loops2/info.txt
@@ -0,0 +1 @@
+Test on loop optimizations.
diff --git a/test/530-checker-loops2/src/Main.java b/test/530-checker-loops2/src/Main.java
new file mode 100644
index 0000000..64be1a2
--- /dev/null
+++ b/test/530-checker-loops2/src/Main.java
@@ -0,0 +1,999 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+//
+// Test on loop optimizations.
+//
+public class Main {
+
+ static int sResult;
+
+ //
+ // Various sequence variables used in bound checks.
+ //
+
+ /// CHECK-START: void Main.bubble(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.bubble(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ // TODO: also CHECK-NOT: Deoptimize, see b/27151190
+ private static void bubble(int[] a) {
+ for (int i = a.length; --i >= 0;) {
+ for (int j = 0; j < i; j++) {
+ if (a[j] > a[j+1]) {
+ int tmp = a[j];
+ a[j] = a[j+1];
+ a[j+1] = tmp;
+ }
+ }
+ }
+ }
+
+ /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int periodicIdiom(int tc) {
+ int[] x = { 1, 3 };
+ // Loop with periodic sequence (0, 1).
+ int k = 0;
+ int result = 0;
+ for (int i = 0; i < tc; i++) {
+ result += x[k];
+ k = 1 - k;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int periodicSequence2(int tc) {
+ int[] x = { 1, 3 };
+ // Loop with periodic sequence (0, 1).
+ int k = 0;
+ int l = 1;
+ int result = 0;
+ for (int i = 0; i < tc; i++) {
+ result += x[k];
+ int t = l;
+ l = k;
+ k = t;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int periodicSequence4(int tc) {
+ int[] x = { 1, 3, 5, 7 };
+ // Loop with periodic sequence (0, 1, 2, 3).
+ int k = 0;
+ int l = 1;
+ int m = 2;
+ int n = 3;
+ int result = 0;
+ for (int i = 0; i < tc; i++) {
+ result += x[k] + x[l] + x[m] + x[n]; // all used at once
+ int t = n;
+ n = k;
+ k = l;
+ l = m;
+ m = t;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justRightUp1() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justRightUp1() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int justRightUp1() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ for (int i = Integer.MAX_VALUE - 10, k = 0; i < Integer.MAX_VALUE; i++) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justRightUp2() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justRightUp2() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int justRightUp2() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ for (int i = Integer.MAX_VALUE - 10; i < Integer.MAX_VALUE; i++) {
+ result += x[i - Integer.MAX_VALUE + 10];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justRightUp3() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justRightUp3() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int justRightUp3() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ for (int i = Integer.MAX_VALUE - 10, k = 0; i <= Integer.MAX_VALUE - 1; i++) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justOOBUp() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBUp() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBUp() BCE (after)
+ /// CHECK-NOT: Deoptimize
+ private static int justOOBUp() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ // Infinite loop!
+ for (int i = Integer.MAX_VALUE - 9, k = 0; i <= Integer.MAX_VALUE; i++) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justRightDown1() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justRightDown1() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int justRightDown1() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ for (int i = Integer.MIN_VALUE + 10, k = 0; i > Integer.MIN_VALUE; i--) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justRightDown2() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justRightDown2() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int justRightDown2() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ for (int i = Integer.MIN_VALUE + 10; i > Integer.MIN_VALUE; i--) {
+ result += x[Integer.MAX_VALUE + i];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justRightDown3() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justRightDown3() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int justRightDown3() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ for (int i = Integer.MIN_VALUE + 10, k = 0; i >= Integer.MIN_VALUE + 1; i--) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.justOOBDown() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBDown() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int Main.justOOBDown() BCE (after)
+ /// CHECK-NOT: Deoptimize
+ private static int justOOBDown() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int result = 0;
+ // Infinite loop!
+ for (int i = Integer.MIN_VALUE + 9, k = 0; i >= Integer.MIN_VALUE; i--) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
+ /// CHECK-NOT: Deoptimize
+ private static void lowerOOB(int[] x) {
+ // OOB!
+ for (int i = -1; i < x.length; i++) {
+ sResult += x[i];
+ }
+ }
+
+ /// CHECK-START: void Main.upperOOB(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
+ /// CHECK-NOT: Deoptimize
+ private static void upperOOB(int[] x) {
+ // OOB!
+ for (int i = 0; i <= x.length; i++) {
+ sResult += x[i];
+ }
+ }
+
+ /// CHECK-START: void Main.doWhileUpOOB() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
+ /// CHECK-NOT: Deoptimize
+ private static void doWhileUpOOB() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int i = 0;
+ // OOB!
+ do {
+ sResult += x[i++];
+ } while (i <= x.length);
+ }
+
+ /// CHECK-START: void Main.doWhileDownOOB() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
+ /// CHECK-NOT: Deoptimize
+ private static void doWhileDownOOB() {
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+ int i = x.length - 1;
+ // OOB!
+ do {
+ sResult += x[i--];
+ } while (-1 <= i);
+ }
+
+ /// CHECK-START: void Main.hiddenOOB1(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
+ /// CHECK-DAG: Deoptimize
+ //
+ /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static void hiddenOOB1(int lo) {
+ int[] a = { 1 } ;
+ for (int i = lo; i <= 10; i++) {
+ // 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];
+ }
+ }
+ }
+
+ /// CHECK-START: void Main.hiddenOOB2(int) BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
+ /// CHECK-DAG: Deoptimize
+ //
+ /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static void hiddenOOB2(int hi) {
+ int[] a = { 1 } ;
+ for (int i = 0; i < hi; i++) {
+ // 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.hiddenInfiniteOOB() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
+ /// CHECK-NOT: Deoptimize
+ private static void hiddenInfiniteOOB() {
+ int[] a = { 11 } ;
+ for (int i = -1; i <= 0; i++) {
+ // Dangerous loop where careless static range analysis would yield a safe upper bound
+ // of -3. In reality, due to arithmetic wrap-around (when i = -1, j <= 2147483647;
+ // whereas when i = 0, j <= -3), this is an infinite loop that goes OOB.
+ for (int j = -3; j <= 2147483646 * i - 3; j++) {
+ sResult += a[j + 3];
+ }
+ }
+ }
+
+ /// CHECK-START: void Main.hiddenFiniteOOB() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
+ /// CHECK-DAG: Deoptimize
+ //
+ /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ private static void hiddenFiniteOOB() {
+ int[] a = { 111 } ;
+ 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];
+ }
+ }
+ }
+
+ /// CHECK-START: int[] Main.add() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int[] Main.add() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int[] add() {
+ int[] a = new int[10];
+ for (int i = 0; i <= 3; i++) {
+ for (int j = 0; j <= 6; j++) {
+ a[i + j] += 1;
+ }
+ }
+ return a;
+ }
+
+ /// CHECK-START: int[] Main.multiply1() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int[] Main.multiply1() BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ /// CHECK-NOT: Deoptimize
+ private static int[] multiply1() {
+ int[] a = new int[10];
+ try {
+ for (int i = 0; i <= 3; i++) {
+ for (int j = 0; j <= 3; j++) {
+ // Range [0,9]: safe.
+ a[i * j] += 1;
+ }
+ }
+ } catch (Exception e) {
+ a[0] += 1000;
+ }
+ return a;
+ }
+
+ /// CHECK-START: int[] Main.multiply2() BCE (before)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int[] Main.multiply2() BCE (after)
+ /// CHECK-DAG: BoundsCheck
+ //
+ /// CHECK-START: int[] Main.multiply2() BCE (after)
+ /// CHECK-NOT: Deoptimize
+ static int[] multiply2() {
+ int[] a = new int[10];
+ try {
+ for (int i = -3; i <= 3; i++) {
+ for (int j = -3; j <= 3; j++) {
+ // Range [-9,9]: unsafe.
+ a[i * j] += 1;
+ }
+ }
+ } catch (Exception e) {
+ a[0] += 1000;
+ }
+ return a;
+ }
+
+ /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ private static int linearDynamicBCE1(int[] x, int lo, int hi) {
+ int result = 0;
+ for (int i = lo; i < hi; i++) {
+ sResult += x[i];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
+ int result = 0;
+ for (int i = lo; i < hi; i++) {
+ sResult += x[offset + i];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ private static int wrapAroundDynamicBCE(int[] x) {
+ int w = 9;
+ int result = 0;
+ for (int i = 0; i < 10; i++) {
+ result += x[w];
+ w = i;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ private static int periodicDynamicBCE(int[] x) {
+ int k = 0;
+ int result = 0;
+ for (int i = 0; i < 10; i++) {
+ result += x[k];
+ k = 1 - k;
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:{{B\d+}}
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
+ // This loop could be infinite for hi = max int. Since i is also used
+ // as subscript, however, dynamic bce can proceed.
+ int result = 0;
+ for (int i = lo; i <= hi; i++) {
+ result += x[i];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
+ /// CHECK-NOT: Deoptimize
+ static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
+ // As above, but now the index is not used as subscript,
+ // and dynamic bce is not applied.
+ int result = 0;
+ for (int k = 0, i = lo; i <= hi; i++) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
+ /// CHECK-NOT: Deoptimize
+ static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
+ int result = 0;
+ // Mix of int and long induction.
+ int k = 0;
+ for (long i = lo; i < hi; i++) {
+ result += x[k++];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (before)
+ /// CHECK-DAG: BoundsCheck loop:<<InnerLoop:B\d+>>
+ /// CHECK-DAG: ArrayGet loop:<<InnerLoop>>
+ /// CHECK-DAG: If loop:<<InnerLoop>>
+ /// CHECK-DAG: If loop:<<OuterLoop:B\d+>>
+ /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
+ //
+ /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:<<InnerLoop:B\d+>>
+ /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
+ /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
+ //
+ /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
+ /// CHECK-NOT: BoundsCheck
+ //
+ // No additional top tests were introduced.
+ /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
+ /// CHECK-DAG: If
+ /// CHECK-DAG: If
+ /// CHECK-NOT: If
+ static int dynamicBCEConstantRange(int[] x) {
+ int result = 0;
+ for (int i = 2; i <= 6; i++) {
+ // Range analysis sees that innermost loop is finite and always taken.
+ for (int j = i - 2; j <= i + 2; j++) {
+ result += x[j];
+ }
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ //
+ /// 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-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
+ /// CHECK: Goto loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
+ /// CHECK-DAG: Deoptimize loop:none
+ static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
+ // Deliberately test array length on a before the loop so that only bounds checks
+ // on constant subscripts remain, making them a viable candidate for hoisting.
+ if (a.length == 0) {
+ return -1;
+ }
+ // Loop that allows BCE on x[i].
+ int result = 0;
+ for (int i = lo; i < hi; i++) {
+ result += x[i];
+ if ((i % 10) != 0) {
+ // None of the subscripts inside a conditional are removed by dynamic bce,
+ // making them a candidate for deoptimization based on constant indices.
+ // Compiler should ensure the array loads are not subsequently hoisted
+ // "above" the deoptimization "barrier" on the bounds.
+ a[0][i] = 1;
+ a[1][i] = 2;
+ a[99][i] = 3;
+ }
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ // For brevity, just test occurrence of at least one of each in the loop:
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-NOT: ArrayGet loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
+ /// CHECK-NOT: NullCheck loop:{{B\d+}}
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
+ /// CHECK-DAG: Deoptimize loop:none
+ static int dynamicBCEAndConstantIndicesAllPrimTypes(int[] q,
+ boolean[] r,
+ byte[] s,
+ char[] t,
+ short[] u,
+ int[] v,
+ long[] w,
+ float[] x,
+ double[] y, int lo, int hi) {
+ int result = 0;
+ for (int i = lo; i < hi; i++) {
+ // All constant index array references can be hoisted out of the loop during BCE on q[i].
+ result += q[i] + (r[0] ? 1 : 0) + (int) s[0] + (int) t[0] + (int) u[0] + (int) v[0] +
+ (int) w[0] + (int) x[0] + (int) y[0];
+ }
+ return result;
+ }
+
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (before)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayGet loop:<<Loop>>
+ /// CHECK-DAG: NullCheck loop:<<Loop>>
+ /// CHECK-DAG: ArrayLength loop:<<Loop>>
+ /// CHECK-DAG: BoundsCheck loop:<<Loop>>
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
+ /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
+ /// CHECK-DAG: Deoptimize loop:none
+ //
+ /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
+ /// CHECK-NOT: ArrayLength loop:{{B\d+}}
+ /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
+ static int dynamicBCEAndConstantIndexRefType(int[] q, Integer[] z, int lo, int hi) {
+ int result = 0;
+ for (int i = lo; i < hi; i++) {
+ // Similar to above, but now implicit call to intValue() may prevent hoisting
+ // z[0] itself during BCE on q[i]. Therefore, we just check BCE on q[i].
+ result += q[i] + z[0];
+ }
+ return result;
+ }
+
+ //
+ // Verifier.
+ //
+
+ public static void main(String[] args) {
+ // Set to run expensive tests for correctness too.
+ boolean HEAVY = false;
+
+ int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+
+ // Sorting.
+ int[] sort = { 5, 4, 1, 9, 10, 2, 7, 6, 3, 8 };
+ bubble(sort);
+ for (int i = 0; i < 10; i++) {
+ expectEquals(sort[i], x[i]);
+ }
+
+ // Periodic adds (1, 3), one at the time.
+ expectEquals(0, periodicIdiom(-1));
+ for (int tc = 0; tc < 32; tc++) {
+ int expected = (tc >> 1) << 2;
+ if ((tc & 1) != 0)
+ expected += 1;
+ expectEquals(expected, periodicIdiom(tc));
+ }
+
+ // Periodic adds (1, 3), one at the time.
+ expectEquals(0, periodicSequence2(-1));
+ for (int tc = 0; tc < 32; tc++) {
+ int expected = (tc >> 1) << 2;
+ if ((tc & 1) != 0)
+ expected += 1;
+ expectEquals(expected, periodicSequence2(tc));
+ }
+
+ // Periodic adds (1, 3, 5, 7), all at once.
+ expectEquals(0, periodicSequence4(-1));
+ for (int tc = 0; tc < 32; tc++) {
+ expectEquals(tc * 16, periodicSequence4(tc));
+ }
+
+ // Large bounds.
+ expectEquals(55, justRightUp1());
+ expectEquals(55, justRightUp2());
+ expectEquals(55, justRightUp3());
+ expectEquals(55, justRightDown1());
+ expectEquals(55, justRightDown2());
+ expectEquals(55, justRightDown3());
+ sResult = 0;
+ try {
+ justOOBUp();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult = 1;
+ }
+ expectEquals(1, sResult);
+ sResult = 0;
+ try {
+ justOOBDown();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult = 1;
+ }
+ expectEquals(1, sResult);
+
+ // Lower bound goes OOB.
+ sResult = 0;
+ try {
+ lowerOOB(x);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1000, sResult);
+
+ // Upper bound goes OOB.
+ sResult = 0;
+ try {
+ upperOOB(x);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1055, sResult);
+
+ // Do while up goes OOB.
+ sResult = 0;
+ try {
+ doWhileUpOOB();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1055, sResult);
+
+ // Do while down goes OOB.
+ sResult = 0;
+ try {
+ doWhileDownOOB();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1055, sResult);
+
+ // Hidden OOB.
+ sResult = 0;
+ try {
+ hiddenOOB1(10); // no OOB
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1, sResult);
+ sResult = 0;
+ try {
+ hiddenOOB1(-2147483648); // OOB
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1001, sResult);
+ sResult = 0;
+ try {
+ hiddenOOB2(1); // no OOB
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1, sResult);
+ if (HEAVY) {
+ sResult = 0;
+ try {
+ hiddenOOB2(2147483647); // OOB
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1002, sResult);
+ }
+ sResult = 0;
+ try {
+ hiddenInfiniteOOB();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1011, sResult);
+ sResult = 0;
+ try {
+ hiddenFiniteOOB();
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1111, sResult);
+
+ // Addition.
+ {
+ int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 };
+ int[] a1 = add();
+ for (int i = 0; i < 10; i++) {
+ expectEquals(a1[i], e1[i]);
+ }
+ }
+
+ // Multiplication.
+ {
+ int[] e1 = { 7, 1, 2, 2, 1, 0, 2, 0, 0, 1 };
+ int[] a1 = multiply1();
+ for (int i = 0; i < 10; i++) {
+ expectEquals(a1[i], e1[i]);
+ }
+ int[] e2 = { 1001, 0, 0, 1, 0, 0, 1, 0, 0, 1 };
+ int[] a2 = multiply2();
+ for (int i = 0; i < 10; i++) {
+ expectEquals(a2[i], e2[i]);
+ }
+ }
+
+ // Dynamic BCE.
+ sResult = 0;
+ try {
+ linearDynamicBCE1(x, -1, x.length);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1000, sResult);
+ sResult = 0;
+ linearDynamicBCE1(x, 0, x.length);
+ expectEquals(55, sResult);
+ sResult = 0;
+ try {
+ linearDynamicBCE1(x, 0, x.length + 1);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1055, sResult);
+
+ // Dynamic BCE with offset.
+ sResult = 0;
+ try {
+ linearDynamicBCE2(x, 0, x.length, -1);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1000, sResult);
+ sResult = 0;
+ linearDynamicBCE2(x, 0, x.length, 0);
+ expectEquals(55, sResult);
+ sResult = 0;
+ try {
+ linearDynamicBCE2(x, 0, x.length, 1);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult += 1000;
+ }
+ expectEquals(1054, sResult);
+
+ // Dynamic BCE candidates.
+ expectEquals(55, wrapAroundDynamicBCE(x));
+ expectEquals(15, periodicDynamicBCE(x));
+ expectEquals(55, dynamicBCEPossiblyInfiniteLoop(x, 0, 9));
+ expectEquals(55, noDynamicBCEPossiblyInfiniteLoop(x, 0, 9));
+ expectEquals(55, noDynamicBCEMixedInductionTypes(x, 0, 10));
+ expectEquals(125, dynamicBCEConstantRange(x));
+
+ // Dynamic BCE combined with constant indices.
+ int[][] a;
+ a = new int[0][0];
+ expectEquals(-1, dynamicBCEAndConstantIndices(x, a, 0, 10));
+ a = new int[100][10];
+ expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
+ for (int i = 0; i < 10; i++) {
+ expectEquals((i % 10) != 0 ? 1 : 0, a[0][i]);
+ expectEquals((i % 10) != 0 ? 2 : 0, a[1][i]);
+ expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
+ }
+ a = new int[2][10];
+ sResult = 0;
+ try {
+ expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
+ } catch (ArrayIndexOutOfBoundsException e) {
+ sResult = 1;
+ }
+ expectEquals(1, sResult);
+ expectEquals(a[0][1], 1);
+ expectEquals(a[1][1], 2);
+
+ // Dynamic BCE combined with constant indices of all types.
+ boolean[] x1 = { true };
+ byte[] x2 = { 2 };
+ char[] x3 = { 3 };
+ short[] x4 = { 4 };
+ int[] x5 = { 5 };
+ long[] x6 = { 6 };
+ float[] x7 = { 7 };
+ double[] x8 = { 8 };
+ expectEquals(415,
+ dynamicBCEAndConstantIndicesAllPrimTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, 0, 10));
+ Integer[] x9 = { 9 };
+ expectEquals(145, dynamicBCEAndConstantIndexRefType(x, x9, 0, 10));
+ }
+
+ private static void expectEquals(int expected, int result) {
+ if (expected != result) {
+ throw new Error("Expected: " + expected + ", found: " + result);
+ }
+ }
+}
diff --git a/tools/libcore_failures.txt b/tools/libcore_failures.txt
index e6394a9..46100ae 100644
--- a/tools/libcore_failures.txt
+++ b/tools/libcore_failures.txt
@@ -208,13 +208,6 @@
"org.apache.harmony.tests.java.util.TimerTaskTest#test_scheduledExecutionTime"]
},
{
- description: "'cat -' does not work anymore",
- result: EXEC_FAILED,
- bug: 26395656,
- modes: [device],
- names: ["org.apache.harmony.tests.java.lang.ProcessTest#test_getOutputStream"]
-},
-{
description: "Missing resource in classpath",
result: EXEC_FAILED,
modes: [device],