1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import java.lang.reflect.Method;
18 
19 //
20 // Test loop optimizations, in particular scalar loop peeling and unrolling.
21 public class Main {
22 
23   static final int LENGTH = 4 * 1024;
24   int[] a = new int[LENGTH];
25   int[] b = new int[LENGTH];
26 
27   private static final int LENGTH_A = LENGTH;
28   private static final int LENGTH_B = 16;
29   private static final int RESULT_POS = 4;
30 
31   double[][] mA;
32   double[][] mB;
33   double[][] mC;
34 
Main()35   public Main() {
36     mA = new double[LENGTH_A][];
37     mB = new double[LENGTH_B][];
38     mC = new double[LENGTH_B][];
39     for (int i = 0; i < LENGTH_A; i++) {
40       mA[i] = new double[LENGTH_B];
41     }
42 
43     for (int i = 0; i < LENGTH_B; i++) {
44       mB[i] = new double[LENGTH_A];
45       mC[i] = new double[LENGTH_B];
46     }
47   }
48 
initMatrix(double[][] m)49   private static final void initMatrix(double[][] m) {
50     for (int i = 0; i < m.length; i++) {
51       for (int j = 0; j < m[i].length; j++) {
52         m[i][j] = (double) (i * LENGTH / (j + 1));
53       }
54     }
55   }
56 
initIntArray(int[] a)57   private static final void initIntArray(int[] a) {
58     for (int i = 0; i < a.length; i++) {
59       a[i] = i % 4;
60     }
61   }
62 
initDoubleArray(double[] a)63   private static final void initDoubleArray(double[] a) {
64     for (int i = 0; i < a.length; i++) {
65       a[i] = (double)(i % 4);
66     }
67   }
68 
69   /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (before)
70   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
71   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
72   /// CHECK-DAG: <<Limit:i\d+>>   IntConstant 4094                          loop:none
73   /// CHECK-DAG: <<Phi:i\d+>>     Phi                                       loop:<<Loop:B\d+>> outer_loop:none
74   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<Phi>>,<<Limit>>]    loop:<<Loop>>      outer_loop:none
75   /// CHECK-DAG: <<If:v\d+>>      If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
76   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<Phi>>]              loop:<<Loop>>      outer_loop:none
77   /// CHECK-DAG: <<IndAdd:i\d+>>  Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
78   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<IndAdd>>]           loop:<<Loop>>      outer_loop:none
79   /// CHECK-DAG: <<Add:i\d+>>     Add [<<Get0>>,<<Get1>>]                   loop:<<Loop>>      outer_loop:none
80   /// CHECK-DAG:                  ArraySet [<<Array>>,<<Phi>>,<<Add>>]      loop:<<Loop>>      outer_loop:none
81   //
82   /// CHECK-NOT:                  ArrayGet                                  loop:<<Loop>>      outer_loop:none
83   /// CHECK-NOT:                  ArraySet                                  loop:<<Loop>>      outer_loop:none
84 
85   /// CHECK-START: void Main.unrollingLoadStoreElimination(int[]) loop_optimization (after)
86   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
87   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                             loop:none
88   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
89   /// CHECK-DAG: <<Limit:i\d+>>   IntConstant 4094                          loop:none
90   /// CHECK-DAG: <<Phi:i\d+>>     Phi                                       loop:<<Loop:B\d+>> outer_loop:none
91   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<Phi>>,<<Limit>>]    loop:<<Loop>>      outer_loop:none
92   /// CHECK-DAG: <<If:v\d+>>      If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
93   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<Phi>>]              loop:<<Loop>>      outer_loop:none
94   /// CHECK-DAG: <<IndAdd:i\d+>>  Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
95   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<IndAdd>>]           loop:<<Loop>>      outer_loop:none
96   /// CHECK-DAG: <<Add:i\d+>>     Add [<<Get0>>,<<Get1>>]                   loop:<<Loop>>      outer_loop:none
97   /// CHECK-DAG:                  ArraySet [<<Array>>,<<Phi>>,<<Add>>]      loop:<<Loop>>      outer_loop:none
98   //
99   /// CHECK-DAG: <<CheckA:z\d+>>  GreaterThanOrEqual [<<IndAdd>>,<<Limit>>] loop:<<Loop>>      outer_loop:none
100   /// CHECK-DAG: <<IfA:v\d+>>     If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
101   /// CHECK-DAG: <<Get0A:i\d+>>   ArrayGet [<<Array>>,<<IndAdd>>]           loop:<<Loop>>      outer_loop:none
102   /// CHECK-DAG: <<IndAddA:i\d+>> Add [<<IndAdd>>,<<Const1>>]               loop:<<Loop>>      outer_loop:none
103   /// CHECK-DAG: <<Get1A:i\d+>>   ArrayGet [<<Array>>,<<IndAddA>>]          loop:<<Loop>>      outer_loop:none
104   /// CHECK-DAG: <<AddA:i\d+>>    Add [<<Get0A>>,<<Get1A>>]                 loop:<<Loop>>      outer_loop:none
105   /// CHECK-DAG:                  ArraySet [<<Array>>,<<IndAdd>>,<<AddA>>]  loop:<<Loop>>      outer_loop:none
106   //
107   /// CHECK-NOT:                  ArrayGet                                  loop:<<Loop>>      outer_loop:none
108   /// CHECK-NOT:                  ArraySet                                  loop:<<Loop>>      outer_loop:none
unrollingLoadStoreElimination(int[] a)109   private static final void unrollingLoadStoreElimination(int[] a) {
110     for (int i = 0; i < LENGTH - 2; i++) {
111       a[i] += a[i + 1];
112     }
113   }
114 
115   // Simple check that loop unrolling has happened.
116   //
117   /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (before)
118   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
119   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
120   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4096                          loop:none
121   /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
122   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
123   /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
124   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
125   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
126   /// CHECK-DAG:                   Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
127   //
128   /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
129   /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
130 
131   /// CHECK-START: void Main.unrollingSwitch(int[]) loop_optimization (after)
132   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
133   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
134   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4096                          loop:none
135   /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
136   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
137   /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
138   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
139   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
140   /// CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
141   //
142   /// CHECK-DAG: <<CheckA:z\d+>>   GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
143   /// CHECK-DAG: <<IfA:v\d+>>      If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
144   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
145   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
146   /// CHECK-DAG:                   Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
147   //
148   /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
149   /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
unrollingSwitch(int[] a)150   private static final void unrollingSwitch(int[] a) {
151     for (int i = 0; i < LENGTH; i++) {
152       switch (i % 3) {
153         case 2:
154           a[i]++;
155           break;
156         default:
157           break;
158       }
159     }
160   }
161 
162   // Simple check that loop unrolling has happened.
163   //
164   /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (before)
165   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
166   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
167   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
168   /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
169   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
170   /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
171   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
172   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
173   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
174   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
175   /// CHECK-DAG:                   Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
176   //
177   /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
178   /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
179 
180   /// CHECK-START: void Main.unrollingSwapElements(int[]) loop_optimization (after)
181   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
182   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
183   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 4094                          loop:none
184   /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
185   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
186   /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
187   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
188   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
189   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
190   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
191   /// CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
192   //
193   /// CHECK-DAG: <<CheckA:z\d+>>   GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
194   /// CHECK-DAG: <<IfA:v\d+>>      If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
195   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
196   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
197   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
198   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
199   /// CHECK-DAG:                   Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
200   //
201   /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
202   /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
unrollingSwapElements(int[] array)203   private static final void unrollingSwapElements(int[] array) {
204     for (int i = 0; i < LENGTH - 2; i++) {
205       if (array[i] > array[i + 1]) {
206         int temp = array[i + 1];
207         array[i + 1] = array[i];
208         array[i] = temp;
209       }
210     }
211   }
212 
213   // Simple check that loop unrolling has happened.
214   //
215   /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (before)
216   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
217   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
218   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 16                            loop:none
219   /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
220   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
221   /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
222   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
223   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
224   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
225   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
226   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
227   /// CHECK-DAG:                   Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
228   //
229   /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
230   /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
231 
232   /// CHECK-START: void Main.unrollingRInnerproduct(double[][], double[][], double[][], int, int) loop_optimization (after)
233   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
234   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
235   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 16                            loop:none
236   /// CHECK-DAG: <<PhiI:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
237   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
238   /// CHECK-DAG: <<If:v\d+>>       If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
239   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
240   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
241   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
242   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
243   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
244   /// CHECK-DAG: <<AddI:i\d+>>     Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
245   //
246   /// CHECK-DAG: <<CheckA:z\d+>>   GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
247   /// CHECK-DAG: <<IfA:v\d+>>      If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
248   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
249   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
250   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
251   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
252   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
253   /// CHECK-DAG:                   Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
254   //
255   /// CHECK-NOT:                   ArrayGet                                  loop:<<Loop>>      outer_loop:none
256   /// CHECK-NOT:                   ArraySet                                  loop:<<Loop>>      outer_loop:none
unrollingRInnerproduct(double[][] result, double[][] a, double[][] b, int row, int column)257   private static final void unrollingRInnerproduct(double[][] result,
258                                                    double[][] a,
259                                                    double[][] b,
260                                                    int row,
261                                                    int column) {
262     // computes the inner product of A[row,*] and B[*,column]
263     int i;
264     result[row][column] = 0.0f;
265     for (i = 0; i < LENGTH_B; i++) {
266       result[row][column] = result[row][column] + a[row][i] * b[i][column];
267     }
268   }
269 
270   // nested loop
271   // [[[]]]
272 
273   /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (before)
274   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
275   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
276   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 128                           loop:none
277   /// CHECK-DAG: <<Phi1:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop1:B\d+>> outer_loop:none
278   /// CHECK-DAG: <<Phi2:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
279   /// CHECK-DAG: <<Phi3:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
280   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<Phi3>>,<<Limit>>]   loop:<<Loop3>>      outer_loop:<<Loop2>>
281   /// CHECK-DAG:                   If [<<Check>>]                            loop:<<Loop3>>      outer_loop:<<Loop2>>
282   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
283   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
284   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
285   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
286   /// CHECK-DAG:                   Add [<<Phi3>>,<<Const1>>]                 loop:<<Loop3>>      outer_loop:<<Loop2>>
287   //
288   /// CHECK-NOT:                   ArrayGet
289   /// CHECK-NOT:                   ArraySet
290   /// CHECK-NOT:                   If
291 
292   /// CHECK-START: void Main.unrollingInTheNest(int[], int[], int) loop_optimization (after)
293   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
294   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
295   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 128                           loop:none
296   /// CHECK-DAG: <<Phi1:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop1:B\d+>> outer_loop:none
297   /// CHECK-DAG: <<Phi2:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
298   /// CHECK-DAG: <<Phi3:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop3:B\d+>> outer_loop:<<Loop2>>
299   /// CHECK-DAG: <<Check:z\d+>>    GreaterThanOrEqual [<<Phi3>>,<<Limit>>]   loop:<<Loop3>>      outer_loop:<<Loop2>>
300   /// CHECK-DAG:                   If [<<Check>>]                            loop:<<Loop3>>      outer_loop:<<Loop2>>
301   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
302   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
303   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
304   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
305   /// CHECK-DAG: <<AddI:i\d+>>     Add [<<Phi3>>,<<Const1>>]                 loop:<<Loop3>>      outer_loop:<<Loop2>>
306   //
307   /// CHECK-DAG:                   If [<<Const0>>]                           loop:<<Loop3>>      outer_loop:<<Loop2>>
308   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
309   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
310   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
311   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop2>>
312   //
313   /// CHECK-NOT:                   ArrayGet
314   /// CHECK-NOT:                   ArraySet
315   /// CHECK-NOT:                   If
unrollingInTheNest(int[] a, int[] b, int x)316   private static final void unrollingInTheNest(int[] a, int[] b, int x) {
317     for (int k = 0; k < 16; k++) {
318       for (int j = 0; j < 16; j++) {
319         for (int i = 0; i < 128; i++) {
320           b[x]++;
321           a[i] = a[i] + 1;
322         }
323       }
324     }
325   }
326 
327   // nested loop:
328   // [
329   //   if [] else []
330   // ]
331 
332   /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (before)
333   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
334   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
335   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 128                           loop:none
336   /// CHECK-DAG: <<XThres:i\d+>>   IntConstant 100                           loop:none
337   /// CHECK-DAG: <<Phi1:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop1:B\d+>> outer_loop:none
338   //
339   /// CHECK-DAG: <<Phi2:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
340   /// CHECK-DAG: <<Check2:z\d+>>   GreaterThanOrEqual [<<Phi2>>,<<Limit>>]   loop:<<Loop2>>      outer_loop:<<Loop1>>
341   /// CHECK-DAG:                   If [<<Check2>>]                           loop:<<Loop2>>      outer_loop:<<Loop1>>
342   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop2>>      outer_loop:<<Loop1>>
343   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop2>>      outer_loop:<<Loop1>>
344   /// CHECK-DAG: <<AddI2:i\d+>>    Add [<<Phi2>>,<<Const1>>]                 loop:<<Loop2>>      outer_loop:<<Loop1>>
345   //
346   /// CHECK-DAG: <<Phi3:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
347   /// CHECK-DAG: <<Check3:z\d+>>   GreaterThanOrEqual [<<Phi3>>,<<Limit>>]   loop:<<Loop3>>      outer_loop:<<Loop1>>
348   /// CHECK-DAG:                   If [<<Check3>>]                           loop:<<Loop3>>      outer_loop:<<Loop1>>
349   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop1>>
350   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop1>>
351   /// CHECK-DAG: <<AddI3:i\d+>>    Add [<<Phi3>>,<<Const1>>]                 loop:<<Loop3>>      outer_loop:<<Loop1>>
352   //
353   /// CHECK-NOT:                   ArrayGet
354   /// CHECK-NOT:                   ArraySet
355   /// CHECK-NOT:                   If
356 
357   /// CHECK-START: void Main.unrollingTwoLoopsInTheNest(int[], int[], int) loop_optimization (after)
358   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
359   /// CHECK-DAG: <<Const1:i\d+>>   IntConstant 1                             loop:none
360   /// CHECK-DAG: <<Limit:i\d+>>    IntConstant 128                           loop:none
361   /// CHECK-DAG: <<XThres:i\d+>>   IntConstant 100                           loop:none
362   /// CHECK-DAG: <<Phi1:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop1:B\d+>> outer_loop:none
363   //
364   /// CHECK-DAG: <<Phi2:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
365   /// CHECK-DAG: <<Check2:z\d+>>   GreaterThanOrEqual [<<Phi2>>,<<Limit>>]   loop:<<Loop2>>      outer_loop:<<Loop1>>
366   /// CHECK-DAG:                   If [<<Check2>>]                           loop:<<Loop2>>      outer_loop:<<Loop1>>
367   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop2>>      outer_loop:<<Loop1>>
368   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop2>>      outer_loop:<<Loop1>>
369   /// CHECK-DAG: <<AddI2:i\d+>>    Add [<<Phi2>>,<<Const1>>]                 loop:<<Loop2>>      outer_loop:<<Loop1>>
370   /// CHECK-DAG:                   If [<<Const0>>]                           loop:<<Loop2>>      outer_loop:<<Loop1>>
371   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop2>>      outer_loop:<<Loop1>>
372   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop2>>      outer_loop:<<Loop1>>
373   /// CHECK-DAG:                   Add [<<AddI2>>,<<Const1>>]                loop:<<Loop2>>      outer_loop:<<Loop1>>
374   //
375   /// CHECK-DAG: <<Phi3:i\d+>>     Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop3:B\d+>> outer_loop:<<Loop1>>
376   /// CHECK-DAG: <<Check3:z\d+>>   GreaterThanOrEqual [<<Phi3>>,<<Limit>>]   loop:<<Loop3>>      outer_loop:<<Loop1>>
377   /// CHECK-DAG:                   If [<<Check3>>]                           loop:<<Loop3>>      outer_loop:<<Loop1>>
378   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop1>>
379   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop1>>
380   /// CHECK-DAG: <<AddI3:i\d+>>    Add [<<Phi3>>,<<Const1>>]                 loop:<<Loop3>>      outer_loop:<<Loop1>>
381   /// CHECK-DAG:                   If [<<Const0>>]                           loop:<<Loop3>>      outer_loop:<<Loop1>>
382   /// CHECK-DAG:                   ArrayGet                                  loop:<<Loop3>>      outer_loop:<<Loop1>>
383   /// CHECK-DAG:                   ArraySet                                  loop:<<Loop3>>      outer_loop:<<Loop1>>
384   /// CHECK-DAG:                   Add [<<AddI3>>,<<Const1>>]                loop:<<Loop3>>      outer_loop:<<Loop1>>
385   //
386   /// CHECK-NOT:                   ArrayGet
387   /// CHECK-NOT:                   ArraySet
388   /// CHECK-NOT:                   If
unrollingTwoLoopsInTheNest(int[] a, int[] b, int x)389   private static final void unrollingTwoLoopsInTheNest(int[] a, int[] b, int x) {
390     for (int k = 0; k < 128; k++) {
391       if (x > 100) {
392         for (int j = 0; j < 128; j++) {
393           a[x]++;
394         }
395       } else {
396         for (int i = 0; i < 128; i++) {
397           b[x]++;
398         }
399       }
400     }
401   }
402 
403   /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (before)
404   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
405   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                             loop:none
406   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
407   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                             loop:none
408   /// CHECK-DAG: <<Limit:i\d+>>   IntConstant 4094                          loop:none
409   /// CHECK-DAG: <<PhiS:i\d+>>    Phi [<<Const1>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
410   /// CHECK-DAG: <<PhiT:i\d+>>    Phi [<<Const2>>,{{i\d+}}]                 loop:<<Loop>>      outer_loop:none
411   /// CHECK-DAG: <<PhiI:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop>>      outer_loop:none
412   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
413   /// CHECK-DAG:                  If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
414   /// CHECK-DAG: <<AddI:i\d+>>    Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
415   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<AddI>>]             loop:<<Loop>>      outer_loop:none
416   /// CHECK-DAG: <<AddS:i\d+>>    Add [<<PhiS>>,<<Get0>>]                   loop:<<Loop>>      outer_loop:none
417   /// CHECK-DAG: <<AddT:i\d+>>    Mul [<<PhiT>>,<<Get0>>]                   loop:<<Loop>>      outer_loop:none
418   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<PhiI>>]             loop:<<Loop>>      outer_loop:none
419   /// CHECK-DAG: <<AddArr:i\d+>>  Add [<<AddS>>,<<Get1>>]                   loop:<<Loop>>      outer_loop:none
420   /// CHECK-DAG:                  ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>]  loop:<<Loop>>      outer_loop:none
421   //
422   /// CHECK-DAG: <<STAdd:i\d+>>   Add [<<PhiS>>,<<PhiT>>]                   loop:none
423   /// CHECK-DAG: <<ZCheck:i\d+>>  DivZeroCheck [<<STAdd>>] env:[[<<PhiS>>,<<PhiT>>,<<STAdd>>,<<Const1>>,_,<<Array>>]] loop:none
424   /// CHECK-DAG: <<Div:i\d+>>     Div [<<Const1>>,<<ZCheck>>]               loop:none
425   /// CHECK-DAG:                  Return [<<Div>>]                          loop:none
426   /// CHECK-NOT:                  ArrayGet
427   /// CHECK-NOT:                  ArraySet
428 
429   /// CHECK-START: int Main.unrollingSimpleLiveOuts(int[]) loop_optimization (after)
430   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
431   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                             loop:none
432   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
433   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                             loop:none
434   /// CHECK-DAG: <<Limit:i\d+>>   IntConstant 4094                          loop:none
435   /// CHECK-DAG: <<PhiS:i\d+>>    Phi [<<Const1>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
436   /// CHECK-DAG: <<PhiT:i\d+>>    Phi [<<Const2>>,{{i\d+}}]                 loop:<<Loop>>      outer_loop:none
437   /// CHECK-DAG: <<PhiI:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop>>      outer_loop:none
438   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
439   /// CHECK-DAG:                  If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
440   /// CHECK-DAG: <<AddI:i\d+>>    Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
441   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<AddI>>]             loop:<<Loop>>      outer_loop:none
442   /// CHECK-DAG: <<AddS:i\d+>>    Add [<<PhiS>>,<<Get0>>]                   loop:<<Loop>>      outer_loop:none
443   /// CHECK-DAG: <<AddT:i\d+>>    Mul [<<PhiT>>,<<Get0>>]                   loop:<<Loop>>      outer_loop:none
444   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<PhiI>>]             loop:<<Loop>>      outer_loop:none
445   /// CHECK-DAG: <<AddArr:i\d+>>  Add [<<AddS>>,<<Get1>>]                   loop:<<Loop>>      outer_loop:none
446   /// CHECK-DAG:                  ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>]  loop:<<Loop>>      outer_loop:none
447   //
448   /// CHECK-DAG:                  GreaterThanOrEqual [<<AddI>>,<<Limit>>]   loop:<<Loop>>      outer_loop:none
449   /// CHECK-DAG:                  If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
450   /// CHECK-DAG: <<AddIA:i\d+>>   Add [<<AddI>>,<<Const1>>]                 loop:<<Loop>>      outer_loop:none
451   /// CHECK-DAG: <<Get0A:i\d+>>   ArrayGet [<<Array>>,<<AddIA>>]            loop:<<Loop>>      outer_loop:none
452   /// CHECK-DAG: <<AddSA:i\d+>>   Add [<<AddS>>,<<Get0A>>]                  loop:<<Loop>>      outer_loop:none
453   /// CHECK-DAG: <<AddTA:i\d+>>   Mul [<<AddT>>,<<Get0A>>]                  loop:<<Loop>>      outer_loop:none
454   /// CHECK-DAG: <<Get1A:i\d+>>   ArrayGet [<<Array>>,<<AddI>>]             loop:<<Loop>>      outer_loop:none
455   /// CHECK-DAG: <<AddArrA:i\d+>> Add [<<AddSA>>,<<Get1A>>]                 loop:<<Loop>>      outer_loop:none
456   /// CHECK-DAG:                  ArraySet [<<Array>>,<<AddI>>,<<AddArrA>>] loop:<<Loop>>      outer_loop:none
457   //
458   /// CHECK-DAG: <<RetPhiS:i\d+>> Phi [<<PhiS>>,<<AddS>>]                   loop:none
459   /// CHECK-DAG: <<RetPhiT:i\d+>> Phi [<<PhiT>>,<<AddT>>]                   loop:none
460   /// CHECK-DAG: <<STAdd:i\d+>>   Add [<<RetPhiS>>,<<RetPhiT>>]             loop:none
461   /// CHECK-DAG: <<ZCheck:i\d+>>  DivZeroCheck [<<STAdd>>] env:[[<<RetPhiS>>,<<RetPhiT>>,<<STAdd>>,<<Const1>>,_,<<Array>>]] loop:none
462   /// CHECK-DAG: <<Div:i\d+>>     Div [<<Const1>>,<<ZCheck>>]               loop:none
463   /// CHECK-DAG:                  Return [<<Div>>]                          loop:none
464   //
465   /// CHECK-NOT:                  ArrayGet
466   /// CHECK-NOT:                  ArraySet
unrollingSimpleLiveOuts(int[] a)467   private static final int unrollingSimpleLiveOuts(int[] a) {
468     int s = 1;
469     int t = 2;
470     for (int i = 0; i < LENGTH - 2; i++) {
471       int temp = a[i + 1];
472       s += temp;
473       t *= temp;
474       a[i] += s;
475     }
476 
477     return 1 / (s + t);
478   }
479 
480   /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (before)
481   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
482   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                             loop:none
483   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
484   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                             loop:none
485   /// CHECK-DAG: <<Limit:i\d+>>   IntConstant 4094                          loop:none
486   //
487   /// CHECK-DAG: <<OutPhiJ:i\d+>> Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop0:B\d+>> outer_loop:none
488   /// CHECK-DAG: <<OutPhiS:i\d+>> Phi [<<Const1>>,{{i\d+}}]                 loop:<<Loop0>>      outer_loop:none
489   /// CHECK-DAG: <<OutPhiT:i\d+>> Phi [<<Const2>>,{{i\d+}}]                 loop:<<Loop0>>      outer_loop:none
490   //
491   /// CHECK-DAG: <<PhiI:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop1:B\d+>> outer_loop:<<Loop0>>
492   /// CHECK-DAG: <<PhiS:i\d+>>    Phi [<<OutPhiS>>,{{i\d+}}]                loop:<<Loop1>>      outer_loop:<<Loop0>>
493   /// CHECK-DAG: <<PhiT:i\d+>>    Phi [<<OutPhiT>>,{{i\d+}}]                loop:<<Loop1>>      outer_loop:<<Loop0>>
494   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop1>>      outer_loop:<<Loop0>>
495   /// CHECK-DAG:                  If [<<Check>>]                            loop:<<Loop1>>      outer_loop:<<Loop0>>
496   /// CHECK-DAG: <<AddI:i\d+>>    Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop1>>      outer_loop:<<Loop0>>
497   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<AddI>>]             loop:<<Loop1>>      outer_loop:<<Loop0>>
498   /// CHECK-DAG: <<AddS:i\d+>>    Add [<<PhiS>>,<<Get0>>]                   loop:<<Loop1>>      outer_loop:<<Loop0>>
499   /// CHECK-DAG: <<AddT:i\d+>>    Mul [<<PhiT>>,<<Get0>>]                   loop:<<Loop1>>      outer_loop:<<Loop0>>
500   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<PhiI>>]             loop:<<Loop1>>      outer_loop:<<Loop0>>
501   /// CHECK-DAG: <<AddArr:i\d+>>  Add [<<AddS>>,<<Get1>>]                   loop:<<Loop1>>      outer_loop:<<Loop0>>
502   /// CHECK-DAG:                  ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>]  loop:<<Loop1>>      outer_loop:<<Loop0>>
503   //
504   /// CHECK-DAG:                  Add [<<OutPhiJ>>,<<Const1>>]              loop:<<Loop0>>      outer_loop:none
505   //
506   /// CHECK-NOT:                  ArrayGet
507   /// CHECK-NOT:                  ArraySet
508 
509   /// CHECK-START: int Main.unrollingLiveOutsNested(int[]) loop_optimization (after)
510   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
511   /// CHECK-DAG: <<Const0:i\d+>>  IntConstant 0                             loop:none
512   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
513   /// CHECK-DAG: <<Const2:i\d+>>  IntConstant 2                             loop:none
514   /// CHECK-DAG: <<Limit:i\d+>>   IntConstant 4094                          loop:none
515   //
516   /// CHECK-DAG: <<OutPhiJ:i\d+>> Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop0:B\d+>> outer_loop:none
517   /// CHECK-DAG: <<OutPhiS:i\d+>> Phi [<<Const1>>,{{i\d+}}]                 loop:<<Loop0>>      outer_loop:none
518   /// CHECK-DAG: <<OutPhiT:i\d+>> Phi [<<Const2>>,{{i\d+}}]                 loop:<<Loop0>>      outer_loop:none
519   //
520   /// CHECK-DAG: <<PhiI:i\d+>>    Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop1:B\d+>> outer_loop:<<Loop0>>
521   /// CHECK-DAG: <<PhiS:i\d+>>    Phi [<<OutPhiS>>,{{i\d+}}]                loop:<<Loop1>>      outer_loop:<<Loop0>>
522   /// CHECK-DAG: <<PhiT:i\d+>>    Phi [<<OutPhiT>>,{{i\d+}}]                loop:<<Loop1>>      outer_loop:<<Loop0>>
523   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<PhiI>>,<<Limit>>]   loop:<<Loop1>>      outer_loop:<<Loop0>>
524   /// CHECK-DAG:                  If [<<Check>>]                            loop:<<Loop1>>      outer_loop:<<Loop0>>
525   /// CHECK-DAG: <<AddI:i\d+>>    Add [<<PhiI>>,<<Const1>>]                 loop:<<Loop1>>      outer_loop:<<Loop0>>
526   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<AddI>>]             loop:<<Loop1>>      outer_loop:<<Loop0>>
527   /// CHECK-DAG: <<AddS:i\d+>>    Add [<<PhiS>>,<<Get0>>]                   loop:<<Loop1>>      outer_loop:<<Loop0>>
528   /// CHECK-DAG: <<AddT:i\d+>>    Mul [<<PhiT>>,<<Get0>>]                   loop:<<Loop1>>      outer_loop:<<Loop0>>
529   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<PhiI>>]             loop:<<Loop1>>      outer_loop:<<Loop0>>
530   /// CHECK-DAG: <<AddArr:i\d+>>  Add [<<AddS>>,<<Get1>>]                   loop:<<Loop1>>      outer_loop:<<Loop0>>
531   /// CHECK-DAG:                  ArraySet [<<Array>>,<<PhiI>>,<<AddArr>>]  loop:<<Loop1>>      outer_loop:<<Loop0>>
532   //
533   /// CHECK-DAG:                  If [<<Const0>>]                           loop:<<Loop1>>      outer_loop:<<Loop0>>
534   /// CHECK-DAG: <<AddIA:i\d+>>   Add [<<AddI>>,<<Const1>>]                 loop:<<Loop1>>      outer_loop:<<Loop0>>
535   /// CHECK-DAG: <<Get0A:i\d+>>   ArrayGet [<<Array>>,<<AddIA>>]            loop:<<Loop1>>      outer_loop:<<Loop0>>
536   /// CHECK-DAG: <<AddSA:i\d+>>   Add [<<AddS>>,<<Get0A>>]                  loop:<<Loop1>>      outer_loop:<<Loop0>>
537   /// CHECK-DAG: <<AddTA:i\d+>>   Mul [<<AddT>>,<<Get0A>>]                  loop:<<Loop1>>      outer_loop:<<Loop0>>
538   /// CHECK-DAG: <<Get1A:i\d+>>   ArrayGet [<<Array>>,<<AddI>>]             loop:<<Loop1>>      outer_loop:<<Loop0>>
539   /// CHECK-DAG: <<AddArrA:i\d+>> Add [<<AddSA>>,<<Get1A>>]                 loop:<<Loop1>>      outer_loop:<<Loop0>>
540   /// CHECK-DAG:                  ArraySet [<<Array>>,<<AddI>>,<<AddArrA>>] loop:<<Loop1>>      outer_loop:<<Loop0>>
541   //
542   /// CHECK-DAG: <<RetPhiS:i\d+>> Phi [<<PhiS>>,<<AddS>>]                   loop:<<Loop0>>      outer_loop:none
543   /// CHECK-DAG: <<RetPhiT:i\d+>> Phi [<<PhiT>>,<<AddT>>]                   loop:<<Loop0>>      outer_loop:none
544   /// CHECK-DAG:                  Add [<<OutPhiJ>>,<<Const1>>]              loop:<<Loop0>>      outer_loop:none
545   //
546   /// CHECK-DAG: <<RetAdd:i\d+>>  Add [<<OutPhiS>>,<<OutPhiT>>]             loop:none
547   /// CHECK-DAG:                  Return [<<RetAdd>>]                       loop:none
548   //
549   /// CHECK-NOT:                  ArrayGet
550   /// CHECK-NOT:                  ArraySet
unrollingLiveOutsNested(int[] a)551   private static final int unrollingLiveOutsNested(int[] a) {
552     int s = 1;
553     int t = 2;
554     for (int j = 0; j < 16; j++) {
555       for (int i = 0; i < LENGTH - 2; i++) {
556         int temp = a[i + 1];
557         s += temp;
558         t *= temp;
559         a[i] += s;
560       }
561     }
562     return s + t;
563   }
564 
565   /// CHECK-START: void Main.unrollingInstanceOf(int[], java.lang.Object[]) loop_optimization (before)
566   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
567   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
568   /// CHECK-DAG:                   InstanceOf                                loop:<<Loop>>      outer_loop:none
569   //
570   /// CHECK-NOT:                   InstanceOf
571 
572   /// CHECK-START: void Main.unrollingInstanceOf(int[], java.lang.Object[]) loop_optimization (after)
573   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
574   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
575   /// CHECK-DAG:                   InstanceOf                                loop:<<Loop>>      outer_loop:none
576   /// CHECK-DAG:                   InstanceOf                                loop:<<Loop>>      outer_loop:none
577   //
578   /// CHECK-NOT:                   InstanceOf
unrollingInstanceOf(int[] a, Object[] obj_array)579   public void unrollingInstanceOf(int[] a, Object[] obj_array) {
580     for (int i = 0; i < LENGTH_B; i++) {
581       if (obj_array[i] instanceof Integer) {
582         a[i] += 1;
583       }
584     }
585   }
586 
587   /// CHECK-START: void Main.unrollingDivZeroCheck(int[], int) loop_optimization (before)
588   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
589   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
590   /// CHECK-DAG:                   DivZeroCheck                              loop:<<Loop>>      outer_loop:none
591   //
592   /// CHECK-NOT:                   DivZeroCheck
593 
594   /// CHECK-START: void Main.unrollingDivZeroCheck(int[], int) loop_optimization (after)
595   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
596   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
597   /// CHECK-DAG:                   DivZeroCheck                              loop:<<Loop>>      outer_loop:none
598   /// CHECK-DAG:                   DivZeroCheck                              loop:<<Loop>>      outer_loop:none
599   //
600   /// CHECK-NOT:                   DivZeroCheck
unrollingDivZeroCheck(int[] a, int r)601   public void unrollingDivZeroCheck(int[] a, int r) {
602     for (int i = 0; i < LENGTH_B; i++) {
603       a[i] += a[i] / r;
604     }
605   }
606 
607   /// CHECK-START: void Main.unrollingTypeConversion(int[], double[]) loop_optimization (before)
608   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
609   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
610   /// CHECK-DAG:                   TypeConversion                            loop:<<Loop>>      outer_loop:none
611   //
612   /// CHECK-NOT:                   TypeConversion
613 
614   /// CHECK-START: void Main.unrollingTypeConversion(int[], double[]) loop_optimization (after)
615   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
616   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
617   /// CHECK-DAG:                   TypeConversion                            loop:<<Loop>>      outer_loop:none
618   /// CHECK-DAG:                   TypeConversion                            loop:<<Loop>>      outer_loop:none
619   //
620   /// CHECK-NOT:                   TypeConversion
unrollingTypeConversion(int[] a, double[] b)621   public void unrollingTypeConversion(int[] a, double[] b) {
622     for (int i = 0; i < LENGTH_B; i++) {
623       a[i] = (int) b[i];
624     }
625   }
626 
627   interface Itf {
628   }
629 
630   class SubMain extends Main implements Itf {
631   }
632 
633   /// CHECK-START: void Main.unrollingCheckCast(int[], java.lang.Object) loop_optimization (before)
634   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
635   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
636   /// CHECK-DAG:                   CheckCast                                 loop:<<Loop>>      outer_loop:none
637   //
638   /// CHECK-NOT:                   CheckCast
639 
640   /// CHECK-START: void Main.unrollingCheckCast(int[], java.lang.Object) loop_optimization (after)
641   /// CHECK-DAG: <<Const0:i\d+>>   IntConstant 0                             loop:none
642   /// CHECK-DAG:                   Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
643   /// CHECK-DAG:                   CheckCast                                 loop:<<Loop>>      outer_loop:none
644   /// CHECK-DAG:                   CheckCast                                 loop:<<Loop>>      outer_loop:none
645   //
646   /// CHECK-NOT:                   CheckCast
unrollingCheckCast(int[] a, Object o)647   public void unrollingCheckCast(int[] a, Object o) {
648     for (int i = 0; i < LENGTH_B; i++) {
649       if (((SubMain)o) == o) {
650         a[i] = i;
651       }
652     }
653   }
654 
655   /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (before)
656   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
657   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
658   /// CHECK-DAG: <<Limit:i\d+>>   IntConstant 4095                          loop:none
659   /// CHECK-DAG: <<Phi:i\d+>>     Phi                                       loop:<<Loop:B\d+>> outer_loop:none
660   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<Phi>>,<<Limit>>]    loop:<<Loop>>      outer_loop:none
661   /// CHECK-DAG: <<If:v\d+>>      If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
662   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<Phi>>]              loop:<<Loop>>      outer_loop:none
663   /// CHECK-DAG: <<IndAdd:i\d+>>  Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
664   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<IndAdd>>]           loop:<<Loop>>      outer_loop:none
665   /// CHECK-DAG: <<Add:i\d+>>     Add [<<Get0>>,<<Get1>>]                   loop:<<Loop>>      outer_loop:none
666   /// CHECK-DAG:                  ArraySet [<<Array>>,<<Phi>>,<<Add>>]      loop:<<Loop>>      outer_loop:none
667   //
668   /// CHECK-NOT:                  Phi
669   /// CHECK-NOT:                  If
670   /// CHECK-NOT:                  ArrayGet
671   /// CHECK-NOT:                  ArraySet
672 
673   /// CHECK-START: void Main.noUnrollingOddTripCount(int[]) loop_optimization (after)
674   /// CHECK-DAG:                  Phi                                       loop:<<Loop:B\d+>> outer_loop:none
675   /// CHECK-DAG:                  If                                        loop:<<Loop>>      outer_loop:none
676   /// CHECK-DAG:                  ArrayGet                                  loop:<<Loop>>      outer_loop:none
677   /// CHECK-DAG:                  ArrayGet                                  loop:<<Loop>>      outer_loop:none
678   /// CHECK-DAG:                  ArraySet                                  loop:<<Loop>>      outer_loop:none
679   //
680   /// CHECK-NOT:                  Phi
681   /// CHECK-NOT:                  If
682   /// CHECK-NOT:                  ArrayGet
683   /// CHECK-NOT:                  ArraySet
noUnrollingOddTripCount(int[] a)684   private static final void noUnrollingOddTripCount(int[] a) {
685     for (int i = 0; i < LENGTH - 1; i++) {
686       a[i] += a[i + 1];
687     }
688   }
689 
690   /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (before)
691   /// CHECK-DAG: <<Array:l\d+>>   ParameterValue                            loop:none
692   /// CHECK-DAG: <<Limit:i\d+>>   ParameterValue                            loop:none
693   /// CHECK-DAG: <<Const1:i\d+>>  IntConstant 1                             loop:none
694   /// CHECK-DAG: <<Phi:i\d+>>     Phi                                       loop:<<Loop:B\d+>> outer_loop:none
695   /// CHECK-DAG: <<Check:z\d+>>   GreaterThanOrEqual [<<Phi>>,<<Limit>>]    loop:<<Loop>>      outer_loop:none
696   /// CHECK-DAG: <<If:v\d+>>      If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
697   /// CHECK-DAG: <<Get0:i\d+>>    ArrayGet [<<Array>>,<<Phi>>]              loop:<<Loop>>      outer_loop:none
698   /// CHECK-DAG: <<IndAdd:i\d+>>  Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
699   /// CHECK-DAG: <<Get1:i\d+>>    ArrayGet [<<Array>>,<<IndAdd>>]           loop:<<Loop>>      outer_loop:none
700   /// CHECK-DAG: <<Add:i\d+>>     Add [<<Get0>>,<<Get1>>]                   loop:<<Loop>>      outer_loop:none
701   /// CHECK-DAG:                  ArraySet [<<Array>>,<<Phi>>,<<Add>>]      loop:<<Loop>>      outer_loop:none
702   //
703   /// CHECK-NOT:                  Phi
704   /// CHECK-NOT:                  ArrayGet
705   /// CHECK-NOT:                  ArraySet
706 
707   /// CHECK-START: void Main.noUnrollingNotKnownTripCount(int[], int) loop_optimization (after)
708   /// CHECK-DAG:                  Phi                                       loop:<<Loop:B\d+>> outer_loop:none
709   /// CHECK-DAG:                  If                                        loop:<<Loop>>      outer_loop:none
710   /// CHECK-DAG:                  ArrayGet                                  loop:<<Loop>>      outer_loop:none
711   /// CHECK-DAG:                  ArrayGet                                  loop:<<Loop>>      outer_loop:none
712   /// CHECK-DAG:                  ArraySet                                  loop:<<Loop>>      outer_loop:none
713   //
714   /// CHECK-NOT:                  Phi
715   /// CHECK-NOT:                  ArrayGet
716   /// CHECK-NOT:                  ArraySet
noUnrollingNotKnownTripCount(int[] a, int n)717   private static final void noUnrollingNotKnownTripCount(int[] a, int n) {
718     for (int i = 0; i < n; i++) {
719       a[i] += a[i + 1];
720     }
721   }
722 
723   /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (before)
724   /// CHECK-DAG: <<Param:z\d+>>     ParameterValue                            loop:none
725   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                             loop:none
726   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                             loop:none
727   /// CHECK-DAG: <<Limit:i\d+>>     IntConstant 4096                          loop:none
728   /// CHECK-DAG: <<Phi:i\d+>>       Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
729   /// CHECK-DAG: <<Check:z\d+>>     GreaterThanOrEqual [<<Phi>>,<<Limit>>]    loop:<<Loop>>      outer_loop:none
730   /// CHECK-DAG:                    If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
731   /// CHECK-DAG:                    If [<<Param>>]                            loop:<<Loop>>      outer_loop:none
732   /// CHECK-DAG:                    ArrayGet                                  loop:<<Loop>>      outer_loop:none
733   /// CHECK-DAG:                    ArraySet                                  loop:<<Loop>>      outer_loop:none
734   /// CHECK-DAG: <<IndAdd:i\d+>>    Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
735   //
736   /// CHECK-NOT:                    If
737   /// CHECK-NOT:                    ArraySet
738 
739   /// CHECK-START: void Main.peelingSimple(int[], boolean) loop_optimization (after)
740   /// CHECK-DAG: <<Param:z\d+>>     ParameterValue                            loop:none
741   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                             loop:none
742   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                             loop:none
743   /// CHECK-DAG: <<Limit:i\d+>>     IntConstant 4096                          loop:none
744   /// CHECK-DAG: <<CheckA:z\d+>>    GreaterThanOrEqual [<<Const0>>,<<Limit>>] loop:none
745   /// CHECK-DAG:                    If [<<CheckA>>]                           loop:none
746   /// CHECK-DAG:                    If [<<Param>>]                            loop:none
747   /// CHECK-DAG:                    ArrayGet                                  loop:none
748   /// CHECK-DAG:                    ArraySet                                  loop:none
749   /// CHECK-DAG: <<IndAddA:i\d+>>   Add [<<Const0>>,<<Const1>>]               loop:none
750   /// CHECK-DAG: <<Phi:i\d+>>       Phi [<<IndAddA>>,{{i\d+}}]                loop:<<Loop:B\d+>> outer_loop:none
751   /// CHECK-DAG: <<Check:z\d+>>     GreaterThanOrEqual [<<Phi>>,<<Limit>>]    loop:<<Loop>>      outer_loop:none
752   /// CHECK-DAG:                    If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
753   /// CHECK-DAG:                    If [<<Const0>>]                           loop:<<Loop>>      outer_loop:none
754   /// CHECK-DAG:                    ArrayGet                                  loop:<<Loop>>      outer_loop:none
755   /// CHECK-DAG:                    ArraySet                                  loop:<<Loop>>      outer_loop:none
756   /// CHECK-DAG: <<IndAdd:i\d+>>    Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
757   //
758   /// CHECK-NOT:                    If
759   /// CHECK-NOT:                    ArraySet
760 
761   /// CHECK-START: void Main.peelingSimple(int[], boolean) dead_code_elimination$final (after)
762   /// CHECK-DAG: <<Param:z\d+>>     ParameterValue                            loop:none
763   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                             loop:none
764   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                             loop:none
765   /// CHECK-DAG: <<Limit:i\d+>>     IntConstant 4096                          loop:none
766   /// CHECK-DAG:                    If [<<Param>>]                            loop:none
767   /// CHECK-DAG:                    ArrayGet                                  loop:none
768   /// CHECK-DAG:                    ArraySet                                  loop:none
769   /// CHECK-DAG: <<Phi:i\d+>>       Phi [<<Const1>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
770   /// CHECK-DAG: <<Check:z\d+>>     GreaterThanOrEqual [<<Phi>>,<<Limit>>]    loop:<<Loop>>      outer_loop:none
771   /// CHECK-DAG:                    If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
772   /// CHECK-DAG:                    ArrayGet                                  loop:<<Loop>>      outer_loop:none
773   /// CHECK-DAG:                    ArraySet                                  loop:<<Loop>>      outer_loop:none
774   /// CHECK-DAG: <<IndAdd:i\d+>>    Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
775   //
776   /// CHECK-NOT:                    GreaterThanOrEqual
777   /// CHECK-NOT:                    If
778   /// CHECK-NOT:                    ArrayGet
779   /// CHECK-NOT:                    ArraySet
peelingSimple(int[] a, boolean f)780   private static final void peelingSimple(int[] a, boolean f) {
781     for (int i = 0; i < LENGTH; i++) {
782       if (f) {
783         break;
784       }
785       a[i] += 1;
786     }
787   }
788 
789   // Often used idiom that, when not hoisted, prevents BCE and vectorization.
790   //
791   /// CHECK-START: void Main.peelingAddInts(int[]) loop_optimization (before)
792   /// CHECK-DAG: <<Param:l\d+>>     ParameterValue                        loop:none
793   /// CHECK-DAG: <<ConstNull:l\d+>> NullConstant                          loop:none
794   /// CHECK-DAG: <<Eq:z\d+>>        Equal [<<Param>>,<<ConstNull>>]       loop:none
795   /// CHECK-DAG: <<Phi:i\d+>>       Phi                                   loop:<<Loop:B\d+>> outer_loop:none
796   /// CHECK-DAG:                    If [<<Eq>>]                           loop:<<Loop>>      outer_loop:none
797   /// CHECK-DAG: <<Check:z\d+>>     GreaterThanOrEqual [<<Phi>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
798   /// CHECK-DAG:                    If [<<Check>>]                        loop:<<Loop>>      outer_loop:none
799   /// CHECK-DAG:                    ArraySet                              loop:<<Loop>>      outer_loop:none
800 
801   /// CHECK-START: void Main.peelingAddInts(int[]) dead_code_elimination$final (after)
802   /// CHECK-DAG: <<Param:l\d+>>     ParameterValue                        loop:none
803   /// CHECK-DAG: <<ConstNull:l\d+>> NullConstant                          loop:none
804   /// CHECK-DAG: <<Eq:z\d+>>        Equal [<<Param>>,<<ConstNull>>]       loop:none
805   /// CHECK-DAG:                    If [<<Eq>>]                           loop:none
806   /// CHECK-DAG:                    ArraySet                              loop:none
807   /// CHECK-DAG: <<Phi:i\d+>>       Phi                                   loop:<<Loop:B\d+>> outer_loop:none
808   /// CHECK-DAG: <<Check:z\d+>>     GreaterThanOrEqual [<<Phi>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
809   /// CHECK-DAG:                    If [<<Check>>]                        loop:<<Loop>>      outer_loop:none
810   /// CHECK-DAG:                    ArraySet                              loop:<<Loop>>      outer_loop:none
811   //
812   /// CHECK-NOT:                    If [<<Eq>>]                           loop:<<Loop>>      outer_loop:none
peelingAddInts(int[] a)813   private static final void peelingAddInts(int[] a) {
814     for (int i = 0; a != null && i < a.length; i++) {
815       a[i] += 1;
816     }
817   }
818 
819   /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) loop_optimization (before)
820   /// CHECK-DAG: <<Param:z\d+>>     ParameterValue                          loop:none
821   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                           loop:none
822   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                           loop:none
823   /// CHECK-DAG: <<Limit:i\d+>>     IntConstant 4096                        loop:none
824   /// CHECK-DAG: <<Phi0:i\d+>>      Phi [<<Const1>>,{{i\d+}}]               loop:<<Loop0:B\d+>> outer_loop:none
825   /// CHECK-DAG: <<Phi1:i\d+>>      Phi [<<Const0>>,{{i\d+}}]               loop:<<Loop1:B\d+>> outer_loop:<<Loop0>>
826   /// CHECK-DAG: <<Check:z\d+>>     GreaterThanOrEqual [<<Phi1>>,<<Limit>>] loop:<<Loop1>>      outer_loop:<<Loop0>>
827   /// CHECK-DAG:                    If [<<Check>>]                          loop:<<Loop1>>      outer_loop:<<Loop0>>
828   /// CHECK-DAG:                    If [<<Param>>]                          loop:<<Loop1>>      outer_loop:<<Loop0>>
829   /// CHECK-DAG:                    ArrayGet                                loop:<<Loop1>>      outer_loop:<<Loop0>>
830   /// CHECK-DAG:                    ArraySet                                loop:<<Loop1>>      outer_loop:<<Loop0>>
831   /// CHECK-DAG: <<IndAdd1:i\d+>>   Add [<<Phi1>>,<<Const1>>]               loop:<<Loop1>>      outer_loop:<<Loop0>>
832   /// CHECK-DAG: <<IndAdd0:i\d+>>   Add [<<Phi0>>,<<Const1>>]               loop:<<Loop0>>      outer_loop:none
833   //
834   /// CHECK-NOT:                    If
835   /// CHECK-NOT:                    ArraySet
836 
837   /// CHECK-START: void Main.peelingBreakFromNest(int[], boolean) dead_code_elimination$final (after)
838   /// CHECK-DAG: <<Param:z\d+>>     ParameterValue                          loop:none
839   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                           loop:none
840   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                           loop:none
841   /// CHECK-DAG: <<Limit:i\d+>>     IntConstant 4096                        loop:none
842   /// CHECK-DAG: <<Phi0:i\d+>>      Phi [<<Const1>>,{{i\d+}}]               loop:<<Loop0:B\d+>> outer_loop:none
843   /// CHECK-DAG:                    If [<<Param>>]                          loop:<<Loop0>>      outer_loop:none
844   /// CHECK-DAG:                    ArrayGet                                loop:<<Loop0>>      outer_loop:none
845   /// CHECK-DAG:                    ArraySet                                loop:<<Loop0>>      outer_loop:none
846   /// CHECK-DAG: <<Phi1:i\d+>>      Phi [<<Const1>>,{{i\d+}}]               loop:<<Loop1:B\d+>> outer_loop:<<Loop0>>
847   /// CHECK-DAG: <<Check:z\d+>>     GreaterThanOrEqual [<<Phi1>>,<<Limit>>] loop:<<Loop1>>      outer_loop:<<Loop0>>
848   /// CHECK-DAG:                    If [<<Check>>]                          loop:<<Loop1>>      outer_loop:<<Loop0>>
849   /// CHECK-DAG:                    ArrayGet                                loop:<<Loop1>>      outer_loop:<<Loop0>>
850   /// CHECK-DAG:                    ArraySet                                loop:<<Loop1>>      outer_loop:<<Loop0>>
851   /// CHECK-DAG: <<IndAdd1:i\d+>>   Add [<<Phi1>>,<<Const1>>]               loop:<<Loop1>>      outer_loop:<<Loop0>>
852   /// CHECK-DAG: <<IndAdd0:i\d+>>   Add [<<Phi0>>,<<Const1>>]               loop:<<Loop0>>      outer_loop:none
853   //
854   /// CHECK-NOT:                    If
855   /// CHECK-NOT:                    ArraySet
peelingBreakFromNest(int[] a, boolean f)856   private static final void peelingBreakFromNest(int[] a, boolean f) {
857     outer:
858     for (int i = 1; i < 32; i++) {
859       for (int j = 0; j < LENGTH; j++) {
860         if (f) {
861           break outer;
862         }
863         a[j] += 1;
864       }
865     }
866   }
867 
868   /// CHECK-START: int Main.peelingHoistOneControl(int) loop_optimization (before)
869   /// CHECK-DAG: <<Param:i\d+>>     ParameterValue                            loop:none
870   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                             loop:none
871   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                             loop:none
872   /// CHECK-DAG: <<Check:z\d+>>     NotEqual [<<Param>>,<<Const0>>]           loop:none
873   /// CHECK-DAG: <<Phi:i\d+>>       Phi [<<Const0>>,{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
874   /// CHECK-DAG:                    If [<<Check>>]                            loop:<<Loop>>      outer_loop:none
875   /// CHECK-DAG: <<IndAdd:i\d+>>    Add [<<Phi>>,<<Const1>>]                  loop:<<Loop>>      outer_loop:none
876   //
877   /// CHECK-NOT:                    If
878 
879   /// CHECK-START: int Main.peelingHoistOneControl(int) dead_code_elimination$final (after)
880   /// CHECK-DAG: <<Param:i\d+>>     ParameterValue                            loop:none
881   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                             loop:none
882   /// CHECK-DAG: <<Check:z\d+>>     NotEqual [<<Param>>,<<Const0>>]           loop:none
883   /// CHECK-DAG:                    If [<<Check>>]                            loop:none
884   /// CHECK-DAG:                    SuspendCheck                              loop:<<Loop:B\d+>> outer_loop:none
885   /// CHECK-DAG:                    Goto                                      loop:<<Loop>>      outer_loop:none
886   //
887   //  Check that the loop has no instruction except SuspendCheck and Goto (indefinite loop).
888   /// CHECK-NOT:                                                              loop:<<Loop>>      outer_loop:none
889   /// CHECK-NOT:                    If
890   /// CHECK-NOT:                    Phi
891   /// CHECK-NOT:                    Add
peelingHoistOneControl(int x)892   private static final int peelingHoistOneControl(int x) {
893     int i = 0;
894     while (true) {
895       if (x == 0)
896         return 1;
897       i++;
898     }
899   }
900 
901   /// CHECK-START: int Main.peelingHoistOneControl(int, int) loop_optimization (before)
902   /// CHECK-DAG: <<Phi:i\d+>> Phi  loop:<<Loop:B\d+>> outer_loop:none
903   /// CHECK-DAG:              If   loop:<<Loop>>      outer_loop:none
904   /// CHECK-DAG:              If   loop:<<Loop>>      outer_loop:none
905   //
906   /// CHECK-START: int Main.peelingHoistOneControl(int, int) dead_code_elimination$final (after)
907   /// CHECK-DAG: <<Phi:i\d+>> Phi  loop:<<Loop:B\d+>> outer_loop:none
908   /// CHECK-DAG:              If   loop:<<Loop>>      outer_loop:none
909   /// CHECK-NOT:              If   loop:<<Loop>>      outer_loop:none
peelingHoistOneControl(int x, int y)910   private static final int peelingHoistOneControl(int x, int y) {
911     while (true) {
912       if (x == 0)
913         return 1;
914       if (y == 0)  // no longer invariant
915         return 2;
916       y--;
917     }
918   }
919 
920   /// CHECK-START: int Main.peelingHoistTwoControl(int, int, int) loop_optimization (before)
921   /// CHECK-DAG: <<Phi:i\d+>> Phi  loop:<<Loop:B\d+>> outer_loop:none
922   /// CHECK-DAG:              If   loop:<<Loop>>      outer_loop:none
923   /// CHECK-DAG:              If   loop:<<Loop>>      outer_loop:none
924   /// CHECK-DAG:              If   loop:<<Loop>>      outer_loop:none
925   //
926   /// CHECK-START: int Main.peelingHoistTwoControl(int, int, int) dead_code_elimination$final (after)
927   /// CHECK-DAG: <<Phi:i\d+>> Phi  loop:<<Loop:B\d+>> outer_loop:none
928   /// CHECK-DAG:              If   loop:<<Loop>>      outer_loop:none
929   /// CHECK-NOT:              If   loop:<<Loop>>      outer_loop:none
peelingHoistTwoControl(int x, int y, int z)930   private static final int peelingHoistTwoControl(int x, int y, int z) {
931     while (true) {
932       if (x == 0)
933         return 1;
934       if (y == 0)
935         return 2;
936       if (z == 0)  // no longer invariant
937         return 3;
938       z--;
939     }
940   }
941 
942   /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (before)
943   /// CHECK-DAG: <<Param:l\d+>>     ParameterValue                          loop:none
944   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                           loop:none
945   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                           loop:none
946   /// CHECK-DAG: <<Limit:i\d+>>     IntConstant 2                           loop:none
947   /// CHECK-DAG: <<Phi:i\d+>>       Phi [<<Const0>>,{{i\d+}}]               loop:<<Loop:B\d+>> outer_loop:none
948   /// CHECK-DAG:                    ArrayGet                                loop:<<Loop>>      outer_loop:none
949   /// CHECK-DAG:                    ArrayGet                                loop:<<Loop>>      outer_loop:none
950   /// CHECK-DAG:                    ArraySet                                loop:<<Loop>>      outer_loop:none
951   //
952   /// CHECK-NOT:                    ArrayGet
953   /// CHECK-NOT:                    ArraySet
954 
955   /// CHECK-START: void Main.unrollingFull(int[]) loop_optimization (after)
956   /// CHECK-DAG: <<Param:l\d+>>     ParameterValue                          loop:none
957   /// CHECK-DAG: <<Const0:i\d+>>    IntConstant 0                           loop:none
958   /// CHECK-DAG: <<Const1:i\d+>>    IntConstant 1                           loop:none
959   /// CHECK-DAG: <<Limit:i\d+>>     IntConstant 2                           loop:none
960   //            Two peeled iterations
961   /// CHECK-DAG:                    ArrayGet                                loop:none
962   /// CHECK-DAG:                    ArrayGet                                loop:none
963   /// CHECK-DAG:                    ArraySet                                loop:none
964   /// CHECK-DAG:                    ArrayGet                                loop:none
965   /// CHECK-DAG:                    ArrayGet                                loop:none
966   /// CHECK-DAG:                    ArraySet                                loop:none
967   //            Loop
968   /// CHECK-DAG: <<Phi:i\d+>>       Phi [{{i\d+}},{{i\d+}}]                 loop:<<Loop:B\d+>> outer_loop:none
969   /// CHECK-DAG:                    ArrayGet                                loop:<<Loop>>      outer_loop:none
970   /// CHECK-DAG:                    ArrayGet                                loop:<<Loop>>      outer_loop:none
971   /// CHECK-DAG:                    ArraySet                                loop:<<Loop>>      outer_loop:none
972   /// CHECK-DAG:                    If [<<Const1>>]                         loop:<<Loop>>      outer_loop:none
973   //
974   /// CHECK-NOT:                    ArrayGet
975   /// CHECK-NOT:                    ArraySet
unrollingFull(int[] a)976   private static final void unrollingFull(int[] a) {
977     for (int i = 0; i < 2; i++) {
978       a[i] += a[i + 1];
979     }
980   }
981 
expectEquals(int expected, int result)982   private static void expectEquals(int expected, int result) {
983     if (expected != result) {
984       throw new Error("Expected: " + expected + ", found: " + result);
985     }
986   }
987 
verifyUnrolling()988   public void verifyUnrolling() throws Exception {
989     initIntArray(a);
990     initIntArray(b);
991 
992     initMatrix(mA);
993     initMatrix(mB);
994     initMatrix(mC);
995 
996     int expected = 174291515;
997     int found = 0;
998 
999     double[] doubleArray = new double[LENGTH_B];
1000     initDoubleArray(doubleArray);
1001 
1002     unrollingInstanceOf(a, new Integer[LENGTH_B]);
1003     unrollingDivZeroCheck(a, 15);
1004     unrollingTypeConversion(a, doubleArray);
1005     unrollingCheckCast(a, new SubMain());
1006 
1007     // Call unrollingWhile(a);
1008     Class<?> c = Class.forName("PeelUnroll");
1009     Method m = c.getMethod("unrollingWhile", Class.forName("[I"));
1010     Object[] arguments = { a };
1011     m.invoke(null, arguments);
1012 
1013     unrollingLoadStoreElimination(a);
1014     unrollingSwitch(a);
1015     unrollingSwapElements(a);
1016     unrollingRInnerproduct(mC, mA, mB, RESULT_POS, RESULT_POS);
1017     unrollingInTheNest(a, b, RESULT_POS);
1018     unrollingTwoLoopsInTheNest(a, b, RESULT_POS);
1019 
1020     noUnrollingOddTripCount(b);
1021     noUnrollingNotKnownTripCount(b, 128);
1022 
1023     for (int i = 0; i < LENGTH; i++) {
1024       found += a[i];
1025       found += b[i];
1026     }
1027     found += (int)mC[RESULT_POS][RESULT_POS];
1028 
1029     expectEquals(expected, found);
1030   }
1031 
verifyPeeling()1032   public void verifyPeeling() throws Exception {
1033     expectEquals(1, peelingHoistOneControl(0));  // anything else loops
1034     expectEquals(1, peelingHoistOneControl(0, 0));
1035     expectEquals(1, peelingHoistOneControl(0, 1));
1036     expectEquals(2, peelingHoistOneControl(1, 0));
1037     expectEquals(2, peelingHoistOneControl(1, 1));
1038     expectEquals(1, peelingHoistTwoControl(0, 0, 0));
1039     expectEquals(1, peelingHoistTwoControl(0, 0, 1));
1040     expectEquals(1, peelingHoistTwoControl(0, 1, 0));
1041     expectEquals(1, peelingHoistTwoControl(0, 1, 1));
1042     expectEquals(2, peelingHoistTwoControl(1, 0, 0));
1043     expectEquals(2, peelingHoistTwoControl(1, 0, 1));
1044     expectEquals(3, peelingHoistTwoControl(1, 1, 0));
1045     expectEquals(3, peelingHoistTwoControl(1, 1, 1));
1046 
1047     initIntArray(a);
1048     peelingSimple(a, false);
1049     peelingSimple(a, true);
1050     peelingAddInts(a);
1051     peelingAddInts(null);  // okay
1052     peelingBreakFromNest(a, false);
1053     peelingBreakFromNest(a, true);
1054 
1055     unrollingSimpleLiveOuts(a);
1056 
1057     // Call unrollingWhileLiveOuts(a);
1058     Class<?> c = Class.forName("PeelUnroll");
1059     Method m = c.getMethod("unrollingWhileLiveOuts", Class.forName("[I"));
1060     Object[] arguments = { a };
1061     m.invoke(null, arguments);
1062 
1063     unrollingLiveOutsNested(a);
1064 
1065     int expected = 51565978;
1066     int found = 0;
1067     for (int i = 0; i < a.length; i++) {
1068       found += a[i];
1069     }
1070 
1071     expectEquals(expected, found);
1072   }
1073 
main(String[] args)1074   public static void main(String[] args) throws Exception {
1075     Main obj = new Main();
1076 
1077     obj.verifyUnrolling();
1078     obj.verifyPeeling();
1079 
1080     System.out.println("passed");
1081   }
1082 }
1083