xref: /aosp_15_r20/art/test/661-checker-simd-cf-loops/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1 /*
2  * Copyright (C) 2023 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 autovectorization of loops with control flow.
19  */
20 public class Main {
21 
22   public static final int ARRAY_LENGTH = 128;
23   public static final int USED_ARRAY_LENGTH = ARRAY_LENGTH - 1;
24 
25   public static boolean[] booleanArray = new boolean[ARRAY_LENGTH];
26   public static boolean[] booleanArray2 = new boolean[ARRAY_LENGTH];
27   public static byte[] byteArray = new byte[ARRAY_LENGTH];
28   public static short[] shortArray = new short[ARRAY_LENGTH];
29   public static char[] charArray = new char[ARRAY_LENGTH];
30   public static int[] intArray = new int[ARRAY_LENGTH];
31   public static long[] longArray = new long[ARRAY_LENGTH];
32   public static float[] floatArray = new float[ARRAY_LENGTH];
33   public static double[] doubleArray = new double[ARRAY_LENGTH];
34 
35   public static final int MAGIC_VALUE_A = 2;
36   public static final int MAGIC_VALUE_B = 10;
37   public static final int MAGIC_VALUE_C = 100;
38 
39   public static final int MAGIC_ADD_CONST = 99;
40 
41   public static final float MAGIC_FLOAT_VALUE_A = 2.0f;
42   public static final float MAGIC_FLOAT_VALUE_B = 10.0f;
43   public static final float MAGIC_FLOAT_VALUE_C = 100.0f;
44 
45   public static final float MAGIC_FLOAT_ADD_CONST = 99.0f;
46 
47   /// CHECK-START-ARM64: int Main.$compile$noinline$FullDiamond(int[]) loop_optimization (after)
48   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
49   //
50   ///     CHECK-DAG: <<C0:i\d+>>      IntConstant 0                                         loop:none
51   ///     CHECK-DAG: <<C4:i\d+>>      IntConstant 4                                         loop:none
52   ///     CHECK-DAG: <<C99:i\d+>>     IntConstant 99                                        loop:none
53   ///     CHECK-DAG: <<C100:i\d+>>    IntConstant 100                                       loop:none
54   ///     CHECK-DAG: <<Vec4:d\d+>>    VecReplicateScalar [<<C4>>,{{j\d+}}]                  loop:none
55   ///     CHECK-DAG: <<Vec99:d\d+>>   VecReplicateScalar [<<C99>>,{{j\d+}}]                 loop:none
56   ///     CHECK-DAG: <<Vec100:d\d+>>  VecReplicateScalar [<<C100>>,{{j\d+}}]                loop:none
57   //
58   ///     CHECK-DAG: <<Phi:i\d+>>     Phi [<<C0>>,{{i\d+}}]                                 loop:<<Loop:B\d+>> outer_loop:none
59   ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi>>,{{i\d+}}]                       loop:<<Loop>>      outer_loop:none
60   //
61   ///     CHECK-DAG: <<Load1:d\d+>>   VecLoad [<<Arr:l\d+>>,<<Phi>>,<<LoopP>>]              loop:<<Loop>>      outer_loop:none
62   ///     CHECK-DAG: <<Cond:j\d+>>    VecEqual [<<Load1>>,<<Vec100>>,<<LoopP>>]             loop:<<Loop>>      outer_loop:none
63   ///     CHECK-DAG: <<CondR:j\d+>>   VecPredNot [<<Cond>>,<<LoopP>>]                       loop:<<Loop>>      outer_loop:none
64   ///     CHECK-DAG: <<AddT:d\d+>>    VecAdd [<<Load1>>,<<Vec99>>,<<CondR>>]                loop:<<Loop>>      outer_loop:none
65   ///     CHECK-DAG: <<StT:d\d+>>     VecStore [<<Arr>>,<<Phi>>,<<AddT>>,<<CondR>>]         loop:<<Loop>>      outer_loop:none
66   ///     CHECK-DAG: <<StF:d\d+>>     VecStore [<<Arr>>,<<Phi>>,{{d\d+}},<<Cond>>]          loop:<<Loop>>      outer_loop:none
67   ///     CHECK-DAG: <<Ld2:d\d+>>     VecLoad [<<Arr>>,<<Phi>>,<<LoopP>>]                   loop:<<Loop>>      outer_loop:none
68   ///     CHECK-DAG: <<Add2:d\d+>>    VecAdd [<<Ld2>>,<<Vec4>>,<<LoopP>>]                   loop:<<Loop>>      outer_loop:none
69   ///     CHECK-DAG: <<St21:d\d+>>    VecStore [<<Arr>>,<<Phi>>,<<Add2>>,<<LoopP>>]         loop:<<Loop>>      outer_loop:none
70   //
71   /// CHECK-ELSE:
72   //
73   ///     CHECK-NOT:                      VecLoad
74   //
75   /// CHECK-FI:
$compile$noinline$FullDiamond(int[] x)76   public static int $compile$noinline$FullDiamond(int[] x) {
77     int i = 0;
78     for (; i < USED_ARRAY_LENGTH; i++) {
79       int val = x[i];
80       if (val != MAGIC_VALUE_C) {
81         x[i] += MAGIC_ADD_CONST;
82       } else {
83         x[i] += 3;
84       }
85       x[i] += 4;
86     }
87     return i;
88   }
89 
90   //
91   // Test various types.
92   //
93 
94   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleBoolean(boolean[], boolean[]) loop_optimization (after)
95   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
96   //
97   ///     CHECK-NOT: VecLoad
98   //
99   /// CHECK-FI:
100   //
101   // TODO: Support extra condition types and boolean comparisons.
$compile$noinline$SimpleBoolean(boolean[] x, boolean[] y)102   public static void $compile$noinline$SimpleBoolean(boolean[] x, boolean[] y) {
103     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
104       boolean val = x[i];
105       if (val != y[i]) {
106         x[i] |= y[i];
107       }
108     }
109   }
110 
111   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleByte(byte[]) loop_optimization (after)
112   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
113   //
114   ///     CHECK-DAG: VecLoad
115   //
116   /// CHECK-FI:
$compile$noinline$SimpleByte(byte[] x)117   public static void $compile$noinline$SimpleByte(byte[] x) {
118     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
119       byte val = x[i];
120       if (val != MAGIC_VALUE_C) {
121         x[i] += MAGIC_ADD_CONST;
122       }
123     }
124   }
125 
126   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleUByte(byte[]) loop_optimization (after)
127   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
128   //
129   ///     CHECK-DAG: VecLoad
130   //
131   /// CHECK-FI:
$compile$noinline$SimpleUByte(byte[] x)132   public static void $compile$noinline$SimpleUByte(byte[] x) {
133     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
134       if ((x[i] & 0xFF) != MAGIC_VALUE_C) {
135         x[i] += MAGIC_ADD_CONST;
136       }
137     }
138   }
139 
140   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleShort(short[]) loop_optimization (after)
141   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
142   //
143   ///     CHECK-DAG: VecLoad
144   //
145   /// CHECK-FI:
$compile$noinline$SimpleShort(short[] x)146   public static void $compile$noinline$SimpleShort(short[] x) {
147     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
148       short val = x[i];
149       if (val != MAGIC_VALUE_C) {
150         x[i] += MAGIC_ADD_CONST;
151       }
152     }
153   }
154 
155   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleChar(char[]) loop_optimization (after)
156   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
157   //
158   ///     CHECK-DAG: VecLoad
159   //
160   /// CHECK-FI:
$compile$noinline$SimpleChar(char[] x)161   public static void $compile$noinline$SimpleChar(char[] x) {
162     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
163       char val = x[i];
164       if (val != MAGIC_VALUE_C) {
165         x[i] += MAGIC_ADD_CONST;
166       }
167     }
168   }
169 
170   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleInt(int[]) loop_optimization (after)
171   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
172   //
173   ///     CHECK-DAG: VecLoad
174   //
175   /// CHECK-FI:
$compile$noinline$SimpleInt(int[] x)176   public static void $compile$noinline$SimpleInt(int[] x) {
177     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
178       int val = x[i];
179       if (val != MAGIC_VALUE_C) {
180         x[i] += MAGIC_ADD_CONST;
181       }
182     }
183   }
184 
185   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleLong(long[]) loop_optimization (after)
186   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
187   //
188   ///     CHECK-NOT: VecLoad
189   //
190   /// CHECK-FI:
191   //
192   // TODO: Support long comparisons.
$compile$noinline$SimpleLong(long[] x)193   public static void $compile$noinline$SimpleLong(long[] x) {
194     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
195       long val = x[i];
196       if (val != MAGIC_VALUE_C) {
197         x[i] += MAGIC_ADD_CONST;
198       }
199     }
200   }
201 
202   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleFloat(float[]) loop_optimization (after)
203   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
204   //
205   ///     CHECK-NOT: VecLoad
206   //
207   /// CHECK-FI:
208   //
209   // TODO: Support FP comparisons.
$compile$noinline$SimpleFloat(float[] x)210   public static void $compile$noinline$SimpleFloat(float[] x) {
211     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
212       float val = x[i];
213       if (val > 10.0f) {
214         x[i] += 99.1f;
215       }
216     }
217   }
218 
219   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleDouble(double[]) loop_optimization (after)
220   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
221   //
222   ///     CHECK-NOT: VecLoad
223   //
224   /// CHECK-FI:
225   //
226   // TODO: Support FP comparisons.
$compile$noinline$SimpleDouble(double[] x)227   public static void $compile$noinline$SimpleDouble(double[] x) {
228     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
229       double val = x[i];
230       if (val != 10.0) {
231         x[i] += 99.1;
232       }
233     }
234   }
235 
236   //
237   // Narrowing types.
238   //
239 
240   /// CHECK-START-ARM64: void Main.$compile$noinline$ByteConv(byte[], byte[]) loop_optimization (after)
241   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
242   //
243   ///     CHECK-DAG: VecLoad
244   //
245   /// CHECK-FI:
$compile$noinline$ByteConv(byte[] x, byte[] y)246   public static void $compile$noinline$ByteConv(byte[] x, byte[] y) {
247     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
248       byte val = (byte)(x[i] + 1);
249       if (val != y[i]) {
250         x[i] += MAGIC_ADD_CONST;
251       }
252     }
253   }
254 
255   /// CHECK-START-ARM64: void Main.$compile$noinline$UByteAndWrongConst(byte[]) loop_optimization (after)
256   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
257   //
258   ///     CHECK-NOT: VecLoad
259   //
260   /// CHECK-FI:
261   //
262   // 'NarrowerOperands' not met: the constant is not a ubyte one.
$compile$noinline$UByteAndWrongConst(byte[] x)263   public static void $compile$noinline$UByteAndWrongConst(byte[] x) {
264     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
265       if ((x[i] & 0xFF) != (MAGIC_VALUE_C | 0x100)) {
266         x[i] += MAGIC_ADD_CONST;
267       }
268     }
269   }
270 
271   /// CHECK-START-ARM64: void Main.$compile$noinline$ByteNoHiBits(byte[], byte[]) loop_optimization (after)
272   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
273   //
274   ///     CHECK-NOT: VecLoad
275   //
276   /// CHECK-FI:
277   //
278   // Check kNoHiBits case when "wider" operations cannot bring in higher order bits.
$compile$noinline$ByteNoHiBits(byte[] x, byte[] y)279   public static void $compile$noinline$ByteNoHiBits(byte[] x, byte[] y) {
280     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
281       byte val = x[i];
282       if ((val >>> 3) != y[i]) {
283         x[i] += MAGIC_ADD_CONST;
284       }
285     }
286   }
287 
288   //
289   // Test condition types.
290   //
291 
292   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleCondition(int[]) loop_optimization (before)
293   //
294   ///     CHECK-DAG: <<C0:i\d+>>      IntConstant 0                                                           loop:none
295   ///     CHECK-DAG: <<C100:i\d+>>    IntConstant 100                                                         loop:none
296   ///     CHECK-DAG: <<C199:i\d+>>    IntConstant 199                                                         loop:none
297   //
298   ///     CHECK-DAG: <<Phi:i\d+>>     Phi [<<C0>>,{{i\d+}}]                                                   loop:<<Loop:B\d+>>
299   ///     CHECK-DAG: <<Load:i\d+>>    ArrayGet [<<Arr:l\d+>>,<<Phi>>]                                         loop:<<Loop>>
300   ///     CHECK-DAG: <<Cond:z\d+>>    NotEqual [<<Load>>,<<C100>>]                                            loop:<<Loop>>
301   ///     CHECK-DAG:                  If [<<Cond>>]                                                           loop:<<Loop>>
302   //
303   ///     CHECK-DAG:                  ArraySet [<<Arr>>,<<Phi>>,<<C199>>]                                     loop:<<Loop>>
304   //
305   /// CHECK-START-ARM64: void Main.$compile$noinline$SimpleCondition(int[]) loop_optimization (after)
306   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
307   //
308   ///     CHECK-DAG: <<C0:i\d+>>      IntConstant 0                                                           loop:none
309   ///     CHECK-DAG: <<C100:i\d+>>    IntConstant 100                                                         loop:none
310   ///     CHECK-DAG: <<C199:i\d+>>    IntConstant 199                                                         loop:none
311   //
312   ///     CHECK-DAG: <<Vec100:d\d+>>  VecReplicateScalar [<<C100>>,{{j\d+}}]           packed_type:Int32      loop:none
313   ///     CHECK-DAG: <<Vec199:d\d+>>  VecReplicateScalar [<<C199>>,{{j\d+}}]           packed_type:Int32      loop:none
314   //
315   ///     CHECK-DAG: <<Phi:i\d+>>     Phi [<<C0>>,{{i\d+}}]                                                   loop:<<Loop:B\d+>>
316   ///     CHECK-DAG: <<LoopP:j\d+>>   VecPredWhile [<<Phi>>,{{i\d+}}]                                         loop:<<Loop>>
317   //
318   ///     CHECK-DAG: <<Load:d\d+>>    VecLoad [<<Arr:l\d+>>,<<Phi>>,<<LoopP>>]         packed_type:Int32      loop:<<Loop>>
319   ///     CHECK-DAG: <<Cond:j\d+>>    VecNotEqual [<<Load>>,<<Vec100>>,<<LoopP>>]      packed_type:Int32      loop:<<Loop>>
320   ///     CHECK-DAG: <<CondR:j\d+>>   VecPredNot [<<Cond>>,<<LoopP>>]                  packed_type:Int32      loop:<<Loop>>
321   ///     CHECK-DAG:                  VecStore [<<Arr>>,<<Phi>>,<<Vec199>>,<<CondR>>]  packed_type:Int32      loop:<<Loop>>
322   //
323   /// CHECK-FI:
324   //
325   // Example of a condition being vectorized. See loop_optimization_test.cc and codegen_test.cc for
326   // full testing of vector conditions.
$compile$noinline$SimpleCondition(int[] x)327   public static void $compile$noinline$SimpleCondition(int[] x) {
328     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
329       int val = x[i];
330       if (val == MAGIC_VALUE_C) {
331         x[i] += MAGIC_ADD_CONST;
332       }
333     }
334   }
335 
336   //
337   // Test vectorization idioms.
338   //
339 
340   /// CHECK-START-ARM64: void Main.$compile$noinline$Select(int[]) loop_optimization (after)
341   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
342   //
343   ///     CHECK-NOT: VecLoad
344   //
345   /// CHECK-FI:
346   //
347   // TODO: vectorize loops with select in the body.
$compile$noinline$Select(int[] x)348   public static void $compile$noinline$Select(int[] x) {
349     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
350       int val = x[i];
351       if (val != MAGIC_VALUE_C) {
352         val += MAGIC_ADD_CONST;
353       }
354       x[i] = val;
355     }
356   }
357 
358   /// CHECK-START-ARM64: void Main.$compile$noinline$Phi(int[]) loop_optimization (after)
359   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
360   //
361   ///     CHECK-NOT: VecLoad
362   //
363   /// CHECK-FI:
364   //
365   // TODO: vectorize loops with phis in the body.
$compile$noinline$Phi(int[] x)366   public static void $compile$noinline$Phi(int[] x) {
367     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
368       int val = x[i];
369       if (val != MAGIC_VALUE_C) {
370         val += MAGIC_ADD_CONST;
371         x[i] += val;
372       }
373       x[i] += val;
374     }
375   }
376 
377   // TODO: when Phis are supported, test dotprod and sad idioms.
378 
379   /// CHECK-START-ARM64: int Main.$compile$noinline$Reduction(int[]) loop_optimization (after)
380   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
381   //
382   ///     CHECK-NOT: VecLoad
383   //
384   /// CHECK-FI:
385   //
386   // TODO: vectorize loops with phis and reductions in the body.
$compile$noinline$Reduction(int[] x)387   private static int $compile$noinline$Reduction(int[] x) {
388     int sum = 0;
389     for (int i = 0; i < ARRAY_LENGTH; i++) {
390       int val = x[i];
391       if (val != MAGIC_VALUE_C) {
392         sum += val + x[i];
393       }
394     }
395     return sum;
396   }
397 
398   /// CHECK-START-ARM64: int Main.$compile$noinline$ReductionBackEdge(int[]) loop_optimization (after)
399   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
400   //
401   ///     CHECK-DAG: VecLoad
402   //
403   /// CHECK-FI:
404   //
405   // Reduction in the back edge block, non-CF-dependent.
$compile$noinline$ReductionBackEdge(int[] x)406   public static int $compile$noinline$ReductionBackEdge(int[] x) {
407     int sum = 0;
408     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
409       int val = x[i];
410       if (val != MAGIC_VALUE_C) {
411         x[i] += MAGIC_ADD_CONST;
412       }
413       sum += x[i];
414     }
415     return sum;
416   }
417 
418   //
419   // Negative compile tests.
420   //
421 
422   public static final int STENCIL_ARRAY_SIZE = 130;
423 
424   /// CHECK-START-ARM64: void Main.$compile$noinline$stencilAlike(int[], int[]) loop_optimization (after)
425   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
426   //
427   ///     CHECK-NOT: VecLoad
428   //
429   /// CHECK-FI:
430   //
431   // This loop needs a runtime test for array references disambiguation and a scalar cleanup loop.
432   // Currently we can't generate a scalar clean up loop with control flow.
$compile$noinline$stencilAlike(int[] a, int[] b)433   private static void $compile$noinline$stencilAlike(int[] a, int[] b) {
434     for (int i = 1; i < STENCIL_ARRAY_SIZE - 1; i++) {
435       int val0 = b[i - 1];
436       int val1 = b[i];
437       int val2 = b[i + 1];
438       int un = a[i];
439       if (val1 != MAGIC_VALUE_C) {
440         a[i] = val0 + val1 + val2;
441       }
442     }
443   }
444 
445   /// CHECK-START-ARM64: void Main.$compile$noinline$NotDiamondCf(int[]) loop_optimization (after)
446   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
447   //
448   ///     CHECK-NOT: VecLoad
449   //
450   /// CHECK-FI:
451   //
452   // Loops with complex CF are not supported.
$compile$noinline$NotDiamondCf(int[] x)453   public static void $compile$noinline$NotDiamondCf(int[] x) {
454     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
455       int val = x[i];
456       if (val != MAGIC_VALUE_C) {
457         if (val != 1234) {
458           x[i] += MAGIC_ADD_CONST;
459         }
460       }
461     }
462   }
463 
464   /// CHECK-START-ARM64: void Main.$compile$noinline$BrokenInduction(int[]) loop_optimization (after)
465   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
466   //
467   ///     CHECK-NOT: VecLoad
468   //
469   /// CHECK-FI:
$compile$noinline$BrokenInduction(int[] x)470   public static void $compile$noinline$BrokenInduction(int[] x) {
471     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
472       int val = x[i];
473       if (val != MAGIC_VALUE_C) {
474         x[i] += MAGIC_ADD_CONST;
475         i++;
476       }
477     }
478   }
479 
480   //
481   // Non-condition if statements.
482   //
483 
484   /// CHECK-START-ARM64: void Main.$compile$noinline$SingleBoolean(int[], boolean) loop_optimization (after)
485   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
486   //
487   ///     CHECK-NOT: VecLoad
488   //
489   /// CHECK-FI:
490   //
491   // Check that single boolean if statements are not vectorized because only binary condition if
492   // statements are supported.
$compile$noinline$SingleBoolean(int[] x, boolean y)493   public static void $compile$noinline$SingleBoolean(int[] x, boolean y) {
494     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
495       if (y) {
496         x[i] += MAGIC_ADD_CONST;
497       }
498     }
499   }
500 
501   /// CHECK-START-ARM64: void Main.$compile$noinline$InstanceOf(int[], java.lang.Object) loop_optimization (after)
502   /// CHECK-IF:     hasIsaFeature("sve") and os.environ.get('ART_FORCE_TRY_PREDICATED_SIMD') == 'true'
503   //
504   ///     CHECK-NOT: VecLoad
505   //
506   /// CHECK-FI:
507   //
508   // Check that control flow without a condition is not vectorized because only binary condition if
509   // statements are supported.
$compile$noinline$InstanceOf(int[] x, Object y)510   public static void $compile$noinline$InstanceOf(int[] x, Object y) {
511     for (int i = 0; i < USED_ARRAY_LENGTH; i++) {
512       if (y instanceof Main) {
513         x[i] += MAGIC_ADD_CONST;
514       }
515     }
516   }
517 
518   //
519   // Main driver.
520   //
521 
main(String[] args)522   public static void main(String[] args) {
523     initIntArray(intArray);
524     int final_ind_value = $compile$noinline$FullDiamond(intArray);
525     expectIntEquals(23755, IntArraySum(intArray));
526     expectIntEquals(USED_ARRAY_LENGTH, final_ind_value);
527 
528     // Types.
529     initBooleanArray(booleanArray);
530     booleanArray2[12] = true;
531     $compile$noinline$SimpleBoolean(booleanArray, booleanArray2);
532     expectIntEquals(86, BooleanArraySum(booleanArray));
533 
534     initByteArray(byteArray);
535     $compile$noinline$SimpleByte(byteArray);
536     expectIntEquals(-64, ByteArraySum(byteArray));
537 
538     initByteArray(byteArray);
539     $compile$noinline$SimpleUByte(byteArray);
540     expectIntEquals(-64, ByteArraySum(byteArray));
541 
542     initShortArray(shortArray);
543     $compile$noinline$SimpleShort(shortArray);
544     expectIntEquals(23121, ShortArraySum(shortArray));
545 
546     initCharArray(charArray);
547     $compile$noinline$SimpleChar(charArray);
548     expectIntEquals(23121, CharArraySum(charArray));
549 
550     initIntArray(intArray);
551     $compile$noinline$SimpleInt(intArray);
552     expectIntEquals(23121, IntArraySum(intArray));
553 
554     initLongArray(longArray);
555     $compile$noinline$SimpleLong(longArray);
556     expectLongEquals(23121, LongArraySum(longArray));
557 
558     initFloatArray(floatArray);
559     $compile$noinline$SimpleFloat(floatArray);
560     expectFloatEquals(18868.2f, FloatArraySum(floatArray));
561 
562     initDoubleArray(doubleArray);
563     $compile$noinline$SimpleDouble(doubleArray);
564     expectDoubleEquals(23129.5, DoubleArraySum(doubleArray));
565 
566     // Narrowing types.
567     initByteArray(byteArray);
568     $compile$noinline$ByteConv(byteArray, byteArray);
569     expectIntEquals(-2, ByteArraySum(byteArray));
570 
571     initByteArray(byteArray);
572     $compile$noinline$UByteAndWrongConst(byteArray);
573     expectIntEquals(-2, ByteArraySum(byteArray));
574 
575     initByteArray(byteArray);
576     $compile$noinline$ByteNoHiBits(byteArray, byteArray);
577     expectIntEquals(-2, ByteArraySum(byteArray));
578 
579     // Conditions.
580     initIntArray(intArray);
581     $compile$noinline$SimpleCondition(intArray);
582     expectIntEquals(18864, IntArraySum(intArray));
583 
584     // Idioms.
585     initIntArray(intArray);
586     $compile$noinline$Select(intArray);
587     expectIntEquals(23121, IntArraySum(intArray));
588 
589     initIntArray(intArray);
590     $compile$noinline$Phi(intArray);
591     expectIntEquals(36748, IntArraySum(intArray));
592 
593     int reduction_result = 0;
594 
595     initIntArray(intArray);
596     reduction_result = $compile$noinline$Reduction(intArray);
597     expectIntEquals(14706, IntArraySum(intArray));
598     expectIntEquals(21012, reduction_result);
599 
600     initIntArray(intArray);
601     reduction_result = $compile$noinline$ReductionBackEdge(intArray);
602     expectIntEquals(23121, IntArraySum(intArray));
603     expectIntEquals(13121, reduction_result);
604 
605     int[] stencilArrayA = new int[STENCIL_ARRAY_SIZE];
606     int[] stencilArrayB = new int[STENCIL_ARRAY_SIZE];
607     initIntArray(stencilArrayA);
608     initIntArray(stencilArrayB);
609     $compile$noinline$stencilAlike(stencilArrayA, stencilArrayB);
610     expectIntEquals(43602, IntArraySum(stencilArrayA));
611 
612     initIntArray(intArray);
613     $compile$noinline$NotDiamondCf(intArray);
614     expectIntEquals(23121, IntArraySum(intArray));
615 
616     initIntArray(intArray);
617     $compile$noinline$BrokenInduction(intArray);
618     expectIntEquals(18963, IntArraySum(intArray));
619 
620     // Non-condition if statements.
621     initIntArray(intArray);
622     $compile$noinline$SingleBoolean(intArray, true);
623     expectIntEquals(27279, IntArraySum(intArray));
624 
625     initIntArray(intArray);
626     Main instance = new Main();
627     $compile$noinline$InstanceOf(intArray, instance);
628     expectIntEquals(27279, IntArraySum(intArray));
629 
630     System.out.println("passed");
631   }
632 
initBooleanArray(boolean[] a)633   public static void initBooleanArray(boolean[] a) {
634     for (int i = 0; i < ARRAY_LENGTH; i++) {
635       if (i % 3 != 0) {
636         a[i] = true;
637       }
638     }
639   }
640 
initByteArray(byte[] a)641   public static void initByteArray(byte[] a) {
642     for (int i = 0; i < ARRAY_LENGTH; i++) {
643       if (i % 3 == 0) {
644         a[i] = (byte)MAGIC_VALUE_A;
645       } else if (i % 3 == 1) {
646         a[i] = (byte)MAGIC_VALUE_B;
647       } else {
648         a[i] = (byte)MAGIC_VALUE_C;
649       }
650     }
651     a[USED_ARRAY_LENGTH] = 127;
652   }
653 
initShortArray(short[] a)654   public static void initShortArray(short[] a) {
655     for (int i = 0; i < ARRAY_LENGTH; i++) {
656       if (i % 3 == 0) {
657         a[i] = (short)MAGIC_VALUE_A;
658       } else if (i % 3 == 1) {
659         a[i] = (short)MAGIC_VALUE_B;
660       } else {
661         a[i] = (short)MAGIC_VALUE_C;
662       }
663     }
664     a[USED_ARRAY_LENGTH] = 10000;
665   }
666 
initCharArray(char[] a)667   public static void initCharArray(char[] a) {
668     for (int i = 0; i < ARRAY_LENGTH; i++) {
669       if (i % 3 == 0) {
670         a[i] = (char)MAGIC_VALUE_A;
671       } else if (i % 3 == 1) {
672         a[i] = (char)MAGIC_VALUE_B;
673       } else {
674         a[i] = (char)MAGIC_VALUE_C;
675       }
676     }
677     a[USED_ARRAY_LENGTH] = 10000;
678   }
679 
initIntArray(int[] a)680   public static void initIntArray(int[] a) {
681     for (int i = 0; i < ARRAY_LENGTH; i++) {
682       if (i % 3 == 0) {
683         a[i] = MAGIC_VALUE_A;
684       } else if (i % 3 == 1) {
685         a[i] = MAGIC_VALUE_B;
686       } else {
687         a[i] = MAGIC_VALUE_C;
688       }
689     }
690     a[USED_ARRAY_LENGTH] = 10000;
691   }
692 
initLongArray(long[] a)693   public static void initLongArray(long[] a) {
694     for (int i = 0; i < ARRAY_LENGTH; i++) {
695       if (i % 3 == 0) {
696         a[i] = MAGIC_VALUE_A;
697       } else if (i % 3 == 1) {
698         a[i] = MAGIC_VALUE_B;
699       } else {
700         a[i] = MAGIC_VALUE_C;
701       }
702     }
703     a[USED_ARRAY_LENGTH] = 10000;
704   }
705 
initFloatArray(float[] a)706   public static void initFloatArray(float[] a) {
707     for (int i = 0; i < ARRAY_LENGTH; i++) {
708       if (i % 3 == 0) {
709         a[i] = MAGIC_FLOAT_VALUE_A;
710       } else if (i % 3 == 1) {
711         a[i] = MAGIC_FLOAT_VALUE_B;
712       } else {
713         a[i] = MAGIC_FLOAT_VALUE_C;
714       }
715     }
716     a[USED_ARRAY_LENGTH] = 10000.0f;
717   }
718 
initDoubleArray(double[] a)719   public static void initDoubleArray(double[] a) {
720     for (int i = 0; i < ARRAY_LENGTH; i++) {
721       if (i % 3 == 0) {
722         a[i] = MAGIC_FLOAT_VALUE_A;
723       } else if (i % 3 == 1) {
724         a[i] = MAGIC_FLOAT_VALUE_B;
725       } else {
726         a[i] = MAGIC_FLOAT_VALUE_C;
727       }
728     }
729     a[USED_ARRAY_LENGTH] = 10000.0f;
730   }
731 
BooleanArraySum(boolean[] a)732   public static byte BooleanArraySum(boolean[] a) {
733     byte sum = 0;
734     for (int i = 0; i < a.length; i++) {
735       sum += a[i] ? 1 : 0;
736     }
737     return sum;
738   }
739 
ByteArraySum(byte[] a)740   public static byte ByteArraySum(byte[] a) {
741     byte sum = 0;
742     for (int i = 0; i < a.length; i++) {
743       sum += a[i];
744     }
745     return sum;
746   }
747 
ShortArraySum(short[] a)748   public static short ShortArraySum(short[] a) {
749     short sum = 0;
750     for (int i = 0; i < a.length; i++) {
751       sum += a[i];
752     }
753     return sum;
754   }
755 
CharArraySum(char[] a)756   public static char CharArraySum(char[] a) {
757     char sum = 0;
758     for (int i = 0; i < a.length; i++) {
759       sum += a[i];
760     }
761     return sum;
762   }
763 
IntArraySum(int[] a)764   public static int IntArraySum(int[] a) {
765     int sum = 0;
766     for (int i = 0; i < a.length; i++) {
767       sum += a[i];
768     }
769     return sum;
770   }
771 
LongArraySum(long[] a)772   public static long LongArraySum(long[] a) {
773     long sum = 0;
774     for (int i = 0; i < a.length; i++) {
775       sum += a[i];
776     }
777     return sum;
778   }
779 
FloatArraySum(float[] a)780   public static float FloatArraySum(float[] a) {
781     float sum = 0.0f;
782     for (int i = 0; i < a.length; i++) {
783       sum += a[i];
784     }
785     return sum;
786   }
787 
DoubleArraySum(double[] a)788   public static double DoubleArraySum(double[] a) {
789     double sum = 0.0;
790     for (int i = 0; i < a.length; i++) {
791       sum += a[i];
792     }
793     return sum;
794   }
795 
expectIntEquals(int expected, int result)796   private static void expectIntEquals(int expected, int result) {
797     if (expected != result) {
798       throw new Error("Expected: " + expected + ", found: " + result);
799     }
800   }
801 
expectLongEquals(long expected, long result)802   private static void expectLongEquals(long expected, long result) {
803     if (expected != result) {
804       throw new Error("Expected: " + expected + ", found: " + result);
805     }
806   }
807 
expectFloatEquals(float expected, float result)808   private static void expectFloatEquals(float expected, float result) {
809     final float THRESHOLD = .1f;
810     if (Math.abs(expected - result) >= THRESHOLD) {
811       throw new Error("Expected: " + expected + ", found: " + result);
812     }
813   }
814 
expectDoubleEquals(double expected, double result)815   private static void expectDoubleEquals(double expected, double result) {
816     final double THRESHOLD = .1;
817     if (Math.abs(expected - result) >= THRESHOLD) {
818       throw new Error("Expected: " + expected + ", found: " + result);
819     }
820   }
821 }
822