blob: 4397f679b95d4ad99a469e620e3776fbcdc3267a [file] [log] [blame]
/*
* 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);
}
}
}