1 /*
2  * Copyright (C) 2017 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 /**
18  * Tests for optimizations of break-loops, i.e. loops that break
19  * out of a while-true loop when the end condition is satisfied.
20  * In particular, the tests focus on break-loops that can be
21  * rewritten into regular countable loops (this may improve certain
22  * loops generated by the Kotlin compiler for inclusive ranges).
23  */
24 public class Main {
25 
26   /// CHECK-START: int Main.breakLoop(int[]) induction_var_analysis (before)
27   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                     loop:none
28   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                      loop:none
29   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                      loop:none
30   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                loop:none
31   /// CHECK-DAG: <<Phi:i\d+>>  Phi [<<Zero>>,<<AddI:i\d+>>]       loop:<<Loop:B\d+>> outer_loop:none
32   /// CHECK-DAG: <<Bnd:i\d+>>  BoundsCheck [<<Phi>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
33   /// CHECK-DAG:               ArraySet [<<Nil>>,<<Bnd>>,<<One>>] loop:<<Loop>>      outer_loop:none
34   /// CHECK-DAG: <<NE:z\d+>>   NotEqual [{{i\d+}},<<Phi>>]        loop:<<Loop>>      outer_loop:none
35   /// CHECK-DAG:               If [<<NE>>]                        loop:<<Loop>>      outer_loop:none
36   /// CHECK-DAG: <<AddI>>      Add [<<Phi>>,<<One>>]              loop:<<Loop>>      outer_loop:none
37   //
38   /// CHECK-START: int Main.breakLoop(int[]) induction_var_analysis (after)
39   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                     loop:none
40   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                      loop:none
41   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                      loop:none
42   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                loop:none
43   /// CHECK-DAG: <<Phi:i\d+>>  Phi [<<Zero>>,<<AddI:i\d+>>]       loop:<<Loop:B\d+>> outer_loop:none
44   /// CHECK-DAG: <<LE:z\d+>>   LessThanOrEqual [<<Phi>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
45   /// CHECK-DAG:               If [<<LE>>]                        loop:<<Loop>>      outer_loop:none
46   /// CHECK-DAG: <<Bnd:i\d+>>  BoundsCheck [<<Phi>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
47   /// CHECK-DAG:               ArraySet [<<Nil>>,<<Bnd>>,<<One>>] loop:<<Loop>>      outer_loop:none
48   /// CHECK-DAG: <<AddI>>      Add [<<Phi>>,<<One>>]              loop:<<Loop>>      outer_loop:none
49   //
50   /// CHECK-START-ARM64: int Main.breakLoop(int[]) loop_optimization (after)
51   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                          loop:none
52   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                           loop:none
53   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                     loop:none
54   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
55   //
56   ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<One>>,{{j\d+}}]             loop:none
57   ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                                      loop:<<Loop:B\d+>> outer_loop:none
58   ///     CHECK-DAG:                VecStore [<<Nil>>,<<Phi:i\d+>>,<<Rep>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
59   ///     CHECK-DAG:                Add [<<Phi>>,{{i\d+}}]                            loop:<<Loop>>      outer_loop:none
60   //
61   /// CHECK-ELSE:
62   //
63   ///     CHECK-DAG: <<Four:i\d+>>  IntConstant 4                           loop:none
64   ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<One>>]            loop:none
65   ///     CHECK-DAG:                VecStore [<<Nil>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none
66   ///     CHECK-DAG:                Add [<<Phi>>,<<Four>>]                  loop:<<Loop>>      outer_loop:none
67   //
68   /// CHECK-FI:
breakLoop(int[] a)69   static int breakLoop(int[] a) {
70     int l = 0;
71     int u = a.length - 1;
72     int i = l;
73     if (l <= u) {
74       while (true) {
75         a[i] = 1;
76         if (i == u) break;
77         i++;
78       }
79     }
80     return i;
81   }
82 
83   /// CHECK-START: int Main.breakLoopDown(int[]) induction_var_analysis (before)
84   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                     loop:none
85   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                      loop:none
86   /// CHECK-DAG: <<MOne:i\d+>> IntConstant -1                     loop:none
87   /// CHECK-DAG: <<Two:i\d+>>  IntConstant 2                      loop:none
88   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                loop:none
89   /// CHECK-DAG: <<Phi:i\d+>>  Phi [{{i\d+}},<<AddI:i\d+>>]       loop:<<Loop:B\d+>> outer_loop:none
90   /// CHECK-DAG: <<Bnd:i\d+>>  BoundsCheck [<<Phi>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
91   /// CHECK-DAG:               ArraySet [<<Nil>>,<<Bnd>>,<<Two>>] loop:<<Loop>>      outer_loop:none
92   /// CHECK-DAG: <<NE:z\d+>>   NotEqual [<<Phi>>,<<Zero>>]        loop:<<Loop>>      outer_loop:none
93   /// CHECK-DAG:               If [<<NE>>]                        loop:<<Loop>>      outer_loop:none
94   /// CHECK-DAG: <<AddI>>      Add [<<Phi>>,<<MOne>>]             loop:<<Loop>>      outer_loop:none
95   //
96   /// CHECK-START: int Main.breakLoopDown(int[]) induction_var_analysis (after)
97   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                        loop:none
98   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                         loop:none
99   /// CHECK-DAG: <<MOne:i\d+>> IntConstant -1                        loop:none
100   /// CHECK-DAG: <<Two:i\d+>>  IntConstant 2                         loop:none
101   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                   loop:none
102   /// CHECK-DAG: <<Phi:i\d+>>  Phi [{{i\d+}},<<AddI:i\d+>>]          loop:<<Loop:B\d+>> outer_loop:none
103   /// CHECK-DAG: <<GE:z\d+>>   GreaterThanOrEqual [<<Phi>>,<<Zero>>] loop:<<Loop>>      outer_loop:none
104   /// CHECK-DAG:               If [<<GE>>]                           loop:<<Loop>>      outer_loop:none
105   /// CHECK-DAG: <<Bnd:i\d+>>  BoundsCheck [<<Phi>>,{{i\d+}}]        loop:<<Loop>>      outer_loop:none
106   /// CHECK-DAG:               ArraySet [<<Nil>>,<<Bnd>>,<<Two>>]    loop:<<Loop>>      outer_loop:none
107   /// CHECK-DAG: <<AddI>>      Add [<<Phi>>,<<MOne>>]                loop:<<Loop>>      outer_loop:none
breakLoopDown(int[] a)108   static int breakLoopDown(int[] a) {
109     int l = 0;
110     int u = a.length - 1;
111     int i = u;
112     if (u >= l) {
113       while (true) {
114         a[i] = 2;
115         if (i == l) break;
116         i--;
117       }
118     }
119     return i;
120   }
121 
122   /// CHECK-START: int Main.breakLoopSafeConst(int[]) induction_var_analysis (before)
123   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
124   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
125   /// CHECK-DAG: <<Three:i\d+>> IntConstant 3                        loop:none
126   /// CHECK-DAG: <<L1:i\d+>>    IntConstant 2147483631               loop:none
127   /// CHECK-DAG: <<L2:i\d+>>    IntConstant 2147483646               loop:none
128   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<L1>>,<<AddI:i\d+>>]           loop:<<Loop:B\d+>> outer_loop:none
129   /// CHECK-DAG: <<Sub:i\d+>>   Sub [<<Phi>>,<<L1>>]                 loop:<<Loop>>      outer_loop:none
130   /// CHECK-DAG: <<Nil:l\d+>>   NullCheck [<<Par>>]                  loop:<<Loop>>      outer_loop:none
131   /// CHECK-DAG: <<Bnd:i\d+>>   BoundsCheck [<<Sub>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
132   /// CHECK-DAG:                ArraySet [<<Nil>>,<<Bnd>>,<<Three>>] loop:<<Loop>>      outer_loop:none
133   /// CHECK-DAG: <<NE:z\d+>>    NotEqual [<<Phi>>,<<L2>>]            loop:<<Loop>>      outer_loop:none
134   /// CHECK-DAG:                If [<<NE>>]                          loop:<<Loop>>      outer_loop:none
135   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
136   //
137   /// CHECK-START: int Main.breakLoopSafeConst(int[]) induction_var_analysis (after)
138   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                        loop:none
139   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
140   /// CHECK-DAG: <<Three:i\d+>> IntConstant 3                        loop:none
141   /// CHECK-DAG: <<L1:i\d+>>    IntConstant 2147483631               loop:none
142   /// CHECK-DAG: <<L2:i\d+>>    IntConstant 2147483646               loop:none
143   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<L1>>,<<AddI:i\d+>>]           loop:<<Loop:B\d+>> outer_loop:none
144   /// CHECK-DAG: <<LE:z\d+>>    LessThanOrEqual [<<Phi>>,<<L2>>]     loop:<<Loop>>      outer_loop:none
145   /// CHECK-DAG: <<Sub:i\d+>>   Sub [<<Phi>>,<<L1>>]                 loop:<<Loop>>      outer_loop:none
146   /// CHECK-DAG: <<Nil:l\d+>>   NullCheck [<<Par>>]                  loop:<<Loop>>      outer_loop:none
147   /// CHECK-DAG: <<Bnd:i\d+>>   BoundsCheck [<<Sub>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
148   /// CHECK-DAG:                ArraySet [<<Nil>>,<<Bnd>>,<<Three>>] loop:<<Loop>>      outer_loop:none
149   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
150   //
151   /// CHECK-START-ARM64: int Main.breakLoopSafeConst(int[]) loop_optimization (after)
152   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                          loop:none
153   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                           loop:none
154   /// CHECK-DAG: <<Three:i\d+>> IntConstant 3                           loop:none
155   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
156   //
157   ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Three>>,{{j\d+}}]           loop:none
158   ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                                      loop:<<Loop:B\d+>> outer_loop:none
159   ///     CHECK-DAG:                VecStore [<<Par>>,<<Phi:i\d+>>,<<Rep>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
160   ///     CHECK-DAG:                Add [<<Phi>>,{{i\d+}}]                            loop:<<Loop>>      outer_loop:none
161   //
162   /// CHECK-ELSE:
163   //
164   ///     CHECK-DAG: <<Four:i\d+>>  IntConstant 4                           loop:none
165   ///     CHECK-DAG: <<Rep:d\d+>>   VecReplicateScalar [<<Three>>]          loop:none
166   ///     CHECK-DAG:                VecStore [<<Par>>,<<Phi:i\d+>>,<<Rep>>] loop:<<Loop:B\d+>> outer_loop:none
167   ///     CHECK-DAG:                Add [<<Phi>>,<<Four>>]                  loop:<<Loop>>      outer_loop:none
168   //
169   /// CHECK-FI:
breakLoopSafeConst(int[] a)170   static int breakLoopSafeConst(int[] a) {
171     int l = Integer.MAX_VALUE - 16;
172     int u = Integer.MAX_VALUE - 1;
173     int i = l;
174     if (l <= u) {  // will be removed by simplifier
175       while (true) {
176         a[i - l] = 3;
177         if (i == u) break;
178         i++;
179       }
180     }
181     return i;
182   }
183 
184   /// CHECK-START: int Main.breakLoopUnsafeConst(int[]) induction_var_analysis (before)
185   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue                       loop:none
186   /// CHECK-DAG: <<One:i\d+>>   IntConstant 1                        loop:none
187   /// CHECK-DAG: <<Four:i\d+>>  IntConstant 4                        loop:none
188   /// CHECK-DAG: <<L1:i\d+>>    IntConstant 2147483632               loop:none
189   /// CHECK-DAG: <<L2:i\d+>>    IntConstant 2147483647               loop:none
190   /// CHECK-DAG: <<Phi:i\d+>>   Phi [<<L1>>,<<AddI:i\d+>>]           loop:<<Loop:B\d+>> outer_loop:none
191   /// CHECK-DAG: <<Sub:i\d+>>   Sub [<<Phi>>,<<L1>>]                 loop:<<Loop>>      outer_loop:none
192   /// CHECK-DAG: <<Nil:l\d+>>   NullCheck [<<Par>>]                  loop:<<Loop>>      outer_loop:none
193   /// CHECK-DAG: <<Bnd:i\d+>>   BoundsCheck [<<Sub>>,{{i\d+}}]       loop:<<Loop>>      outer_loop:none
194   /// CHECK-DAG:                ArraySet [<<Nil>>,<<Bnd>>,<<Four>>]  loop:<<Loop>>      outer_loop:none
195   /// CHECK-DAG: <<NE:z\d+>>    NotEqual [<<Phi>>,<<L2>>]            loop:<<Loop>>      outer_loop:none
196   /// CHECK-DAG:                If [<<NE>>]                          loop:<<Loop>>      outer_loop:none
197   /// CHECK-DAG: <<AddI>>       Add [<<Phi>>,<<One>>]                loop:<<Loop>>      outer_loop:none
198   //
199   /// CHECK-START: int Main.breakLoopUnsafeConst(int[]) induction_var_analysis (after)
200   /// CHECK-DAG:                NotEqual
201   /// CHECK-NOT:                LessThanOrEqual
breakLoopUnsafeConst(int[] a)202   static int breakLoopUnsafeConst(int[] a) {
203     int l = Integer.MAX_VALUE - 15;
204     int u = Integer.MAX_VALUE;
205     int i = l;
206     if (l <= u) {  // will be removed by simplifier
207       while (true) {
208         a[i - l] = 4;
209         if (i == u) break;  // rewriting exit not safe!
210         i++;
211       }
212     }
213     return i;
214   }
215 
216   /// CHECK-START: int Main.breakLoopNastyPhi(int[]) induction_var_analysis (before)
217   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                      loop:none
218   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                       loop:none
219   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                       loop:none
220   /// CHECK-DAG: <<Five:i\d+>> IntConstant 5                       loop:none
221   /// CHECK-DAG: <<M123:i\d+>> IntConstant -123                    loop:none
222   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                 loop:none
223   /// CHECK-DAG: <<Phi:i\d+>>  Phi [<<Zero>>,<<AddI:i\d+>>]        loop:<<Loop:B\d+>> outer_loop:none
224   /// CHECK-DAG: <<Wrap:i\d+>> Phi [<<M123>>,<<Phi>>]              loop:<<Loop>>      outer_loop:none
225   /// CHECK-DAG: <<Bnd:i\d+>>  BoundsCheck [<<Phi>>,{{i\d+}}]      loop:<<Loop>>      outer_loop:none
226   /// CHECK-DAG:               ArraySet [<<Nil>>,<<Bnd>>,<<Five>>] loop:<<Loop>>      outer_loop:none
227   /// CHECK-DAG: <<NE:z\d+>>   NotEqual [{{i\d+}},<<Phi>>]         loop:<<Loop>>      outer_loop:none
228   /// CHECK-DAG:               If [<<NE>>]                         loop:<<Loop>>      outer_loop:none
229   /// CHECK-DAG: <<AddI>>      Add [<<Phi>>,<<One>>]               loop:<<Loop>>      outer_loop:none
230   /// CHECK-DAG: <<Comb:i\d+>> Phi [<<M123>>,<<Wrap>>]             loop:none
231   /// CHECK-DAG:               Return [<<Comb>>]                   loop:none
232   //
233   /// CHECK-START: int Main.breakLoopNastyPhi(int[]) induction_var_analysis (after)
234   /// CHECK-DAG:               NotEqual
235   /// CHECK-NOT:               LessThanOrEqual
breakLoopNastyPhi(int[] a)236   static int breakLoopNastyPhi(int[] a) {
237     int l = 0;
238     int u = a.length - 1;
239     int x = -123;
240     if (l <= u) {
241       int i = l;
242       while (true) {
243         a[i] = 5;
244         if (i == u) break;
245         x = i;
246         i++;
247       }
248     }
249     return x;  // keep another phi live
250   }
251 
252   /// CHECK-START: int Main.breakLoopReduction(int[]) induction_var_analysis (before)
253   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                 loop:none
254   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                  loop:none
255   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                  loop:none
256   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                 loop:none
257   /// CHECK-DAG: <<Red:i\d+>>  Phi [<<Zero>>,<<RedI:i\d+>>]   loop:<<Loop:B\d+>> outer_loop:none
258   /// CHECK-DAG: <<Phi:i\d+>>  Phi [<<Zero>>,<<AddI:i\d+>>]   loop:<<Loop>>      outer_loop:none
259   /// CHECK-DAG: <<Bnd:i\d+>>  BoundsCheck [<<Phi>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
260   /// CHECK-DAG: <<Get:i\d+>>  ArrayGet [<<Nil>>,<<Bnd>>]     loop:<<Loop>>      outer_loop:none
261   /// CHECK-DAG: <<RedI>>      Add [<<Red>>,<<Get>>]          loop:<<Loop>>      outer_loop:none
262   /// CHECK-DAG: <<NE:z\d+>>   NotEqual [{{i\d+}},<<Phi>>]    loop:<<Loop>>      outer_loop:none
263   /// CHECK-DAG:               If [<<NE>>]                    loop:<<Loop>>      outer_loop:none
264   /// CHECK-DAG: <<AddI>>      Add [<<Phi>>,<<One>>]          loop:<<Loop>>      outer_loop:none
265   /// CHECK-DAG: <<Comb:i\d+>> Phi [<<Zero>>,<<RedI>>]        loop:none
266   /// CHECK-DAG:               Return [<<Comb>>]              loop:none
267   //
268   /// CHECK-START: int Main.breakLoopReduction(int[]) induction_var_analysis (after)
269   /// CHECK-DAG: <<Par:l\d+>>  ParameterValue                     loop:none
270   /// CHECK-DAG: <<Zero:i\d+>> IntConstant 0                      loop:none
271   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                      loop:none
272   /// CHECK-DAG: <<Nil:l\d+>>  NullCheck [<<Par>>]                loop:none
273   /// CHECK-DAG: <<Red:i\d+>>  Phi [<<Zero>>,<<RedI:i\d+>>]       loop:<<Loop:B\d+>> outer_loop:none
274   /// CHECK-DAG: <<Phi:i\d+>>  Phi [<<Zero>>,<<AddI:i\d+>>]       loop:<<Loop>>      outer_loop:none
275   /// CHECK-DAG: <<LE:z\d+>>   LessThanOrEqual [<<Phi>>,{{i\d+}}] loop:<<Loop>>      outer_loop:none
276   /// CHECK-DAG:               If [<<LE>>]                        loop:<<Loop>>      outer_loop:none
277   /// CHECK-DAG: <<Bnd:i\d+>>  BoundsCheck [<<Phi>>,{{i\d+}}]     loop:<<Loop>>      outer_loop:none
278   /// CHECK-DAG: <<Get:i\d+>>  ArrayGet [<<Nil>>,<<Bnd>>]         loop:<<Loop>>      outer_loop:none
279   /// CHECK-DAG: <<RedI>>      Add [<<Red>>,<<Get>>]              loop:<<Loop>>      outer_loop:none
280   /// CHECK-DAG: <<AddI>>      Add [<<Phi>>,<<One>>]              loop:<<Loop>>      outer_loop:none
281   /// CHECK-DAG: <<Comb:i\d+>> Phi [<<Zero>>,<<Red>>]             loop:none
282   /// CHECK-DAG:               Return [<<Comb>>]                  loop:none
283   //
284   /// CHECK-START-ARM64: int Main.breakLoopReduction(int[]) loop_optimization (after)
285   /// CHECK-DAG: <<Par:l\d+>>   ParameterValue              loop:none
286   /// CHECK-DAG: <<Zero:i\d+>>  IntConstant 0               loop:none
287   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
288   //
289   ///     CHECK-DAG: <<Exp:d\d+>>   VecSetScalars [<<Zero>>,{{j\d+}}]     loop:none
290   ///     CHECK-DAG: <<LoopP:j\d+>> VecPredWhile                          loop:<<Loop:B\d+>> outer_loop:none
291   ///     CHECK-DAG: <<VPhi:d\d+>>  Phi [<<Exp>>,<<VAdd:d\d+>>]           loop:<<Loop>>      outer_loop:none
292   ///     CHECK-DAG: <<VLoad:d\d+>> VecLoad                               loop:<<Loop>>      outer_loop:none
293   ///     CHECK-DAG: <<VAdd>>       VecAdd [<<VPhi>>,<<VLoad>>,<<LoopP>>] loop:<<Loop>>      outer_loop:none
294   //
295   /// CHECK-ELSE:
296   //
297   ///     CHECK-DAG: <<Exp:d\d+>>   VecSetScalars [<<Zero>>]    loop:none
298   ///     CHECK-DAG: <<VPhi:d\d+>>  Phi [<<Exp>>,<<VAdd:d\d+>>] loop:<<Loop:B\d+>> outer_loop:none
299   ///     CHECK-DAG: <<VLoad:d\d+>> VecLoad                     loop:<<Loop>>      outer_loop:none
300   ///     CHECK-DAG: <<VAdd>>       VecAdd [<<VPhi>>,<<VLoad>>] loop:<<Loop>>      outer_loop:none
301   //
302   /// CHECK-FI:
breakLoopReduction(int[] a)303   static int breakLoopReduction(int[] a) {
304     int l = 0;
305     int u = a.length - 1;
306     int x = 0;
307     if (l <= u) {
308       int i = l;
309       while (true) {
310         x += a[i];
311         if (i == u) break;
312         i++;
313       }
314     }
315     return x;
316   }
317 
318   //
319   // Test driver.
320   //
321 
main(String[] args)322   public static void main(String[] args) {
323     int[] a = new int[100];
324 
325     expectEquals(99, breakLoop(a));
326     for (int i = 0; i < a.length; i++) {
327       expectEquals(1, a[i]);
328     }
329 
330     expectEquals(0, breakLoopDown(a));
331     for (int i = 0; i < a.length; i++) {
332       expectEquals(2, a[i]);
333     }
334 
335     expectEquals(Integer.MAX_VALUE - 1, breakLoopSafeConst(a));
336     for (int i = 0; i < a.length; i++) {
337       int e = i < 16 ? 3 : 2;
338       expectEquals(e, a[i]);
339     }
340 
341     expectEquals(Integer.MAX_VALUE, breakLoopUnsafeConst(a));
342     for (int i = 0; i < a.length; i++) {
343       int e = i < 16 ? 4 : 2;
344       expectEquals(e, a[i]);
345     }
346 
347     expectEquals(98, breakLoopNastyPhi(a));
348     for (int i = 0; i < a.length; i++) {
349       expectEquals(5, a[i]);
350     }
351 
352     expectEquals(500, breakLoopReduction(a));
353 
354     System.out.println("passed");
355   }
356 
357   private static void expectEquals(int expected, int result) {
358     if (expected != result) {
359       throw new Error("Expected: " + expected + ", found: " + result);
360     }
361   }
362 }
363