xref: /aosp_15_r20/art/test/562-bce-preheader/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker public class Main {
18*795d594fSAndroid Build Coastguard Worker 
19*795d594fSAndroid Build Coastguard Worker   /**
20*795d594fSAndroid Build Coastguard Worker    * Method with an outer countable loop and an inner do-while loop.
21*795d594fSAndroid Build Coastguard Worker    * Since all work is done in the header of the inner loop, any invariant hoisting
22*795d594fSAndroid Build Coastguard Worker    * and deopting should be done in its proper loop preheader, not the true-block
23*795d594fSAndroid Build Coastguard Worker    * of the newly generated taken-test after dynamic BCE.
24*795d594fSAndroid Build Coastguard Worker    */
doit(int[][] x, int j)25*795d594fSAndroid Build Coastguard Worker   public static int doit(int[][] x, int j) {
26*795d594fSAndroid Build Coastguard Worker     float f = 0;
27*795d594fSAndroid Build Coastguard Worker     int acc = 0;
28*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 2; i++) {
29*795d594fSAndroid Build Coastguard Worker       // The full body of a do-while loop is the loop header.
30*795d594fSAndroid Build Coastguard Worker       do {
31*795d594fSAndroid Build Coastguard Worker         // Some "noise" to avoid hoisting the array reference
32*795d594fSAndroid Build Coastguard Worker         // before the dynamic BCE phase runs.
33*795d594fSAndroid Build Coastguard Worker         f++;
34*795d594fSAndroid Build Coastguard Worker         // The invariant array reference with corresponding bounds check
35*795d594fSAndroid Build Coastguard Worker         // is a candidate for hoisting when dynamic BCE runs. If it is
36*795d594fSAndroid Build Coastguard Worker         // not moved to the proper loop preheader, the wrong values
37*795d594fSAndroid Build Coastguard Worker         // cause the test to fail.
38*795d594fSAndroid Build Coastguard Worker         acc += x[i][i];
39*795d594fSAndroid Build Coastguard Worker       } while (++j < i);
40*795d594fSAndroid Build Coastguard Worker     }
41*795d594fSAndroid Build Coastguard Worker     return acc;
42*795d594fSAndroid Build Coastguard Worker   }
43*795d594fSAndroid Build Coastguard Worker 
44*795d594fSAndroid Build Coastguard Worker   /**
45*795d594fSAndroid Build Coastguard Worker    * Single countable loop with a clear header and a loop body. In this case,
46*795d594fSAndroid Build Coastguard Worker    * after dynamic bce, some invariant hoisting and deopting must go to the
47*795d594fSAndroid Build Coastguard Worker    * proper loop preheader and some must go to the true-block.
48*795d594fSAndroid Build Coastguard Worker    */
foo(int[] x, int[] y, int n)49*795d594fSAndroid Build Coastguard Worker   public static int foo(int[] x, int[] y, int n) {
50*795d594fSAndroid Build Coastguard Worker     float f = 0;
51*795d594fSAndroid Build Coastguard Worker     int acc = 0;
52*795d594fSAndroid Build Coastguard Worker     int i = 0;
53*795d594fSAndroid Build Coastguard Worker     while (true) {
54*795d594fSAndroid Build Coastguard Worker       // This part is the loop header.
55*795d594fSAndroid Build Coastguard Worker       // Some "noise" to avoid hoisting the array reference
56*795d594fSAndroid Build Coastguard Worker       // before the dynamic BCE phase runs.
57*795d594fSAndroid Build Coastguard Worker       f++;
58*795d594fSAndroid Build Coastguard Worker       // The invariant array reference with corresponding bounds check
59*795d594fSAndroid Build Coastguard Worker       // is a candidate for hoisting when dynamic BCE runs. If it is
60*795d594fSAndroid Build Coastguard Worker       // not moved to the proper loop preheader, the wrong values
61*795d594fSAndroid Build Coastguard Worker       // cause the test to fail.
62*795d594fSAndroid Build Coastguard Worker       acc += y[0];
63*795d594fSAndroid Build Coastguard Worker       if (++i > n)
64*795d594fSAndroid Build Coastguard Worker         break;
65*795d594fSAndroid Build Coastguard Worker       // From here on, this part is the loop body.
66*795d594fSAndroid Build Coastguard Worker       // The unit-stride array reference is a candidate for dynamic BCE.
67*795d594fSAndroid Build Coastguard Worker       // The deopting appears in the true-block.
68*795d594fSAndroid Build Coastguard Worker       acc += x[i];
69*795d594fSAndroid Build Coastguard Worker     }
70*795d594fSAndroid Build Coastguard Worker     return acc;
71*795d594fSAndroid Build Coastguard Worker   }
72*795d594fSAndroid Build Coastguard Worker 
73*795d594fSAndroid Build Coastguard Worker   /**
74*795d594fSAndroid Build Coastguard Worker    * An artificial example with an inconsistent phi structure during
75*795d594fSAndroid Build Coastguard Worker    * dynamic bce that is corrected afterwards. Note that only the last
76*795d594fSAndroid Build Coastguard Worker    * assignment is really live, but the other statements set up an
77*795d594fSAndroid Build Coastguard Worker    * interesting phi structure.
78*795d594fSAndroid Build Coastguard Worker    */
doit(int[] z)79*795d594fSAndroid Build Coastguard Worker   private static int doit(int[] z) {
80*795d594fSAndroid Build Coastguard Worker     int a = 0;
81*795d594fSAndroid Build Coastguard Worker     for (int i = 0; i < 10; ++i) {
82*795d594fSAndroid Build Coastguard Worker       for (int j = i; j < 10; ++j) {
83*795d594fSAndroid Build Coastguard Worker         a = z[i];
84*795d594fSAndroid Build Coastguard Worker         for (int k = 0; k < 10; ++k) {
85*795d594fSAndroid Build Coastguard Worker           a += z[k];
86*795d594fSAndroid Build Coastguard Worker           a = z[i];
87*795d594fSAndroid Build Coastguard Worker         }
88*795d594fSAndroid Build Coastguard Worker       }
89*795d594fSAndroid Build Coastguard Worker     }
90*795d594fSAndroid Build Coastguard Worker     return a;
91*795d594fSAndroid Build Coastguard Worker   }
92*795d594fSAndroid Build Coastguard Worker 
93*795d594fSAndroid Build Coastguard Worker   /**
94*795d594fSAndroid Build Coastguard Worker    * Example shows that we can hoist ArrayGet to pre-header only if
95*795d594fSAndroid Build Coastguard Worker    * its execution is guaranteed.
96*795d594fSAndroid Build Coastguard Worker    */
hoistcheck(int[] c)97*795d594fSAndroid Build Coastguard Worker   public static int hoistcheck(int[] c) {
98*795d594fSAndroid Build Coastguard Worker     int i = 0, i2 = 0, i3 = 0, k = 0;
99*795d594fSAndroid Build Coastguard Worker     int n = c.length;
100*795d594fSAndroid Build Coastguard Worker     for (i = -100000000; i < 20; i += 10000000) {
101*795d594fSAndroid Build Coastguard Worker       i3 = i;
102*795d594fSAndroid Build Coastguard Worker       i2 = 0;
103*795d594fSAndroid Build Coastguard Worker       while (i2++ < 1) {
104*795d594fSAndroid Build Coastguard Worker         if (i3 >= 0 && i3 < n) {
105*795d594fSAndroid Build Coastguard Worker           k += c[i3];
106*795d594fSAndroid Build Coastguard Worker         }
107*795d594fSAndroid Build Coastguard Worker       }
108*795d594fSAndroid Build Coastguard Worker     }
109*795d594fSAndroid Build Coastguard Worker     return k;
110*795d594fSAndroid Build Coastguard Worker   }
111*795d594fSAndroid Build Coastguard Worker 
main(String args[])112*795d594fSAndroid Build Coastguard Worker   public static void main(String args[]) {
113*795d594fSAndroid Build Coastguard Worker     int[][] x = new int[2][2];
114*795d594fSAndroid Build Coastguard Worker     int y;
115*795d594fSAndroid Build Coastguard Worker 
116*795d594fSAndroid Build Coastguard Worker     x[0][0] = 1;
117*795d594fSAndroid Build Coastguard Worker     x[1][1] = 2;
118*795d594fSAndroid Build Coastguard Worker 
119*795d594fSAndroid Build Coastguard Worker     expectEquals(8, doit(x, -6));
120*795d594fSAndroid Build Coastguard Worker     expectEquals(7, doit(x, -5));
121*795d594fSAndroid Build Coastguard Worker     expectEquals(6, doit(x, -4));
122*795d594fSAndroid Build Coastguard Worker     expectEquals(5, doit(x, -3));
123*795d594fSAndroid Build Coastguard Worker     expectEquals(4, doit(x, -2));
124*795d594fSAndroid Build Coastguard Worker     expectEquals(3, doit(x, -1));
125*795d594fSAndroid Build Coastguard Worker     expectEquals(3, doit(x,  0));
126*795d594fSAndroid Build Coastguard Worker     expectEquals(3, doit(x,  1));
127*795d594fSAndroid Build Coastguard Worker     expectEquals(3, doit(x, 22));
128*795d594fSAndroid Build Coastguard Worker 
129*795d594fSAndroid Build Coastguard Worker     int a[] = { 1, 2, 3, 5 };
130*795d594fSAndroid Build Coastguard Worker     int b[] = { 7 };
131*795d594fSAndroid Build Coastguard Worker 
132*795d594fSAndroid Build Coastguard Worker     expectEquals(7,  foo(a, b, -1));
133*795d594fSAndroid Build Coastguard Worker     expectEquals(7,  foo(a, b,  0));
134*795d594fSAndroid Build Coastguard Worker     expectEquals(16, foo(a, b,  1));
135*795d594fSAndroid Build Coastguard Worker     expectEquals(26, foo(a, b,  2));
136*795d594fSAndroid Build Coastguard Worker     expectEquals(38, foo(a, b,  3));
137*795d594fSAndroid Build Coastguard Worker 
138*795d594fSAndroid Build Coastguard Worker     int[] z = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
139*795d594fSAndroid Build Coastguard Worker     expectEquals(10, doit(z));
140*795d594fSAndroid Build Coastguard Worker 
141*795d594fSAndroid Build Coastguard Worker     int c[] = { 1, 2, 3, 5 };
142*795d594fSAndroid Build Coastguard Worker     expectEquals(1, hoistcheck(c));
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker     System.out.println("passed");
145*795d594fSAndroid Build Coastguard Worker   }
146*795d594fSAndroid Build Coastguard Worker 
expectEquals(int expected, int result)147*795d594fSAndroid Build Coastguard Worker   private static void expectEquals(int expected, int result) {
148*795d594fSAndroid Build Coastguard Worker     if (expected != result) {
149*795d594fSAndroid Build Coastguard Worker       throw new Error("Expected: " + expected + ", found: " + result);
150*795d594fSAndroid Build Coastguard Worker     }
151*795d594fSAndroid Build Coastguard Worker   }
152*795d594fSAndroid Build Coastguard Worker }
153