/// 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 privatestaticint 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 privatestaticint 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 privatestaticint 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.periodicXorSequence(int) BCE (before) /// CHECK-DAG: BoundsCheck // /// CHECK-START: int Main.periodicXorSequence(int) BCE (after) /// CHECK-NOT: BoundsCheck /// CHECK-NOT: Deoptimize privatestaticint periodicXorSequence(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;
} 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 privatestaticint 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 privatestaticint 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 privatestaticint 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 privatestaticint 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 privatestaticint 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 privatestaticint 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 privatestaticint 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 privatestaticint 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.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 privatestaticvoid 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. 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 privatestaticvoid 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. for (int j = 6; j > i + 5; j--) {
sResult += a[j - 6];
}
}
}
/// CHECK-START: void Main.hiddenOOB3(int) BCE (before) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.hiddenOOB3(int) BCE (after) /// CHECK-DAG: Deoptimize // /// CHECK-START: void Main.hiddenOOB3(int) BCE (after) /// CHECK-NOT: BoundsCheck privatestaticvoid hiddenOOB3(int hi) { int[] a = { 11 } ; for (int i = -1; i <= hi; i++) { // Dangerous loop where careless static range analysis would yield strict lower bound // on index j of 0. For large i, the initial value of j becomes really negative due // to arithmetic wrap-around, causing OOB. for (int j = i + 1; j < 1; j++) {
sResult += a[j];
}
}
}
/// CHECK-START: void Main.hiddenInfiniteOOB() BCE (before) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after) /// CHECK-NOT: Deoptimize privatestaticvoid 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 privatestaticvoid 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. for (int j = -4; j < 2147483646 * i - 3; j++) {
sResult += a[j + 4];
}
}
}
/// CHECK-START: void Main.inductionOOB(int[]) BCE (before) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.inductionOOB(int[]) BCE (after) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.inductionOOB(int[]) BCE (after) /// CHECK-NOT: Deoptimize privatestaticvoid inductionOOB(int[] a) { // Careless range analysis would remove the bounds check. // However, the narrower induction b wraps around arithmetically // before it reaches the end of arrays longer than 127. byte b = 0; for (int i = 0; i < a.length; i++) {
a[b++] = i;
}
}
/// CHECK-START: void Main.controlOOB(int[]) BCE (before) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.controlOOB(int[]) BCE (after) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.controlOOB(int[]) BCE (after) /// CHECK-NOT: Deoptimize privatestaticvoid controlOOB(int[] a) { // As above, but now the loop control also wraps around. for (byte i = 0; i < a.length; i++) {
a[i] = -i;
}
}
/// CHECK-START: void Main.conversionOOB(int[]) BCE (before) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.conversionOOB(int[]) BCE (after) /// CHECK-DAG: BoundsCheck // /// CHECK-START: void Main.conversionOOB(int[]) BCE (after) /// CHECK-NOT: Deoptimize privatestaticvoid conversionOOB(int[] a) { // As above, but with wrap around caused by an explicit conversion. for (int i = 0; i < a.length; ) {
a[i] = i;
i = (byte) (i + 1);
}
}
/// CHECK-START: int Main.doNotHoist(int[]) BCE (before) /// CHECK-DAG: BoundsCheck // /// CHECK-START: int Main.doNotHoist(int[]) BCE (after) /// CHECK-NOT: BoundsCheck publicstaticint doNotHoist(int[] a) { int n = a.length; int x = 0; // BCE applies, but hoisting would crash the loop. for (int i = -10000; i < 10000; i++) { for (int j = 0; j <= 1; j++) { if (0 <= i && i < n)
x += a[i];
}
} return x;
}
/// CHECK-START: int Main.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+}} privatestaticint 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+}} privatestaticint 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+}} privatestaticint 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+}} privatestaticint 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+}} staticint 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 staticint 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 staticint 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 staticint 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 staticint 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[1][i] = 1;
a[2][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 staticint 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+}} staticint 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;
}
/// CHECK-START: int Main.shortIndex(int[]) BCE (before) /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> /// CHECK-DAG: BoundsCheck loop:<<Loop>> // /// CHECK-START: int Main.shortIndex(int[]) BCE (after) /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>> /// CHECK-DAG: BoundsCheck loop:<<Loop>> // /// CHECK-START: int Main.shortIndex(int[]) BCE (after) /// CHECK-NOT: Deoptimize staticint shortIndex(int[] a) { int r = 0; // Make sure short/int conversions compiles well (b/32193474). for (short i = 1; i < 10; i++) { int ki = i - 1;
r += a[ki] + a[i];
} return r;
}
// // Verifier. //
publicstaticvoid main(String[] args) { // Set to run expensive tests for correctness too. boolean HEAVY = false;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.