/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ public class Main { /** * Method with an outer countable loop and an inner do-while loop. * Since all work is done in the header of the inner loop, any invariant hoisting * and deopting should be done in its proper loop preheader, not the true-block * of the newly generated taken-test after dynamic BCE. */ public static int doit(int[][] x, int j) { float f = 0; int acc = 0; for (int i = 0; i < 2; i++) { // The full body of a do-while loop is the loop header. do { // Some "noise" to avoid hoisting the array reference // before the dynamic BCE phase runs. f++; // The invariant array reference with corresponding bounds check // is a candidate for hoisting when dynamic BCE runs. If it is // not moved to the proper loop preheader, the wrong values // cause the test to fail. acc += x[i][i]; } while (++j < i); } return acc; } /** * Single countable loop with a clear header and a loop body. In this case, * after dynamic bce, some invariant hoisting and deopting must go to the * proper loop preheader and some must go to the true-block. */ public static int foo(int[] x, int[] y, int n) { float f = 0; int acc = 0; int i = 0; while (true) { // This part is the loop header. // Some "noise" to avoid hoisting the array reference // before the dynamic BCE phase runs. f++; // The invariant array reference with corresponding bounds check // is a candidate for hoisting when dynamic BCE runs. If it is // not moved to the proper loop preheader, the wrong values // cause the test to fail. acc += y[0]; if (++i > n) break; // From here on, this part is the loop body. // The unit-stride array reference is a candidate for dynamic BCE. // The deopting appears in the true-block. acc += x[i]; } return acc; } /** * An artificial example with an inconsistent phi structure during * dynamic bce that is corrected afterwards. Note that only the last * assignment is really live, but the other statements set up an * interesting phi structure. */ private static int doit(int[] z) { int a = 0; for (int i = 0; i < 10; ++i) { for (int j = i; j < 10; ++j) { a = z[i]; for (int k = 0; k < 10; ++k) { a += z[k]; a = z[i]; } } } return a; } /** * Example shows that we can hoist ArrayGet to pre-header only if * its execution is guaranteed. */ public static int hoistcheck(int[] c) { int i = 0, i2 = 0, i3 = 0, k = 0; int n = c.length; for (i = -100000000; i < 20; i += 10000000) { i3 = i; i2 = 0; while (i2++ < 1) { if (i3 >= 0 && i3 < n) { k += c[i3]; } } } return k; } public static void main(String args[]) { int[][] x = new int[2][2]; int y; x[0][0] = 1; x[1][1] = 2; expectEquals(8, doit(x, -6)); expectEquals(7, doit(x, -5)); expectEquals(6, doit(x, -4)); expectEquals(5, doit(x, -3)); expectEquals(4, doit(x, -2)); expectEquals(3, doit(x, -1)); expectEquals(3, doit(x, 0)); expectEquals(3, doit(x, 1)); expectEquals(3, doit(x, 22)); int a[] = { 1, 2, 3, 5 }; int b[] = { 7 }; expectEquals(7, foo(a, b, -1)); expectEquals(7, foo(a, b, 0)); expectEquals(16, foo(a, b, 1)); expectEquals(26, foo(a, b, 2)); expectEquals(38, foo(a, b, 3)); int[] z = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; expectEquals(10, doit(z)); int c[] = { 1, 2, 3, 5 }; expectEquals(1, hoistcheck(c)); System.out.println("passed"); } private static void expectEquals(int expected, int result) { if (expected != result) { throw new Error("Expected: " + expected + ", found: " + result); } } }