blob: 0e8561299c17eb47f4d869d4c1664a3b45557b70 [file] [log] [blame]
Aart Bik807868e2016-11-03 17:51:43 -07001/*
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 */
20public class Main {
21
22 /// CHECK-START: int Main.earlyExitFirst(int) loop_optimization (before)
23 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
24 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
25 //
26 /// CHECK-START: int Main.earlyExitFirst(int) loop_optimization (after)
27 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
28 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
29 static int earlyExitFirst(int m) {
30 int k = 0;
31 for (int i = 0; i < 10; i++) {
32 if (i == m) {
33 return k;
34 }
35 k++;
36 }
37 return k;
38 }
39
40 /// CHECK-START: int Main.earlyExitLast(int) loop_optimization (before)
41 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
42 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
43 //
44 /// CHECK-START: int Main.earlyExitLast(int) loop_optimization (after)
45 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
46 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
47 static int earlyExitLast(int m) {
48 int k = 0;
49 for (int i = 0; i < 10; i++) {
50 k++;
51 if (i == m) {
52 return k;
53 }
54 }
55 return k;
56 }
57
58 /// CHECK-START: int Main.earlyExitNested() loop_optimization (before)
59 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
60 /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none
61 /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:<<Loop1>>
62 /// CHECK-DAG: Phi loop:<<Loop2>> outer_loop:<<Loop1>>
63 //
64 /// CHECK-START: int Main.earlyExitNested() loop_optimization (after)
65 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
66 /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none
67 //
68 /// CHECK-START: int Main.earlyExitNested() loop_optimization (after)
69 /// CHECK-NOT: Phi loop:{{B\d+}} outer_loop:{{B\d+}}
70 static int earlyExitNested() {
71 int offset = 0;
72 for (int i = 0; i < 2; i++) {
73 int start = offset;
74 // This loop can be removed.
75 for (int j = 0; j < 2; j++) {
76 offset++;
77 }
78 if (i == 1) {
79 return start;
80 }
81 }
82 return 0;
83 }
84
Aart Bik74da5292016-12-20 11:13:03 -080085 // Regression test for b/33774618: transfer operations involving
86 // narrowing linear induction should be done correctly.
87 //
88 /// CHECK-START: int Main.transferNarrowWrap() loop_optimization (before)
89 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
90 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
91 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
92 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
93 //
94 /// CHECK-START: int Main.transferNarrowWrap() loop_optimization (after)
95 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
96 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
97 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
98 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
99 static int transferNarrowWrap() {
100 short x = 0;
101 int w = 10;
102 int v = 3;
103 for (int i = 0; i < 10; i++) {
104 v = w + 1; // transfer on wrap-around
105 w = x; // wrap-around
106 x += 2; // narrowing linear
107 }
108 return v;
109 }
110
111 // Regression test for b/33774618: transfer operations involving
112 // narrowing linear induction should be done correctly
113 // (currently rejected, could be improved).
114 //
115 /// CHECK-START: int Main.polynomialShort() loop_optimization (before)
116 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
117 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
118 //
119 /// CHECK-START: int Main.polynomialShort() loop_optimization (after)
120 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
121 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
122 static int polynomialShort() {
123 int x = 0;
124 for (short i = 0; i < 10; i++) {
125 x = x - i; // polynomial on narrowing linear
126 }
127 return x;
128 }
129
130 // Regression test for b/33774618: transfer operations involving
131 // narrowing linear induction should be done correctly
132 // (currently rejected, could be improved).
133 //
134 /// CHECK-START: int Main.polynomialIntFromLong() loop_optimization (before)
135 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
136 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
137 //
138 /// CHECK-START: int Main.polynomialIntFromLong() loop_optimization (after)
139 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
140 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
141 static int polynomialIntFromLong() {
142 int x = 0;
143 for (long i = 0; i < 10; i++) {
144 x = x - (int) i; // polynomial on narrowing linear
145 }
146 return x;
147 }
148
149 /// CHECK-START: int Main.polynomialInt() loop_optimization (before)
150 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
151 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
152 //
153 /// CHECK-START: int Main.polynomialInt() loop_optimization (after)
154 /// CHECK-NOT: Phi
155 //
156 /// CHECK-START: int Main.polynomialInt() instruction_simplifier$after_bce (after)
Aart Bikd3ba6262017-01-30 14:37:12 -0800157 /// CHECK-DAG: <<Int:i\d+>> IntConstant -45 loop:none
158 /// CHECK-DAG: Return [<<Int>>] loop:none
Aart Bik74da5292016-12-20 11:13:03 -0800159 static int polynomialInt() {
160 int x = 0;
161 for (int i = 0; i < 10; i++) {
162 x = x - i;
163 }
164 return x;
165 }
166
Aart Bikd3ba6262017-01-30 14:37:12 -0800167 // Regression test for b/34779592 (found with fuzz testing): overflow for last value
168 // of division truncates to zero, for multiplication it simply truncates.
169 //
170 /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (before)
171 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
172 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
173 //
174 /// CHECK-START: int Main.geoIntDivLastValue(int) loop_optimization (after)
175 /// CHECK-NOT: Phi
176 //
177 /// CHECK-START: int Main.geoIntDivLastValue(int) instruction_simplifier$after_bce (after)
178 /// CHECK-DAG: <<Int:i\d+>> IntConstant 0 loop:none
179 /// CHECK-DAG: Return [<<Int>>] loop:none
180 static int geoIntDivLastValue(int x) {
181 for (int i = 0; i < 2; i++) {
182 x /= 1081788608;
183 }
184 return x;
185 }
186
187 /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (before)
188 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
189 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
190 //
191 /// CHECK-START: int Main.geoIntMulLastValue(int) loop_optimization (after)
192 /// CHECK-NOT: Phi
193 //
194 /// CHECK-START: int Main.geoIntMulLastValue(int) instruction_simplifier$after_bce (after)
195 /// CHECK-DAG: <<Par:i\d+>> ParameterValue loop:none
196 /// CHECK-DAG: <<Int:i\d+>> IntConstant -194211840 loop:none
197 /// CHECK-DAG: <<Mul:i\d+>> Mul [<<Par>>,<<Int>>] loop:none
198 /// CHECK-DAG: Return [<<Mul>>] loop:none
199 static int geoIntMulLastValue(int x) {
200 for (int i = 0; i < 2; i++) {
201 x *= 1081788608;
202 }
203 return x;
204 }
205
206 /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (before)
207 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
208 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
209 //
210 /// CHECK-START: long Main.geoLongDivLastValue(long) loop_optimization (after)
211 /// CHECK-NOT: Phi
212 //
213 /// CHECK-START: long Main.geoLongDivLastValue(long) instruction_simplifier$after_bce (after)
214 /// CHECK-DAG: <<Long:j\d+>> LongConstant 0 loop:none
215 /// CHECK-DAG: Return [<<Long>>] loop:none
Aart Bikb603a5c2017-03-06 18:29:39 -0800216 //
217 // Tests overflow in the divisor (while updating intermediate result).
Aart Bikd3ba6262017-01-30 14:37:12 -0800218 static long geoLongDivLastValue(long x) {
219 for (int i = 0; i < 10; i++) {
220 x /= 1081788608;
221 }
222 return x;
223 }
224
Aart Bikb603a5c2017-03-06 18:29:39 -0800225 /// CHECK-START: long Main.geoLongDivLastValue() loop_optimization (before)
226 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
227 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
228 //
229 /// CHECK-START: long Main.geoLongDivLastValue() loop_optimization (after)
230 /// CHECK-NOT: Phi
231 //
232 /// CHECK-START: long Main.geoLongDivLastValue() instruction_simplifier$after_bce (after)
233 /// CHECK-DAG: <<Long:j\d+>> LongConstant 0 loop:none
234 /// CHECK-DAG: Return [<<Long>>] loop:none
235 //
236 // Tests overflow in the divisor (while updating base).
237 static long geoLongDivLastValue() {
238 long x = -1;
239 for (int i2 = 0; i2 < 2; i2++) {
240 x /= (Long.MAX_VALUE);
241 }
242 return x;
243 }
244
Aart Bikd3ba6262017-01-30 14:37:12 -0800245 /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (before)
246 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
247 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
248 //
249 /// CHECK-START: long Main.geoLongMulLastValue(long) loop_optimization (after)
250 /// CHECK-NOT: Phi
251 //
252 /// CHECK-START: long Main.geoLongMulLastValue(long) instruction_simplifier$after_bce (after)
253 /// CHECK-DAG: <<Par:j\d+>> ParameterValue loop:none
254 /// CHECK-DAG: <<Long:j\d+>> LongConstant -8070450532247928832 loop:none
255 /// CHECK-DAG: <<Mul:j\d+>> Mul [<<Par>>,<<Long>>] loop:none
256 /// CHECK-DAG: Return [<<Mul>>] loop:none
257 static long geoLongMulLastValue(long x) {
258 for (int i = 0; i < 10; i++) {
259 x *= 1081788608;
260 }
261 return x;
262 }
263
Aart Bik7adb6882017-03-07 13:28:51 -0800264 // If vectorized, the narrowing subscript should not cause
265 // type inconsistencies in the synthesized code.
266 static void narrowingSubscript(float[] a) {
267 float val = 2.0f;
268 for (long i = 0; i < a.length; i++) {
269 a[(int) i] += val;
270 }
271 }
272
Aart Bikfa762962017-04-07 11:33:37 -0700273 // If vectorized, invariant stride should be recognized
274 // as a reduction, not a unit stride in outer loop.
275 static void reduc(int[] xx, int[] yy) {
276 for (int i0 = 0; i0 < 2; i0++) {
277 for (int i1 = 0; i1 < 469; i1++) {
278 xx[i0] -= (++yy[i1]);
279 }
280 }
281 }
282
Aart Bik472821b2017-04-27 17:23:51 -0700283 /// CHECK-START: void Main.string2Bytes(char[], java.lang.String) loop_optimization (before)
284 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
285 /// CHECK-DAG: ArrayGet loop:<<Loop>> outer_loop:none
286 /// CHECK-DAG: ArraySet loop:<<Loop>> outer_loop:none
287 //
Artem Serov8f7c4102017-06-21 11:21:37 +0100288 /// CHECK-START-ARM: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after)
289 /// CHECK-NOT: VecLoad
290 //
Aart Bik472821b2017-04-27 17:23:51 -0700291 /// CHECK-START-ARM64: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after)
292 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
293 /// CHECK-DAG: VecLoad loop:<<Loop>> outer_loop:none
294 /// CHECK-DAG: VecStore loop:<<Loop>> outer_loop:none
295 //
296 // NOTE: should correctly deal with compressed and uncompressed cases.
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200297 //
298 /// CHECK-START-MIPS64: void Main.string2Bytes(char[], java.lang.String) loop_optimization (after)
299 /// CHECK-NOT: VecLoad
Aart Bik3101e582017-04-11 10:15:44 -0700300 private static void string2Bytes(char[] a, String b) {
301 int min = Math.min(a.length, b.length());
302 for (int i = 0; i < min; i++) {
303 a[i] = b.charAt(i);
304 }
305 }
306
Aart Bikd86c0852017-04-14 12:00:15 -0700307 // A strange function that does not inline.
308 private static void $noinline$foo(boolean x, int n) {
309 if (n < 0)
310 throw new Error("oh no");
311 if (n > 100) {
312 $noinline$foo(!x, n - 1);
313 $noinline$foo(!x, n - 2);
314 $noinline$foo(!x, n - 3);
315 $noinline$foo(!x, n - 4);
316 }
317 }
318
319 // A loop with environment uses of x (the terminating condition). As exposed by bug
320 // b/37247891, the loop can be unrolled, but should handle the (unlikely, but clearly
321 // not impossible) environment uses of the terminating condition in a correct manner.
322 private static void envUsesInCond() {
323 boolean x = false;
324 for (int i = 0; !(x = i >= 1); i++) {
325 $noinline$foo(true, i);
326 }
327 }
328
Aart Bikd58bc322017-05-01 14:49:18 -0700329 /// CHECK-START: void Main.oneBoth(short[], char[]) loop_optimization (before)
330 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
331 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
332 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none
333 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<One>>] loop:<<Loop>> outer_loop:none
334 //
Artem Serov8f7c4102017-06-21 11:21:37 +0100335 /// CHECK-START-ARM: void Main.oneBoth(short[], char[]) loop_optimization (after)
336 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
337 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none
338 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
339 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none
340 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none
341 //
Aart Bikd58bc322017-05-01 14:49:18 -0700342 /// CHECK-START-ARM64: void Main.oneBoth(short[], char[]) loop_optimization (after)
343 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
344 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none
345 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
346 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none
347 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none
348 //
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200349 /// CHECK-START-MIPS64: void Main.oneBoth(short[], char[]) loop_optimization (after)
350 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
351 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none
352 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
353 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none
354 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi>>,<<Repl>>] loop:<<Loop>> outer_loop:none
355 //
Aart Bikd58bc322017-05-01 14:49:18 -0700356 // Bug b/37764324: integral same-length packed types can be mixed freely.
357 private static void oneBoth(short[] a, char[] b) {
358 for (int i = 0; i < Math.min(a.length, b.length); i++) {
359 a[i] = 1;
360 b[i] = 1;
361 }
362 }
363
Aart Bike22445f2017-05-03 14:29:20 -0700364 // Bug b/37768917: potential dynamic BCE vs. loop optimizations
365 // case should be deal with correctly (used to DCHECK fail).
366 private static void arrayInTripCount(int[] a, byte[] b, int n) {
367 for (int k = 0; k < n; k++) {
368 for (int i = 0, u = a[0]; i < u; i++) {
369 b[i] += 2;
370 }
371 }
372 }
373
Aart Bik304c8a52017-05-23 11:01:13 -0700374 /// CHECK-START: void Main.typeConv(byte[], byte[]) loop_optimization (before)
375 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
376 /// CHECK-DAG: <<Phi:i\d+>> Phi loop:<<Loop:B\d+>> outer_loop:none
377 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi>>] loop:<<Loop>> outer_loop:none
378 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop>> outer_loop:none
379 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop>> outer_loop:none
380 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi>>,<<Cnv>>] loop:<<Loop>> outer_loop:none
381 //
Artem Serov8f7c4102017-06-21 11:21:37 +0100382 /// CHECK-START-ARM: void Main.typeConv(byte[], byte[]) loop_optimization (after)
383 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
384 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none
385 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none
386 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop1>> 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: <<Phi2:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:none
390 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2>>] loop:<<Loop2>> outer_loop:none
391 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none
392 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none
393 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none
394 //
Aart Bik304c8a52017-05-23 11:01:13 -0700395 /// CHECK-START-ARM64: void Main.typeConv(byte[], byte[]) loop_optimization (after)
396 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
397 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none
398 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none
399 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop1>> outer_loop:none
400 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>] loop:<<Loop1>> outer_loop:none
401 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>> outer_loop:none
402 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:none
403 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2>>] loop:<<Loop2>> outer_loop:none
404 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none
405 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none
406 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none
407 //
Goran Jakovljevic19680d32017-05-11 10:38:36 +0200408 /// CHECK-START-MIPS64: void Main.typeConv(byte[], byte[]) loop_optimization (after)
409 /// CHECK-DAG: <<One:i\d+>> IntConstant 1 loop:none
410 /// CHECK-DAG: <<Repl:d\d+>> VecReplicateScalar [<<One>>] loop:none
411 /// CHECK-DAG: <<Phi1:i\d+>> Phi loop:<<Loop1:B\d+>> outer_loop:none
412 /// CHECK-DAG: <<Load:d\d+>> VecLoad [{{l\d+}},<<Phi1>>] loop:<<Loop1>> outer_loop:none
413 /// CHECK-DAG: <<Vadd:d\d+>> VecAdd [<<Load>>,<<Repl>>] loop:<<Loop1>> outer_loop:none
414 /// CHECK-DAG: VecStore [{{l\d+}},<<Phi1>>,<<Vadd>>] loop:<<Loop1>> outer_loop:none
415 /// CHECK-DAG: <<Phi2:i\d+>> Phi loop:<<Loop2:B\d+>> outer_loop:none
416 /// CHECK-DAG: <<Get:b\d+>> ArrayGet [{{l\d+}},<<Phi2>>] loop:<<Loop2>> outer_loop:none
417 /// CHECK-DAG: <<Add:i\d+>> Add [<<Get>>,<<One>>] loop:<<Loop2>> outer_loop:none
418 /// CHECK-DAG: <<Cnv:b\d+>> TypeConversion [<<Add>>] loop:<<Loop2>> outer_loop:none
419 /// CHECK-DAG: ArraySet [{{l\d+}},<<Phi2>>,<<Cnv>>] loop:<<Loop2>> outer_loop:none
420 //
Aart Bik304c8a52017-05-23 11:01:13 -0700421 // Scalar code in cleanup loop uses correct byte type on array get and type conversion.
422 private static void typeConv(byte[] a, byte[] b) {
423 int len = Math.min(a.length, b.length);
424 for (int i = 0; i < len; i++) {
425 a[i] = (byte) (b[i] + 1);
426 }
427 }
428
Artem Serov21c7e6f2017-07-27 16:04:42 +0100429 // Environment of an instruction, removed during SimplifyInduction, should be adjusted.
430 //
431 /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (before)
432 /// CHECK-DAG: Phi loop:<<Loop:B\d+>> outer_loop:none
433 /// CHECK-DAG: Phi loop:<<Loop>> outer_loop:none
434 //
435 /// CHECK-START: void Main.inductionMax(int[]) loop_optimization (after)
436 /// CHECK-NOT: Phi
437 private static void inductionMax(int[] a) {
438 int s = 0;
439 for (int i = 0; i < 10; i++) {
440 s = Math.max(s, 5);
441 }
442 }
443
Aart Bik671e48a2017-08-09 13:16:56 -0700444 /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (before)
445 /// CHECK-DAG: Phi loop:<<Loop1:B\d+>> outer_loop:none
446 /// CHECK-DAG: Phi loop:<<Loop1>> outer_loop:none
447 /// CHECK-DAG: Phi loop:<<Loop2:B\d+>> outer_loop:none
448 //
449 /// CHECK-EVAL: "<<Loop1>>" != "<<Loop2>>"
450 //
451 /// CHECK-START: int Main.feedsIntoDeopt(int[]) loop_optimization (after)
452 /// CHECK-DAG: Phi loop:{{B\d+}} outer_loop:none
453 /// CHECK-NOT: Phi
454 static int feedsIntoDeopt(int[] a) {
455 // Reduction should be removed.
456 int r = 0;
457 for (int i = 0; i < 100; i++) {
458 r += 10;
459 }
460 // Even though uses feed into deopts of BCE.
461 for (int i = 1; i < 100; i++) {
462 a[i] = a[i - 1];
463 }
464 return r;
465 }
466
Aart Bik807868e2016-11-03 17:51:43 -0700467 public static void main(String[] args) {
468 expectEquals(10, earlyExitFirst(-1));
469 for (int i = 0; i <= 10; i++) {
470 expectEquals(i, earlyExitFirst(i));
471 }
472 expectEquals(10, earlyExitFirst(11));
473
474 expectEquals(10, earlyExitLast(-1));
475 for (int i = 0; i < 10; i++) {
476 expectEquals(i + 1, earlyExitLast(i));
477 }
478 expectEquals(10, earlyExitLast(10));
479 expectEquals(10, earlyExitLast(11));
480
481 expectEquals(2, earlyExitNested());
482
Aart Bik74da5292016-12-20 11:13:03 -0800483 expectEquals(17, transferNarrowWrap());
484 expectEquals(-45, polynomialShort());
485 expectEquals(-45, polynomialIntFromLong());
486 expectEquals(-45, polynomialInt());
487
Aart Bikd3ba6262017-01-30 14:37:12 -0800488 expectEquals(0, geoIntDivLastValue(0));
489 expectEquals(0, geoIntDivLastValue(1));
490 expectEquals(0, geoIntDivLastValue(2));
491 expectEquals(0, geoIntDivLastValue(1081788608));
492 expectEquals(0, geoIntDivLastValue(-1081788608));
493 expectEquals(0, geoIntDivLastValue(2147483647));
494 expectEquals(0, geoIntDivLastValue(-2147483648));
495
496 expectEquals( 0, geoIntMulLastValue(0));
497 expectEquals( -194211840, geoIntMulLastValue(1));
498 expectEquals( -388423680, geoIntMulLastValue(2));
499 expectEquals(-1041498112, geoIntMulLastValue(1081788608));
500 expectEquals( 1041498112, geoIntMulLastValue(-1081788608));
501 expectEquals( 194211840, geoIntMulLastValue(2147483647));
502 expectEquals( 0, geoIntMulLastValue(-2147483648));
503
504 expectEquals(0L, geoLongDivLastValue(0L));
505 expectEquals(0L, geoLongDivLastValue(1L));
506 expectEquals(0L, geoLongDivLastValue(2L));
507 expectEquals(0L, geoLongDivLastValue(1081788608L));
508 expectEquals(0L, geoLongDivLastValue(-1081788608L));
509 expectEquals(0L, geoLongDivLastValue(2147483647L));
510 expectEquals(0L, geoLongDivLastValue(-2147483648L));
511 expectEquals(0L, geoLongDivLastValue(9223372036854775807L));
512 expectEquals(0L, geoLongDivLastValue(-9223372036854775808L));
513
Aart Bikb603a5c2017-03-06 18:29:39 -0800514 expectEquals(0L, geoLongDivLastValue());
515
Aart Bikd3ba6262017-01-30 14:37:12 -0800516 expectEquals( 0L, geoLongMulLastValue(0L));
517 expectEquals(-8070450532247928832L, geoLongMulLastValue(1L));
518 expectEquals( 2305843009213693952L, geoLongMulLastValue(2L));
519 expectEquals( 0L, geoLongMulLastValue(1081788608L));
520 expectEquals( 0L, geoLongMulLastValue(-1081788608L));
521 expectEquals( 8070450532247928832L, geoLongMulLastValue(2147483647L));
522 expectEquals( 0L, geoLongMulLastValue(-2147483648L));
523 expectEquals( 8070450532247928832L, geoLongMulLastValue(9223372036854775807L));
524 expectEquals( 0L, geoLongMulLastValue(-9223372036854775808L));
525
Aart Bik7adb6882017-03-07 13:28:51 -0800526 float[] a = new float[16];
527 narrowingSubscript(a);
528 for (int i = 0; i < 16; i++) {
529 expectEquals(2.0f, a[i]);
530 }
531
Aart Bikfa762962017-04-07 11:33:37 -0700532 int[] xx = new int[2];
533 int[] yy = new int[469];
534 reduc(xx, yy);
535 expectEquals(-469, xx[0]);
536 expectEquals(-938, xx[1]);
537 for (int i = 0; i < 469; i++) {
538 expectEquals(2, yy[i]);
539 }
540
Aart Bik3101e582017-04-11 10:15:44 -0700541 char[] aa = new char[23];
542 String bb = "hello world how are you";
543 string2Bytes(aa, bb);
544 for (int i = 0; i < aa.length; i++) {
545 expectEquals(aa[i], bb.charAt(i));
546 }
Aart Bik472821b2017-04-27 17:23:51 -0700547 String cc = "\u1010\u2020llo world how are y\u3030\u4040";
548 string2Bytes(aa, cc);
549 for (int i = 0; i < aa.length; i++) {
550 expectEquals(aa[i], cc.charAt(i));
551 }
Aart Bik3101e582017-04-11 10:15:44 -0700552
Aart Bikd86c0852017-04-14 12:00:15 -0700553 envUsesInCond();
554
Aart Bikd58bc322017-05-01 14:49:18 -0700555 short[] dd = new short[23];
556 oneBoth(dd, aa);
557 for (int i = 0; i < aa.length; i++) {
558 expectEquals(aa[i], 1);
559 expectEquals(dd[i], 1);
560 }
561
Aart Bike22445f2017-05-03 14:29:20 -0700562 xx[0] = 10;
563 byte[] bt = new byte[10];
564 arrayInTripCount(xx, bt, 20);
565 for (int i = 0; i < bt.length; i++) {
566 expectEquals(40, bt[i]);
567 }
568
Aart Bik304c8a52017-05-23 11:01:13 -0700569 byte[] b1 = new byte[259]; // few extra iterations
570 byte[] b2 = new byte[259];
571 for (int i = 0; i < 259; i++) {
572 b1[i] = 0;
573 b2[i] = (byte) i;
574 }
575 typeConv(b1, b2);
576 for (int i = 0; i < 259; i++) {
577 expectEquals((byte)(i + 1), b1[i]);
578 }
579
Artem Serov21c7e6f2017-07-27 16:04:42 +0100580 inductionMax(yy);
581
Aart Bik671e48a2017-08-09 13:16:56 -0700582 int[] f = new int[100];
583 f[0] = 11;
584 expectEquals(1000, feedsIntoDeopt(f));
585 for (int i = 0; i < 100; i++) {
586 expectEquals(11, f[i]);
587 }
588
Aart Bik807868e2016-11-03 17:51:43 -0700589 System.out.println("passed");
590 }
591
592 private static void expectEquals(int expected, int result) {
593 if (expected != result) {
594 throw new Error("Expected: " + expected + ", found: " + result);
595 }
596 }
Aart Bikd3ba6262017-01-30 14:37:12 -0800597
598 private static void expectEquals(long expected, long result) {
599 if (expected != result) {
600 throw new Error("Expected: " + expected + ", found: " + result);
601 }
602 }
Aart Bik7adb6882017-03-07 13:28:51 -0800603
604 private static void expectEquals(float expected, float result) {
605 if (expected != result) {
606 throw new Error("Expected: " + expected + ", found: " + result);
607 }
608 }
Aart Bik807868e2016-11-03 17:51:43 -0700609}