OSDN Git Service

Split 530-checker-loops to please our run-test file size limit.
authorNicolas Geoffray <ngeoffray@google.com>
Thu, 25 Feb 2016 12:40:27 +0000 (12:40 +0000)
committerNicolas Geoffray <ngeoffray@google.com>
Thu, 25 Feb 2016 12:42:55 +0000 (12:42 +0000)
Change-Id: Ib03303435918b333691625f3999b937072f8ec31

test/530-checker-loops/src/Main.java
test/530-checker-loops2/expected.txt [new file with mode: 0644]
test/530-checker-loops2/info.txt [new file with mode: 0644]
test/530-checker-loops2/src/Main.java [new file with mode: 0644]

index 0c32491..8633745 100644 (file)
@@ -605,729 +605,7 @@ public class Main {
     }
   }
 
-  /// 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[] empty = { };
     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
 
@@ -1401,246 +679,6 @@ public class Main {
     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);
-    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) {
diff --git a/test/530-checker-loops2/expected.txt b/test/530-checker-loops2/expected.txt
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/test/530-checker-loops2/info.txt b/test/530-checker-loops2/info.txt
new file mode 100644 (file)
index 0000000..f5d334d
--- /dev/null
@@ -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 (file)
index 0000000..64be1a2
--- /dev/null
@@ -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);
+    }
+  }
+}