1 /*
2  * Copyright (C) 2016 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  * Regression tests for loop optimizations.
19  */
20 public class Main {
21 
ensureJitCompiled(Class<?> cls, String methodName)22   private static native void ensureJitCompiled(Class<?> cls, String methodName);
23 
24   /// CHECK-START: int Main.earlyExitFirst(int) loop_optimization (before)
25   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
26   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
27   //
28   /// CHECK-START: int Main.earlyExitFirst(int) loop_optimization (after)
29   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
30   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
earlyExitFirst(int m)31   static int earlyExitFirst(int m) {
32     int k = 0;
33     for (int i = 0; i < 10; i++) {
34       if (i == m) {
35         return k;
36       }
37       k++;
38     }
39     return k;
40   }
41 
42   /// CHECK-START: int Main.earlyExitLast(int) loop_optimization (before)
43   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
44   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
45   //
46   /// CHECK-START: int Main.earlyExitLast(int) loop_optimization (after)
47   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
48   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
earlyExitLast(int m)49   static int earlyExitLast(int m) {
50     int k = 0;
51     for (int i = 0; i < 10; i++) {
52       k++;
53       if (i == m) {
54         return k;
55       }
56     }
57     return k;
58   }
59 
60   /// CHECK-START: int Main.earlyExitNested() loop_optimization (before)
61   /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
62   /// CHECK-DAG: Phi loop:<<Loop1>>      outer_loop:none
63   /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
64   /// CHECK-DAG: Phi loop:<<Loop2>>      outer_loop:<<Loop1>>
65   //
66   /// CHECK-START: int Main.earlyExitNested() loop_optimization (after)
67   /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
68   /// CHECK-DAG: Phi loop:<<Loop1>>      outer_loop:none
69   //
70   /// CHECK-START: int Main.earlyExitNested() loop_optimization (after)
71   /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:{{B\d+}}
earlyExitNested()72   static int earlyExitNested() {
73     int offset = 0;
74     for (int i = 0; i < 2; i++) {
75       int start = offset;
76       // This loop can be removed.
77       for (int j = 0; j < 2; j++) {
78         offset++;
79       }
80       if (i == 1) {
81         return start;
82       }
83     }
84     return 0;
85   }
86 
87   // Regression test for b/33774618: transfer operations involving
88   // narrowing linear induction should be done correctly.
89   //
90   /// CHECK-START: int Main.transferNarrowWrap() loop_optimization (before)
91   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
92   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
93   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
94   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
95   //
96   /// CHECK-START: int Main.transferNarrowWrap() loop_optimization (after)
97   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
98   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
99   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
100   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
transferNarrowWrap()101   static int transferNarrowWrap() {
102     short x = 0;
103     int w = 10;
104     int v = 3;
105     for (int i = 0; i < 10; i++) {
106       v = w + 1;    // transfer on wrap-around
107       w = x;   // wrap-around
108       x += 2;  // narrowing linear
109     }
110     return v;
111   }
112 
113   // Regression test for b/33774618: transfer operations involving
114   // narrowing linear induction should be done correctly
115   // (currently rejected, could be improved).
116   //
117   /// CHECK-START: int Main.polynomialShort() loop_optimization (before)
118   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
119   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
120   //
121   /// CHECK-START: int Main.polynomialShort() loop_optimization (after)
122   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
123   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
polynomialShort()124   static int polynomialShort() {
125     int x = 0;
126     for (short i = 0; i < 10; i++) {
127       x = x - i;  // polynomial on narrowing linear
128     }
129     return x;
130   }
131 
132   // Regression test for b/33774618: transfer operations involving
133   // narrowing linear induction should be done correctly
134   // (currently rejected, could be improved).
135   //
136   /// CHECK-START: int Main.polynomialIntFromLong() loop_optimization (before)
137   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
138   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
139   //
140   /// CHECK-START: int Main.polynomialIntFromLong() loop_optimization (after)
141   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
142   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
polynomialIntFromLong()143   static int polynomialIntFromLong() {
144     int x = 0;
145     for (long i = 0; i < 10; i++) {
146       x = x - (int) i;  // polynomial on narrowing linear
147     }
148     return x;
149   }
150 
151   /// CHECK-START: int Main.polynomialInt() loop_optimization (before)
152   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
153   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
154   //
155   /// CHECK-START: int Main.polynomialInt() loop_optimization (after)
156   /// CHECK-NOT: Phi
157   //
158   /// CHECK-START: int Main.polynomialInt() instruction_simplifier$after_bce (after)
159   /// CHECK-DAG: <<Int:i\d+>>  IntConstant -45  loop:none
160   /// CHECK-DAG:               Return [<<Int>>] loop:none
polynomialInt()161   static int polynomialInt() {
162     int x = 0;
163     for (int i = 0; i < 10; i++) {
164       x = x - i;
165     }
166     return x;
167   }
168 
169   // Regression test for b/34779592 (found with fuzz testing): overflow for last value
170   // of division truncates to zero, for multiplication it simply truncates.
171   //
172   /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (before)
173   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
174   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
175   //
176   /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (after)
177   /// CHECK-NOT: Phi
178   //
179   /// CHECK-START: int Main.geoIntDivLastValue(int) instruction_simplifier$after_bce (after)
180   /// CHECK-DAG: <<Int:i\d+>> IntConstant 0    loop:none
181   /// CHECK-DAG:              Return [<<Int>>] loop:none
geoIntDivLastValue(int x)182   static int geoIntDivLastValue(int x) {
183     for (int i = 0; i < 2; i++) {
184       x /= 1081788608;
185     }
186     return x;
187   }
188 
189   /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (before)
190   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
191   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
192   //
193   /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (after)
194   /// CHECK-NOT: Phi
195   //
196   /// CHECK-START: int Main.geoIntMulLastValue(int) instruction_simplifier$after_bce (after)
197   /// CHECK-DAG: <<Par:i\d+>> ParameterValue         loop:none
198   /// CHECK-DAG: <<Int:i\d+>> IntConstant -194211840 loop:none
199   /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>]  loop:none
200   /// CHECK-DAG:              Return [<<Mul>>]       loop:none
geoIntMulLastValue(int x)201   static int geoIntMulLastValue(int x) {
202     for (int i = 0; i < 2; i++) {
203       x *= 1081788608;
204     }
205     return x;
206   }
207 
208   /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (before)
209   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
210   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
211   //
212   /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (after)
213   /// CHECK-NOT: Phi
214   //
215   /// CHECK-START: long Main.geoLongDivLastValue(long) instruction_simplifier$after_bce (after)
216   /// CHECK-DAG: <<Long:j\d+>> LongConstant 0    loop:none
217   /// CHECK-DAG:               Return [<<Long>>] loop:none
218   //
219   // Tests overflow in the divisor (while updating intermediate result).
geoLongDivLastValue(long x)220   static long geoLongDivLastValue(long x) {
221     for (int i = 0; i < 10; i++) {
222       x /= 1081788608;
223     }
224     return x;
225   }
226 
227   /// CHECK-START: long Main.geoLongDivLastValue() loop_optimization (before)
228   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
229   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
230   //
231   /// CHECK-START: long Main.geoLongDivLastValue() loop_optimization (after)
232   /// CHECK-NOT: Phi
233   //
234   /// CHECK-START: long Main.geoLongDivLastValue() instruction_simplifier$after_bce (after)
235   /// CHECK-DAG: <<Long:j\d+>> LongConstant 0    loop:none
236   /// CHECK-DAG:               Return [<<Long>>] loop:none
237   //
238   // Tests overflow in the divisor (while updating base).
geoLongDivLastValue()239   static long geoLongDivLastValue() {
240     long x = -1;
241     for (int i2 = 0; i2 < 2; i2++) {
242       x /= (Long.MAX_VALUE);
243     }
244     return x;
245   }
246 
247   /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (before)
248   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
249   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
250   //
251   /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (after)
252   /// CHECK-NOT: Phi
253   //
254   /// CHECK-START: long Main.geoLongMulLastValue(long) instruction_simplifier$after_bce (after)
255   /// CHECK-DAG: <<Par:j\d+>>  ParameterValue                    loop:none
256   /// CHECK-DAG: <<Long:j\d+>> LongConstant -8070450532247928832 loop:none
257   /// CHECK-DAG: <<Mul:j\d+>>  Mul [<<Par>>,<<Long>>]            loop:none
258   /// CHECK-DAG:               Return [<<Mul>>]                  loop:none
geoLongMulLastValue(long x)259   static long geoLongMulLastValue(long x) {
260     for (int i = 0; i < 10; i++) {
261       x *= 1081788608;
262     }
263     return x;
264   }
265 
266   // If vectorized, the narrowing subscript should not cause
267   // type inconsistencies in the synthesized code.
narrowingSubscript(float[] a)268   static void narrowingSubscript(float[] a) {
269     float val = 2.0f;
270     for (long i = 0; i < a.length; i++) {
271       a[(int) i] += val;
272     }
273   }
274 
275   // If vectorized, invariant stride should be recognized
276   // as a reduction, not a unit stride in outer loop.
reduc(int[] xx, int[] yy)277   static void reduc(int[] xx, int[] yy) {
278     for (int i0 = 0; i0 < 2; i0++) {
279       for (int i1 = 0; i1 < 469; i1++) {
280         xx[i0] -= (++yy[i1]);
281       }
282     }
283   }
284 
285   /// CHECK-START: void Main.string2Bytes(char[], java.lang.String) loop_optimization (before)
286   /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>> outer_loop:none
287   /// CHECK-DAG: ArraySet loop:<<Loop>>      outer_loop:none
288   //
289   /// CHECK-START-ARM: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after)
290   /// CHECK-NOT: VecLoad
291   //
292   /// CHECK-START-ARM64: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after)
293   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
294   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
295   //
296   // NOTE: should correctly deal with compressed and uncompressed cases.
string2Bytes(char[] a, String b)297   private static void string2Bytes(char[] a, String b) {
298     int min = Math.min(a.length, b.length());
299     for (int i = 0; i < min; i++) {
300       a[i] = b.charAt(i);
301     }
302   }
303 
304   /// CHECK-START-ARM: void Main.$noinline$stringToShorts(short[], java.lang.String) loop_optimization (after)
305   /// CHECK-NOT: VecLoad
306 
307   /// CHECK-START-ARM64: void Main.$noinline$stringToShorts(short[], java.lang.String) loop_optimization (after)
308   /// CHECK-DAG: VecLoad  loop:<<Loop:B\d+>> outer_loop:none
309   /// CHECK-DAG: VecStore loop:<<Loop>>      outer_loop:none
$noinline$stringToShorts(short[] dest, String src)310   private static void $noinline$stringToShorts(short[] dest, String src) {
311     int min = Math.min(dest.length, src.length());
312     for (int i = 0; i < min; ++i) {
313       dest[i] = (short) src.charAt(i);
314     }
315   }
316 
317   // A strange function that does not inline.
$noinline$foo(boolean x, int n)318   private static void $noinline$foo(boolean x, int n) {
319     if (n < 0)
320       throw new Error("oh no");
321     if (n > 100) {
322       $noinline$foo(!x, n - 1);
323       $noinline$foo(!x, n - 2);
324       $noinline$foo(!x, n - 3);
325       $noinline$foo(!x, n - 4);
326     }
327   }
328 
329   // A loop with environment uses of x (the terminating condition). As exposed by bug
330   // b/37247891, the loop can be unrolled, but should handle the (unlikely, but clearly
331   // not impossible) environment uses of the terminating condition in a correct manner.
envUsesInCond()332   private static void envUsesInCond() {
333     boolean x = false;
334     for (int i = 0; !(x = i >= 1); i++) {
335       $noinline$foo(true, i);
336     }
337   }
338 
339   /// CHECK-START: void Main.oneBoth(short[], char[]) loop_optimization (before)
340   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                       loop:none
341   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
342   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>>      outer_loop:none
343   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>>      outer_loop:none
344   //
345   /// CHECK-START-ARM: void Main.oneBoth(short[], char[]) loop_optimization (after)
346   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                             loop:none
347   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]              loop:none
348   /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none
349   /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>]      loop:<<Loop>>      outer_loop:none
350   //
351   /// CHECK-START-ARM64: void Main.oneBoth(short[], char[]) loop_optimization (after)
352   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                             loop:none
353   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]              loop:none
354   /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi:i\d+>>,<<Repl>>] loop:<<Loop:B\d+>> outer_loop:none
355   /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi>>,<<Repl>>]      loop:<<Loop>>      outer_loop:none
356   //
357   // Bug b/37764324: integral same-length packed types can be mixed freely.
oneBoth(short[] a, char[] b)358   private static void oneBoth(short[] a, char[] b) {
359     for (int i = 0; i < Math.min(a.length, b.length); i++) {
360       a[i] = 1;
361       b[i] = 1;
362     }
363   }
364 
365   // Bug b/37768917: potential dynamic BCE vs. loop optimizations
366   // case should be deal with correctly (used to DCHECK fail).
arrayInTripCount(int[] a, byte[] b, int n)367   private static void arrayInTripCount(int[] a, byte[] b, int n) {
368     for (int k = 0; k < n; k++) {
369       for (int i = 0, u = a[0]; i < u; i++) {
370         b[i] += 2;
371       }
372     }
373   }
374 
375   /// CHECK-START: void Main.typeConv(byte[], byte[]) loop_optimization (before)
376   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                       loop:none
377   /// CHECK-DAG: <<Phi:i\d+>>  Phi                                 loop:<<Loop:B\d+>> outer_loop:none
378   /// CHECK-DAG: <<Get:b\d+>>  ArrayGet [{{l\d+}},<<Phi>>]         loop:<<Loop>>      outer_loop:none
379   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<One>>]               loop:<<Loop>>      outer_loop:none
380   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Add>>]            loop:<<Loop>>      outer_loop:none
381   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>>      outer_loop:none
382   //
383   /// CHECK-START-ARM: void Main.typeConv(byte[], byte[]) loop_optimization (after)
384   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                         loop:none
385   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]          loop:none
386   /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>]      loop:<<Loop1:B\d+>> outer_loop:none
387   /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>]            loop:<<Loop1>>      outer_loop:none
388   /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>>      outer_loop:none
389   /// CHECK-DAG: <<Get:b\d+>>  ArrayGet [{{l\d+}},<<Phi2:i\d+>>]     loop:<<Loop2:B\d+>> outer_loop:none
390   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<One>>]                 loop:<<Loop2>>      outer_loop:none
391   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Add>>]              loop:<<Loop2>>      outer_loop:none
392   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>]  loop:<<Loop2>>      outer_loop:none
393   //
394   /// CHECK-START-ARM64: void Main.typeConv(byte[], byte[]) loop_optimization (after)
395   /// CHECK-DAG: <<One:i\d+>>  IntConstant 1                         loop:none
396   /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>]          loop:none
397   /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1:i\d+>>]      loop:<<Loop1:B\d+>> outer_loop:none
398   /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>]            loop:<<Loop1>>      outer_loop:none
399   /// CHECK-DAG:               VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>>      outer_loop:none
400   /// CHECK-DAG: <<Get:b\d+>>  ArrayGet [{{l\d+}},<<Phi2:i\d+>>]     loop:<<Loop2:B\d+>> outer_loop:none
401   /// CHECK-DAG: <<Add:i\d+>>  Add [<<Get>>,<<One>>]                 loop:<<Loop2>>      outer_loop:none
402   /// CHECK-DAG: <<Cnv:b\d+>>  TypeConversion [<<Add>>]              loop:<<Loop2>>      outer_loop:none
403   /// CHECK-DAG:               ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>]  loop:<<Loop2>>      outer_loop:none
404   //
405   // Scalar code in cleanup loop uses correct byte type on array get and type conversion.
typeConv(byte[] a, byte[] b)406   private static void typeConv(byte[] a, byte[] b) {
407     int len = Math.min(a.length, b.length);
408     for (int i = 0; i < len; i++) {
409       a[i] = (byte) (b[i] + 1);
410     }
411   }
412 
413   // Environment of an instruction, removed during SimplifyInduction, should be adjusted.
414   //
415   /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (before)
416   /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
417   /// CHECK-DAG: Phi loop:<<Loop>>      outer_loop:none
418   //
419   /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (after)
420   /// CHECK-NOT: Phi
inductionMax(int[] a)421   private static void inductionMax(int[] a) {
422    int s = 0;
423     for (int i = 0; i < 10; i++) {
424       s = Math.max(s, 5);
425     }
426   }
427 
428   /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (before)
429   /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
430   /// CHECK-DAG: Phi loop:<<Loop1>>      outer_loop:none
431   /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none
432   //
433   /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
434   //
435   /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (after)
436   /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none
437   /// CHECK-NOT: Phi
feedsIntoDeopt(int[] a)438   static int feedsIntoDeopt(int[] a) {
439     // Reduction should be removed.
440     int r = 0;
441     for (int i = 0; i < 100; i++) {
442       r += 10;
443     }
444     // Even though uses feed into deopts of BCE.
445     for (int i = 1; i < 100; i++) {
446       a[i] = a[i - 1];
447     }
448     return r;
449   }
450 
absCanBeNegative(int x)451   static int absCanBeNegative(int x) {
452     int a[] = { 1, 2, 3 };
453     int y = 0;
454     for (int i = Math.abs(x); i < a.length; i++) {
455       y += a[i];
456     }
457     return y;
458   }
459 
460   // b/65478356: sum up 2-dim array.
sum(int[][] a)461   static int sum(int[][] a) {
462     int sum = 0;
463     for (int y = 0; y < a.length; y++) {
464       int[] aa = a[y];
465       for (int x = 0; x < aa.length; x++) {
466         sum += aa[x];
467       }
468     }
469     return sum;
470   }
471 
472   // Large loop body should not break unrolling computation.
largeBody(int[] x)473   static void largeBody(int[] x) {
474     for (int i = 0; i < 100; i++) {
475       x[i] = x[i] * 1 + x[i] * 2 + x[i] * 3 + x[i] * 4 + x[i] * 5 + x[i] * 6 +
476           x[i] * 7 + x[i] * 8 + x[i] * 9 + x[i] * 10 + x[i] * 11 + x[i] * 12 +
477           x[i] * 13 + x[i] * 14 + x[i] * 15 + x[i] * 1 + x[i] * 2 + x[i] * 3 + x[i] * 4 +
478           x[i] * 5 + x[i] * 6 + x[i] * 7 + x[i] * 8 + x[i] * 9 + x[i] * 10 + x[i] * 11 +
479           x[i] * 12 + x[i] * 13 + x[i] * 14 + x[i] * 15 + x[i] * 1 + x[i] * 2 + x[i] * 3 +
480           x[i] * 4 + x[i] * 5;
481     }
482   }
483 
484   // Mixed of 16-bit and 8-bit array references.
castAndNarrow(byte[] x, char[] y)485   static void castAndNarrow(byte[] x, char[] y) {
486     for (int i = 0; i < x.length; i++) {
487       x[i] = (byte) ((short) y[i] +  1);
488     }
489   }
490 
491   // Avoid bad scheduler-SIMD interaction.
doNotMoveSIMD()492   static int doNotMoveSIMD() {
493     int sum = 0;
494     for (int j = 0; j <= 8; j++) {
495       int[] a = new int[17];    // a[i] = 0;
496                                 // ConstructorFence ?
497       for (int i = 0; i < a.length; i++) {
498         a[i] += 1;              // a[i] = 1;
499       }
500       for (int i = 0; i < a.length; i++) {
501         sum += a[i];            // expect a[i] = 1;
502       }
503     }
504     return sum;
505   }
506 
507   // Ensure spilling saves full SIMD values.
reduction32Values(int[] a, int[] b, int[] c, int[] d)508   private static final int reduction32Values(int[] a, int[] b, int[] c, int[] d) {
509     int s0 = 0;
510     int s1 = 0;
511     int s2 = 0;
512     int s3 = 0;
513     int s4 = 0;
514     int s5 = 0;
515     int s6 = 0;
516     int s7 = 0;
517     int s8 = 0;
518     int s9 = 0;
519     int s10 = 0;
520     int s11 = 0;
521     int s12 = 0;
522     int s13 = 0;
523     int s14 = 0;
524     int s15 = 0;
525     int s16 = 0;
526     int s17 = 0;
527     int s18 = 0;
528     int s19 = 0;
529     int s20 = 0;
530     int s21 = 0;
531     int s22 = 0;
532     int s23 = 0;
533     int s24 = 0;
534     int s25 = 0;
535     int s26 = 0;
536     int s27 = 0;
537     int s28 = 0;
538     int s29 = 0;
539     int s30 = 0;
540     int s31 = 0;
541     for (int i = 1; i < 100; i++) {
542       s0 += a[i];
543       s1 += b[i];
544       s2 += c[i];
545       s3 += d[i];
546       s4 += a[i];
547       s5 += b[i];
548       s6 += c[i];
549       s7 += d[i];
550       s8 += a[i];
551       s9 += b[i];
552       s10 += c[i];
553       s11 += d[i];
554       s12 += a[i];
555       s13 += b[i];
556       s14 += c[i];
557       s15 += d[i];
558       s16 += a[i];
559       s17 += b[i];
560       s18 += c[i];
561       s19 += d[i];
562       s20 += a[i];
563       s21 += b[i];
564       s22 += c[i];
565       s23 += d[i];
566       s24 += a[i];
567       s25 += b[i];
568       s26 += c[i];
569       s27 += d[i];
570       s28 += a[i];
571       s29 += b[i];
572       s30 += c[i];
573       s31 += d[i];
574     }
575     return s0 + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10 + s11 + s12 + s13 + s14 + s15 +
576            s16 + s17 + s18 + s19 + s20 + s21 + s22 + s23 +
577            s24 + s25 + s26 + s27 + s28 + s29 + s30 + s31;
578   }
579 
580   // Ensure spilling saves regular FP values correctly when the graph HasSIMD()
581   // is true.
582   /// CHECK-START-ARM64: float Main.$noinline$ensureSlowPathFPSpillFill(float[], float[], float[], float[], int[]) loop_optimization (after)
583   //
584   //  Both regular and SIMD accesses are present.
585   /// CHECK-DAG: VecLoad
586   /// CHECK-DAG: ArrayGet
$noinline$ensureSlowPathFPSpillFill(float[] a, float[] b, float[] c, float[] d, int[] e)587   private static final float $noinline$ensureSlowPathFPSpillFill(float[] a,
588                                                                  float[] b,
589                                                                  float[] c,
590                                                                  float[] d,
591                                                                  int[] e) {
592     // This loop should be vectorized so the graph->HasSIMD() will be true.
593     // A power-of-2 number of iterations is chosen to avoid peeling/unrolling interference.
594     for (int i = 0; i < 64; i++) {
595       // The actual values of the array elements don't matter, just the
596       // presence of a SIMD loop.
597       e[i]++;
598     }
599 
600     float f0 = 0;
601     float f1 = 0;
602     float f2 = 0;
603     float f3 = 0;
604     float f4 = 0;
605     float f5 = 0;
606     float f6 = 0;
607     float f7 = 0;
608     float f8 = 0;
609     float f9 = 0;
610     float f10 = 0;
611     float f11 = 0;
612     float f12 = 0;
613     float f13 = 0;
614     float f14 = 0;
615     float f15 = 0;
616     float f16 = 0;
617     float f17 = 0;
618     float f18 = 0;
619     float f19 = 0;
620     float f20 = 0;
621     float f21 = 0;
622     float f22 = 0;
623     float f23 = 0;
624     float f24 = 0;
625     float f25 = 0;
626     float f26 = 0;
627     float f27 = 0;
628     float f28 = 0;
629     float f29 = 0;
630     float f30 = 0;
631     float f31 = 0;
632     for (int i = 0; i < 100; i++) {
633       f0 += a[i];
634       f1 += b[i];
635       f2 += c[i];
636       f3 += d[i];
637       f4 += a[i];
638       f5 += b[i];
639       f6 += c[i];
640       f7 += d[i];
641       f8 += a[i];
642       f9 += b[i];
643       f10 += c[i];
644       f11 += d[i];
645       f12 += a[i];
646       f13 += b[i];
647       f14 += c[i];
648       f15 += d[i];
649       f16 += a[i];
650       f17 += b[i];
651       f18 += c[i];
652       f19 += d[i];
653       f20 += a[i];
654       f21 += b[i];
655       f22 += c[i];
656       f23 += d[i];
657       f24 += a[i];
658       f25 += b[i];
659       f26 += c[i];
660       f27 += d[i];
661       f28 += a[i];
662       f29 += b[i];
663       f30 += c[i];
664       f31 += d[i];
665     }
666     return f0 + f1 + f2 + f3 + f4 + f5 + f6 + f7 + f8 + f9 + f10 + f11 + f12 + f13 + f14 + f15 +
667            f16 + f17 + f18 + f19 + f20 + f21 + f22 + f23 +
668            f24 + f25 + f26 + f27 + f28 + f29 + f30 + f31;
669   }
670 
reductionIntoReplication()671   public static int reductionIntoReplication() {
672     int[] a = { 1, 2, 3, 4 };
673     int x = 0;
674     for (int i = 0; i < 4; i++) {
675       x += a[i];
676     }
677     for (int i = 0; i < 4; i++) {
678       a[i] = x;
679     }
680     return a[3];
681   }
682 
683   // Dot product and SAD vectorization idioms used to have a bug when some
684   // instruction in the loop was visited twice causing a compiler crash.
685   // It happened when two vectorization idioms' matched patterns had a common
686   // sub-expression.
687 
688   // Idioms common sub-expression bug: DotProduct and ArraySet.
689   //
690   /// CHECK-START-ARM64: int Main.testDotProdAndSet(byte[], byte[], byte[]) loop_optimization (after)
691   /// CHECK-DAG:       VecDotProd
692   /// CHECK-DAG:       VecStore
testDotProdAndSet(byte[] a, byte[] b, byte[] c)693   public static final int testDotProdAndSet(byte[] a, byte[] b, byte[] c) {
694     int s = 1;
695     for (int i = 0; i < b.length; i++) {
696       int temp = a[i] * b[i];
697       c[i]= (byte)temp;
698       s += temp;
699     }
700     return s - 1;
701   }
702 
703   // Idioms common sub-expression bug: DotProduct and DotProduct.
704   //
705   /// CHECK-START-ARM64: int Main.testDotProdAndDotProd(byte[], byte[]) loop_optimization (after)
706   /// CHECK-DAG:       VecDotProd
707   /// CHECK-DAG:       VecDotProd
testDotProdAndDotProd(byte[] a, byte[] b)708   public static final int testDotProdAndDotProd(byte[] a, byte[] b) {
709     int s0 = 1;
710     int s1 = 1;
711     for (int i = 0; i < b.length; i++) {
712       int temp = a[i] * b[i];
713       s0 += temp;
714       s1 += temp;
715     }
716     return s0 + s1;
717   }
718 
719   // Idioms common sub-expression bug: SAD and ArraySet.
720   //
721   /// CHECK-START-{ARM,ARM64}: int Main.testSADAndSet(int[], int[], int[]) loop_optimization (after)
722   /// CHECK-DAG:       VecSADAccumulate
723   /// CHECK-DAG:       VecStore
testSADAndSet(int[] x, int[] y, int[] z)724   public static int testSADAndSet(int[] x, int[] y, int[] z) {
725     int min_length = Math.min(x.length, y.length);
726     int sad = 0;
727     for (int i = 0; i < min_length; i++) {
728       int temp = Math.abs(x[i] - y[i]);
729       z[i] = temp;
730       sad += temp;
731     }
732     return sad;
733   }
734 
735   // Idioms common sub-expression bug: SAD and SAD.
736   /// CHECK-START-{ARM,ARM64}: int Main.testSADAndSAD(int[], int[]) loop_optimization (after)
737   /// CHECK-DAG:       VecSADAccumulate
738   /// CHECK-DAG:       VecSADAccumulate
testSADAndSAD(int[] x, int[] y)739   public static final int testSADAndSAD(int[] x, int[] y) {
740     int s0 = 1;
741     int s1 = 1;
742     for (int i = 0; i < x.length; i++) {
743       int temp = Math.abs(x[i] - y[i]);
744       s0 += temp;
745       s1 += temp;
746     }
747     return s0 + s1;
748   }
749 
750   // Idioms common sub-expression bug: DotProd and DotProd with extra mul.
751   //
752   /// CHECK-START-ARM64: int Main.testDotProdAndDotProdExtraMul0(byte[], byte[]) loop_optimization (after)
753   /// CHECK-DAG:       VecMul
754   /// CHECK-DAG:       VecDotProd
755   /// CHECK-DAG:       VecDotProd
testDotProdAndDotProdExtraMul0(byte[] a, byte[] b)756   public static final int testDotProdAndDotProdExtraMul0(byte[] a, byte[] b) {
757     int s0 = 1;
758     int s1 = 1;
759     for (int i = 0; i < b.length; i++) {
760       int temp0 = a[i] * b[i];
761       int temp1 = (byte)(temp0) * a[i];
762       s0 += temp1;
763       s1 += temp0;
764     }
765     return s0 + s1;
766   }
767 
768   // Idioms common sub-expression bug: DotProd and DotProd with extra mul (reversed order).
769   //
770   /// CHECK-START-ARM64: int Main.testDotProdAndDotProdExtraMul1(byte[], byte[]) loop_optimization (after)
771   /// CHECK-DAG:       VecMul
772   /// CHECK-DAG:       VecDotProd
773   /// CHECK-DAG:       VecDotProd
testDotProdAndDotProdExtraMul1(byte[] a, byte[] b)774   public static final int testDotProdAndDotProdExtraMul1(byte[] a, byte[] b) {
775     int s0 = 1;
776     int s1 = 1;
777     for (int i = 0; i < b.length; i++) {
778       int temp0 = a[i] * b[i];
779       int temp1 = (byte)(temp0) * a[i];
780       s0 += temp0;
781       s1 += temp1;
782     }
783     return s0 + s1;
784   }
785 
786   // Idioms common sub-expression bug: SAD and SAD with extra abs.
787   //
788   /// CHECK-START-{ARM,ARM64}: int Main.testSADAndSADExtraAbs0(int[], int[]) loop_optimization (after)
789   /// CHECK-DAG:       VecSub
790   /// CHECK-DAG:       VecAbs
791   /// CHECK-DAG:       VecSADAccumulate
792   /// CHECK-DAG:       VecSADAccumulate
testSADAndSADExtraAbs0(int[] x, int[] y)793   public static final int testSADAndSADExtraAbs0(int[] x, int[] y) {
794     int s0 = 1;
795     int s1 = 1;
796     for (int i = 0; i < x.length; i++) {
797       int temp0 = Math.abs(x[i] - y[i]);
798       int temp1 = Math.abs(temp0 - y[i]);
799       s0 += temp1;
800       s1 += temp0;
801     }
802     return s0 + s1;
803   }
804 
805   // Idioms common sub-expression bug: SAD and SAD with extra abs (reversed order).
806   //
807   /// CHECK-START-{ARM,ARM64}: int Main.testSADAndSADExtraAbs1(int[], int[]) loop_optimization (after)
808   /// CHECK-DAG:       VecSub
809   /// CHECK-DAG:       VecAbs
810   /// CHECK-DAG:       VecSADAccumulate
811   /// CHECK-DAG:       VecSADAccumulate
testSADAndSADExtraAbs1(int[] x, int[] y)812   public static final int testSADAndSADExtraAbs1(int[] x, int[] y) {
813     int s0 = 1;
814     int s1 = 1;
815     for (int i = 0; i < x.length; i++) {
816       int temp0 = Math.abs(x[i] - y[i]);
817       int temp1 = Math.abs(temp0 - y[i]);
818       s0 += temp0;
819       s1 += temp1;
820     }
821     return s0 + s1;
822   }
823 
824 
825   // Idioms common sub-expression bug: SAD and DotProd combined.
826   //
827   /// CHECK-START-ARM64: int Main.testSADAndDotProdCombined0(byte[], byte[]) loop_optimization (after)
828   /// CHECK-DAG:       VecSub
829   /// CHECK-DAG:       VecSADAccumulate
830   /// CHECK-DAG:       VecDotProd
testSADAndDotProdCombined0(byte[] x, byte[] y)831   public static final int testSADAndDotProdCombined0(byte[] x, byte[] y) {
832     int s0 = 1;
833     int s1 = 1;
834     for (int i = 0; i < x.length; i++) {
835       int temp0 = x[i] - y[i];
836       int temp1 = Math.abs(temp0);
837       int temp2 = x[i] * (byte)(temp0);
838 
839       s0 += temp1;
840       s1 += temp2;
841     }
842     return s0 + s1;
843   }
844 
845   // Idioms common sub-expression bug: SAD and DotProd combined (reversed order).
846   /// CHECK-START-ARM64: int Main.testSADAndDotProdCombined1(byte[], byte[]) loop_optimization (after)
847   /// CHECK-DAG:       VecSub
848   /// CHECK-DAG:       VecSADAccumulate
849   /// CHECK-DAG:       VecDotProd
testSADAndDotProdCombined1(byte[] x, byte[] y)850   public static final int testSADAndDotProdCombined1(byte[] x, byte[] y) {
851     int s0 = 1;
852     int s1 = 1;
853     for (int i = 0; i < x.length; i++) {
854       int temp0 = x[i] - y[i];
855       int temp1 = Math.abs(temp0);
856       int temp2 = x[i] * (byte)(temp0);
857 
858       s0 += temp2;
859       s1 += temp1;
860     }
861     return s0 + s1;
862   }
863 
864   public static final int ARRAY_SIZE = 512;
865 
createAndInitByteArray(int x)866   private static byte[] createAndInitByteArray(int x) {
867     byte[] a = new byte[ARRAY_SIZE];
868     for (int i = 0; i < a.length; i++) {
869       a[i] = (byte)((~i) + x);
870     }
871     return a;
872   }
873 
createAndInitIntArray(int x)874   private static int[] createAndInitIntArray(int x) {
875     int[] a = new int[ARRAY_SIZE];
876     for (int i = 0; i < a.length; i++) {
877       a[i] = (~i) + x;
878     }
879     return a;
880   }
881 
main(String[] args)882   public static void main(String[] args) {
883     System.loadLibrary(args[0]);
884 
885     expectEquals(10, earlyExitFirst(-1));
886     for (int i = 0; i <= 10; i++) {
887       expectEquals(i, earlyExitFirst(i));
888     }
889     expectEquals(10, earlyExitFirst(11));
890 
891     expectEquals(10, earlyExitLast(-1));
892     for (int i = 0; i < 10; i++) {
893       expectEquals(i + 1, earlyExitLast(i));
894     }
895     expectEquals(10, earlyExitLast(10));
896     expectEquals(10, earlyExitLast(11));
897 
898     expectEquals(2, earlyExitNested());
899 
900     expectEquals(17, transferNarrowWrap());
901     expectEquals(-45, polynomialShort());
902     expectEquals(-45, polynomialIntFromLong());
903     expectEquals(-45, polynomialInt());
904 
905     expectEquals(0, geoIntDivLastValue(0));
906     expectEquals(0, geoIntDivLastValue(1));
907     expectEquals(0, geoIntDivLastValue(2));
908     expectEquals(0, geoIntDivLastValue(1081788608));
909     expectEquals(0, geoIntDivLastValue(-1081788608));
910     expectEquals(0, geoIntDivLastValue(2147483647));
911     expectEquals(0, geoIntDivLastValue(-2147483648));
912 
913     expectEquals(          0, geoIntMulLastValue(0));
914     expectEquals( -194211840, geoIntMulLastValue(1));
915     expectEquals( -388423680, geoIntMulLastValue(2));
916     expectEquals(-1041498112, geoIntMulLastValue(1081788608));
917     expectEquals( 1041498112, geoIntMulLastValue(-1081788608));
918     expectEquals(  194211840, geoIntMulLastValue(2147483647));
919     expectEquals(          0, geoIntMulLastValue(-2147483648));
920 
921     expectEquals(0L, geoLongDivLastValue(0L));
922     expectEquals(0L, geoLongDivLastValue(1L));
923     expectEquals(0L, geoLongDivLastValue(2L));
924     expectEquals(0L, geoLongDivLastValue(1081788608L));
925     expectEquals(0L, geoLongDivLastValue(-1081788608L));
926     expectEquals(0L, geoLongDivLastValue(2147483647L));
927     expectEquals(0L, geoLongDivLastValue(-2147483648L));
928     expectEquals(0L, geoLongDivLastValue(9223372036854775807L));
929     expectEquals(0L, geoLongDivLastValue(-9223372036854775808L));
930 
931     expectEquals(0L, geoLongDivLastValue());
932 
933     expectEquals(                   0L, geoLongMulLastValue(0L));
934     expectEquals(-8070450532247928832L, geoLongMulLastValue(1L));
935     expectEquals( 2305843009213693952L, geoLongMulLastValue(2L));
936     expectEquals(                   0L, geoLongMulLastValue(1081788608L));
937     expectEquals(                   0L, geoLongMulLastValue(-1081788608L));
938     expectEquals( 8070450532247928832L, geoLongMulLastValue(2147483647L));
939     expectEquals(                   0L, geoLongMulLastValue(-2147483648L));
940     expectEquals( 8070450532247928832L, geoLongMulLastValue(9223372036854775807L));
941     expectEquals(                   0L, geoLongMulLastValue(-9223372036854775808L));
942 
943     float[] a = new float[16];
944     narrowingSubscript(a);
945     for (int i = 0; i < 16; i++) {
946       expectEquals(2.0f, a[i]);
947     }
948 
949     int[] xx = new int[2];
950     int[] yy = new int[469];
951     reduc(xx, yy);
952     expectEquals(-469, xx[0]);
953     expectEquals(-938, xx[1]);
954     for (int i = 0; i < 469; i++) {
955       expectEquals(2, yy[i]);
956     }
957 
958     char[] aa = new char[23];
959     String bb = "hello world how are you";
960     string2Bytes(aa, bb);
961     for (int i = 0; i < aa.length; i++) {
962       expectEquals(aa[i], bb.charAt(i));
963     }
964     String cc = "\u1010\u2020llo world how are y\u3030\u4040";
965     string2Bytes(aa, cc);
966     for (int i = 0; i < aa.length; i++) {
967       expectEquals(aa[i], cc.charAt(i));
968     }
969 
970     short[] s2s = new short[12];
971     $noinline$stringToShorts(s2s, "abcdefghijkl");
972     for (int i = 0; i < s2s.length; ++i) {
973       expectEquals((short) "abcdefghijkl".charAt(i), s2s[i]);
974     }
975 
976     envUsesInCond();
977 
978     short[] dd = new short[23];
979     oneBoth(dd, aa);
980     for (int i = 0; i < aa.length; i++) {
981       expectEquals(aa[i], 1);
982       expectEquals(dd[i], 1);
983     }
984 
985     xx[0] = 10;
986     byte[] bt = new byte[10];
987     arrayInTripCount(xx, bt, 20);
988     for (int i = 0; i < bt.length; i++) {
989       expectEquals(40, bt[i]);
990     }
991 
992     byte[] b1 = new byte[259];  // few extra iterations
993     byte[] b2 = new byte[259];
994     for (int i = 0; i < 259; i++) {
995       b1[i] = 0;
996       b2[i] = (byte) i;
997     }
998     typeConv(b1, b2);
999     for (int i = 0; i < 259; i++) {
1000       expectEquals((byte)(i + 1), b1[i]);
1001     }
1002 
1003     inductionMax(yy);
1004 
1005     int[] f = new int[100];
1006     f[0] = 11;
1007     expectEquals(1000, feedsIntoDeopt(f));
1008     for (int i = 0; i < 100; i++) {
1009       expectEquals(11, f[i]);
1010     }
1011 
1012     expectEquals(0, absCanBeNegative(-3));
1013     expectEquals(3, absCanBeNegative(-2));
1014     expectEquals(5, absCanBeNegative(-1));
1015     expectEquals(6, absCanBeNegative(0));
1016     expectEquals(5, absCanBeNegative(1));
1017     expectEquals(3, absCanBeNegative(2));
1018     expectEquals(0, absCanBeNegative(3));
1019     expectEquals(0, absCanBeNegative(Integer.MAX_VALUE));
1020     // Abs(min_int) = min_int.
1021     int verify = 0;
1022     try {
1023       absCanBeNegative(Integer.MIN_VALUE);
1024       verify = 1;
1025     } catch (ArrayIndexOutOfBoundsException e) {
1026       verify = 2;
1027     }
1028     expectEquals(2, verify);
1029 
1030     int[][] x = new int[128][128];
1031     for (int i = 0; i < 128; i++) {
1032       for (int j = 0; j < 128; j++) {
1033         x[i][j] = -i - j;
1034       }
1035     }
1036     expectEquals(-2080768, sum(x));
1037 
1038     largeBody(f);
1039     for (int i = 0; i < 100; i++) {
1040       expectEquals(2805, f[i]);
1041     }
1042 
1043     char[] cx = new char[259];
1044     for (int i = 0; i < 259; i++) {
1045       cx[i] = (char) (i - 100);
1046     }
1047     castAndNarrow(b1, cx);
1048     for (int i = 0; i < 259; i++) {
1049       expectEquals((byte)((short) cx[i] + 1), b1[i]);
1050     }
1051 
1052     expectEquals(153, doNotMoveSIMD());
1053 
1054     // This test exposed SIMDization issues on x86 and x86_64
1055     // so we make sure the test runs with JIT enabled.
1056     ensureJitCompiled(Main.class, "reduction32Values");
1057     {
1058       int[] a1 = new int[100];
1059       int[] a2 = new int[100];
1060       int[] a3 = new int[100];
1061       int[] a4 = new int[100];
1062       for (int i = 0; i < 100; i++) {
1063         a1[i] = i;
1064         a2[i] = 1;
1065         a3[i] = 100 - i;
1066         a4[i] = i % 16;
1067       }
1068       expectEquals(85800, reduction32Values(a1, a2, a3, a4));
1069     }
1070     {
1071       float[] a1 = new float[100];
1072       float[] a2 = new float[100];
1073       float[] a3 = new float[100];
1074       float[] a4 = new float[100];
1075       int[] a5 = new int[100];
1076 
1077       for (int i = 0; i < 100; i++) {
1078         a1[i] = (float)i;
1079         a2[i] = (float)1;
1080         a3[i] = (float)(100 - i);
1081         a4[i] = (i % 16);
1082       }
1083       expectEquals(86608.0f, $noinline$ensureSlowPathFPSpillFill(a1, a2, a3, a4, a5));
1084     }
1085 
1086     expectEquals(10, reductionIntoReplication());
1087 
1088     {
1089         byte[] b_a = createAndInitByteArray(1);
1090         byte[] b_b = createAndInitByteArray(2);
1091         byte[] b_c = createAndInitByteArray(3);
1092         expectEquals(2731008, testDotProdAndSet(b_a, b_b, b_c));
1093     }
1094     {
1095         byte[] b_a = createAndInitByteArray(1);
1096         byte[] b_b = createAndInitByteArray(2);
1097         expectEquals(5462018, testDotProdAndDotProd(b_a, b_b));
1098     }
1099     {
1100         int[] i_a = createAndInitIntArray(1);
1101         int[] i_b = createAndInitIntArray(2);
1102         int[] i_c = createAndInitIntArray(3);
1103         expectEquals(512, testSADAndSet(i_a, i_b, i_c));
1104     }
1105     {
1106         int[] i_a = createAndInitIntArray(1);
1107         int[] i_b = createAndInitIntArray(2);
1108         expectEquals(1026, testSADAndSAD(i_a, i_b));
1109     }
1110     {
1111         byte[] b_a = createAndInitByteArray(1);
1112         byte[] b_b = createAndInitByteArray(2);
1113         expectEquals(2731266, testDotProdAndDotProdExtraMul0(b_a, b_b));
1114     }
1115     {
1116         byte[] b_a = createAndInitByteArray(1);
1117         byte[] b_b = createAndInitByteArray(2);
1118         expectEquals(2731266, testDotProdAndDotProdExtraMul1(b_a, b_b));
1119     }
1120     {
1121         int[] i_a = createAndInitIntArray(1);
1122         int[] i_b = createAndInitIntArray(2);
1123         expectEquals(131330, testSADAndSADExtraAbs0(i_a, i_b));
1124     }
1125     {
1126         int[] i_a = createAndInitIntArray(1);
1127         int[] i_b = createAndInitIntArray(2);
1128         expectEquals(131330, testSADAndSADExtraAbs1(i_a, i_b));
1129     }
1130     {
1131         byte[] b_a = createAndInitByteArray(1);
1132         byte[] b_b = createAndInitByteArray(2);
1133         expectEquals(1278, testSADAndDotProdCombined0(b_a, b_b));
1134     }
1135     {
1136         byte[] b_a = createAndInitByteArray(1);
1137         byte[] b_b = createAndInitByteArray(2);
1138         expectEquals(1278, testSADAndDotProdCombined1(b_a, b_b));
1139     }
1140 
1141     System.out.println("passed");
1142   }
1143 
expectEquals(int expected, int result)1144   private static void expectEquals(int expected, int result) {
1145     if (expected != result) {
1146       throw new Error("Expected: " + expected + ", found: " + result);
1147     }
1148   }
1149 
expectEquals(long expected, long result)1150   private static void expectEquals(long expected, long result) {
1151     if (expected != result) {
1152       throw new Error("Expected: " + expected + ", found: " + result);
1153     }
1154   }
1155 
expectEquals(float expected, float result)1156   private static void expectEquals(float expected, float result) {
1157     if (expected != result) {
1158       throw new Error("Expected: " + expected + ", found: " + result);
1159     }
1160   }
1161 }
1162