blob: dca00bd2ecb20c8f6b377144f0e39e2b423b9551 [file] [log] [blame]
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001/*
2 * Copyright (C) 2015 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// Test on loop optimizations.
19//
20public class Main {
21
22 static int sResult;
23
24 //
25 // Various sequence variables used in bound checks.
26 //
27
28 /// CHECK-START: void Main.bubble(int[]) BCE (before)
29 /// CHECK-DAG: BoundsCheck
30 /// CHECK-DAG: BoundsCheck
31 //
32 /// CHECK-START: void Main.bubble(int[]) BCE (after)
33 /// CHECK-NOT: BoundsCheck
Aart Bik52be7e72016-06-23 11:20:41 -070034 /// CHECK-NOT: Deoptimize
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +000035 private static void bubble(int[] a) {
36 for (int i = a.length; --i >= 0;) {
37 for (int j = 0; j < i; j++) {
38 if (a[j] > a[j+1]) {
39 int tmp = a[j];
40 a[j] = a[j+1];
41 a[j+1] = tmp;
42 }
43 }
44 }
45 }
46
47 /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
48 /// CHECK-DAG: BoundsCheck
49 //
50 /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
51 /// CHECK-NOT: BoundsCheck
52 /// CHECK-NOT: Deoptimize
53 private static int periodicIdiom(int tc) {
54 int[] x = { 1, 3 };
55 // Loop with periodic sequence (0, 1).
56 int k = 0;
57 int result = 0;
58 for (int i = 0; i < tc; i++) {
59 result += x[k];
60 k = 1 - k;
61 }
62 return result;
63 }
64
65 /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
66 /// CHECK-DAG: BoundsCheck
67 //
68 /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
69 /// CHECK-NOT: BoundsCheck
70 /// CHECK-NOT: Deoptimize
71 private static int periodicSequence2(int tc) {
72 int[] x = { 1, 3 };
73 // Loop with periodic sequence (0, 1).
74 int k = 0;
75 int l = 1;
76 int result = 0;
77 for (int i = 0; i < tc; i++) {
78 result += x[k];
79 int t = l;
80 l = k;
81 k = t;
82 }
83 return result;
84 }
85
86 /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
87 /// CHECK-DAG: BoundsCheck
88 /// CHECK-DAG: BoundsCheck
89 /// CHECK-DAG: BoundsCheck
90 /// CHECK-DAG: BoundsCheck
91 //
92 /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
93 /// CHECK-NOT: BoundsCheck
94 /// CHECK-NOT: Deoptimize
95 private static int periodicSequence4(int tc) {
96 int[] x = { 1, 3, 5, 7 };
97 // Loop with periodic sequence (0, 1, 2, 3).
98 int k = 0;
99 int l = 1;
100 int m = 2;
101 int n = 3;
102 int result = 0;
103 for (int i = 0; i < tc; i++) {
104 result += x[k] + x[l] + x[m] + x[n]; // all used at once
105 int t = n;
106 n = k;
107 k = l;
108 l = m;
109 m = t;
110 }
111 return result;
112 }
113
Aart Bik7dc96932016-10-12 10:01:05 -0700114 /// CHECK-START: int Main.periodicXorSequence(int) BCE (before)
115 /// CHECK-DAG: BoundsCheck
116 //
117 /// CHECK-START: int Main.periodicXorSequence(int) BCE (after)
118 /// CHECK-NOT: BoundsCheck
119 /// CHECK-NOT: Deoptimize
120 private static int periodicXorSequence(int tc) {
121 int[] x = { 1, 3 };
122 // Loop with periodic sequence (0, 1).
123 int k = 0;
124 int result = 0;
125 for (int i = 0; i < tc; i++) {
126 result += x[k];
127 k ^= 1;
128 }
129 return result;
130 }
131
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000132 /// CHECK-START: int Main.justRightUp1() BCE (before)
133 /// CHECK-DAG: BoundsCheck
134 //
135 /// CHECK-START: int Main.justRightUp1() BCE (after)
136 /// CHECK-NOT: BoundsCheck
137 /// CHECK-NOT: Deoptimize
138 private static int justRightUp1() {
139 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
140 int result = 0;
141 for (int i = Integer.MAX_VALUE - 10, k = 0; i < Integer.MAX_VALUE; i++) {
142 result += x[k++];
143 }
144 return result;
145 }
146
147 /// CHECK-START: int Main.justRightUp2() BCE (before)
148 /// CHECK-DAG: BoundsCheck
149 //
150 /// CHECK-START: int Main.justRightUp2() BCE (after)
151 /// CHECK-NOT: BoundsCheck
152 /// CHECK-NOT: Deoptimize
153 private static int justRightUp2() {
154 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
155 int result = 0;
156 for (int i = Integer.MAX_VALUE - 10; i < Integer.MAX_VALUE; i++) {
157 result += x[i - Integer.MAX_VALUE + 10];
158 }
159 return result;
160 }
161
162 /// CHECK-START: int Main.justRightUp3() BCE (before)
163 /// CHECK-DAG: BoundsCheck
164 //
165 /// CHECK-START: int Main.justRightUp3() BCE (after)
166 /// CHECK-NOT: BoundsCheck
167 /// CHECK-NOT: Deoptimize
168 private static int justRightUp3() {
169 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
170 int result = 0;
171 for (int i = Integer.MAX_VALUE - 10, k = 0; i <= Integer.MAX_VALUE - 1; i++) {
172 result += x[k++];
173 }
174 return result;
175 }
176
177 /// CHECK-START: int Main.justOOBUp() BCE (before)
178 /// CHECK-DAG: BoundsCheck
179 //
180 /// CHECK-START: int Main.justOOBUp() BCE (after)
181 /// CHECK-DAG: BoundsCheck
182 //
183 /// CHECK-START: int Main.justOOBUp() BCE (after)
184 /// CHECK-NOT: Deoptimize
185 private static int justOOBUp() {
186 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
187 int result = 0;
188 // Infinite loop!
189 for (int i = Integer.MAX_VALUE - 9, k = 0; i <= Integer.MAX_VALUE; i++) {
190 result += x[k++];
191 }
192 return result;
193 }
194
195 /// CHECK-START: int Main.justRightDown1() BCE (before)
196 /// CHECK-DAG: BoundsCheck
197 //
198 /// CHECK-START: int Main.justRightDown1() BCE (after)
199 /// CHECK-NOT: BoundsCheck
200 /// CHECK-NOT: Deoptimize
201 private static int justRightDown1() {
202 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
203 int result = 0;
204 for (int i = Integer.MIN_VALUE + 10, k = 0; i > Integer.MIN_VALUE; i--) {
205 result += x[k++];
206 }
207 return result;
208 }
209
210 /// CHECK-START: int Main.justRightDown2() BCE (before)
211 /// CHECK-DAG: BoundsCheck
212 //
213 /// CHECK-START: int Main.justRightDown2() BCE (after)
214 /// CHECK-NOT: BoundsCheck
215 /// CHECK-NOT: Deoptimize
216 private static int justRightDown2() {
217 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
218 int result = 0;
219 for (int i = Integer.MIN_VALUE + 10; i > Integer.MIN_VALUE; i--) {
220 result += x[Integer.MAX_VALUE + i];
221 }
222 return result;
223 }
224
225 /// CHECK-START: int Main.justRightDown3() BCE (before)
226 /// CHECK-DAG: BoundsCheck
227 //
228 /// CHECK-START: int Main.justRightDown3() BCE (after)
229 /// CHECK-NOT: BoundsCheck
230 /// CHECK-NOT: Deoptimize
231 private static int justRightDown3() {
232 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
233 int result = 0;
234 for (int i = Integer.MIN_VALUE + 10, k = 0; i >= Integer.MIN_VALUE + 1; i--) {
235 result += x[k++];
236 }
237 return result;
238 }
239
240 /// CHECK-START: int Main.justOOBDown() BCE (before)
241 /// CHECK-DAG: BoundsCheck
242 //
243 /// CHECK-START: int Main.justOOBDown() BCE (after)
244 /// CHECK-DAG: BoundsCheck
245 //
246 /// CHECK-START: int Main.justOOBDown() BCE (after)
247 /// CHECK-NOT: Deoptimize
248 private static int justOOBDown() {
249 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
250 int result = 0;
251 // Infinite loop!
252 for (int i = Integer.MIN_VALUE + 9, k = 0; i >= Integer.MIN_VALUE; i--) {
253 result += x[k++];
254 }
255 return result;
256 }
257
258 /// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
259 /// CHECK-DAG: BoundsCheck
260 //
261 /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
262 /// CHECK-DAG: BoundsCheck
263 //
264 /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
265 /// CHECK-NOT: Deoptimize
266 private static void lowerOOB(int[] x) {
267 // OOB!
268 for (int i = -1; i < x.length; i++) {
269 sResult += x[i];
270 }
271 }
272
273 /// CHECK-START: void Main.upperOOB(int[]) BCE (before)
274 /// CHECK-DAG: BoundsCheck
275 //
276 /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
277 /// CHECK-DAG: BoundsCheck
278 //
279 /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
280 /// CHECK-NOT: Deoptimize
281 private static void upperOOB(int[] x) {
282 // OOB!
283 for (int i = 0; i <= x.length; i++) {
284 sResult += x[i];
285 }
286 }
287
288 /// CHECK-START: void Main.doWhileUpOOB() BCE (before)
289 /// CHECK-DAG: BoundsCheck
290 //
291 /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
292 /// CHECK-DAG: BoundsCheck
293 //
294 /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
295 /// CHECK-NOT: Deoptimize
296 private static void doWhileUpOOB() {
297 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
298 int i = 0;
299 // OOB!
300 do {
301 sResult += x[i++];
302 } while (i <= x.length);
303 }
304
305 /// CHECK-START: void Main.doWhileDownOOB() BCE (before)
306 /// CHECK-DAG: BoundsCheck
307 //
308 /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
309 /// CHECK-DAG: BoundsCheck
310 //
311 /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
312 /// CHECK-NOT: Deoptimize
313 private static void doWhileDownOOB() {
314 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
315 int i = x.length - 1;
316 // OOB!
317 do {
318 sResult += x[i--];
319 } while (-1 <= i);
320 }
321
Aart Bik52be7e72016-06-23 11:20:41 -0700322 /// CHECK-START: void Main.justRightTriangular1() BCE (before)
323 /// CHECK-DAG: BoundsCheck
324 //
325 /// CHECK-START: void Main.justRightTriangular1() BCE (after)
326 /// CHECK-NOT: BoundsCheck
327 /// CHECK-NOT: Deoptimize
328 private static void justRightTriangular1() {
329 int[] a = { 1 } ;
330 for (int i = Integer.MIN_VALUE + 5; i <= Integer.MIN_VALUE + 10; i++) {
331 for (int j = Integer.MIN_VALUE + 4; j < i - 5; j++) {
332 sResult += a[j - (Integer.MIN_VALUE + 4)];
333 }
334 }
335 }
336
337 /// CHECK-START: void Main.justRightTriangular2() BCE (before)
338 /// CHECK-DAG: BoundsCheck
339 //
340 /// CHECK-START: void Main.justRightTriangular2() BCE (after)
341 /// CHECK-NOT: BoundsCheck
342 /// CHECK-NOT: Deoptimize
343 private static void justRightTriangular2() {
344 int[] a = { 1 } ;
345 for (int i = Integer.MIN_VALUE + 5; i <= 10; i++) {
346 for (int j = 4; j < i - 5; j++) {
347 sResult += a[j - 4];
348 }
349 }
350 }
351
352 /// CHECK-START: void Main.justOOBTriangular() BCE (before)
353 /// CHECK-DAG: BoundsCheck
354 //
355 /// CHECK-START: void Main.justOOBTriangular() BCE (after)
356 /// CHECK-DAG: Deoptimize
357 //
358 /// CHECK-START: void Main.justOOBTriangular() BCE (after)
359 /// CHECK-NOT: BoundsCheck
360 private static void justOOBTriangular() {
361 int[] a = { 1 } ;
362 for (int i = Integer.MIN_VALUE + 4; i <= 10; i++) {
363 for (int j = 4; j < i - 5; j++) {
364 sResult += a[j - 4];
365 }
366 }
367 }
368
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000369 /// CHECK-START: void Main.hiddenOOB1(int) BCE (before)
370 /// CHECK-DAG: BoundsCheck
371 //
372 /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
373 /// CHECK-DAG: Deoptimize
374 //
375 /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
376 /// CHECK-NOT: BoundsCheck
377 private static void hiddenOOB1(int lo) {
378 int[] a = { 1 } ;
379 for (int i = lo; i <= 10; i++) {
380 // Dangerous loop where careless static range analysis would yield strict upper bound
381 // on index j of 5. When, for instance, lo and thus i = -2147483648, the upper bound
382 // becomes really positive due to arithmetic wrap-around, causing OOB.
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000383 for (int j = 4; j < i - 5; j++) {
384 sResult += a[j - 4];
385 }
386 }
387 }
388
389 /// CHECK-START: void Main.hiddenOOB2(int) BCE (before)
390 /// CHECK-DAG: BoundsCheck
391 //
392 /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
393 /// CHECK-DAG: Deoptimize
394 //
395 /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
396 /// CHECK-NOT: BoundsCheck
397 private static void hiddenOOB2(int hi) {
398 int[] a = { 1 } ;
399 for (int i = 0; i < hi; i++) {
400 // Dangerous loop where careless static range analysis would yield strict lower bound
401 // on index j of 5. When, for instance, hi and thus i = 2147483647, the upper bound
402 // becomes really negative due to arithmetic wrap-around, causing OOB.
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000403 for (int j = 6; j > i + 5; j--) {
404 sResult += a[j - 6];
405 }
406 }
407 }
408
Aart Bik52be7e72016-06-23 11:20:41 -0700409 /// CHECK-START: void Main.hiddenOOB3(int) BCE (before)
410 /// CHECK-DAG: BoundsCheck
411 //
412 /// CHECK-START: void Main.hiddenOOB3(int) BCE (after)
413 /// CHECK-DAG: Deoptimize
414 //
415 /// CHECK-START: void Main.hiddenOOB3(int) BCE (after)
416 /// CHECK-NOT: BoundsCheck
417 private static void hiddenOOB3(int hi) {
418 int[] a = { 11 } ;
419 for (int i = -1; i <= hi; i++) {
420 // Dangerous loop where careless static range analysis would yield strict lower bound
421 // on index j of 0. For large i, the initial value of j becomes really negative due
422 // to arithmetic wrap-around, causing OOB.
423 for (int j = i + 1; j < 1; j++) {
424 sResult += a[j];
425 }
426 }
427 }
428
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000429 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (before)
430 /// CHECK-DAG: BoundsCheck
431 //
432 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
433 /// CHECK-DAG: BoundsCheck
434 //
435 /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
436 /// CHECK-NOT: Deoptimize
437 private static void hiddenInfiniteOOB() {
438 int[] a = { 11 } ;
439 for (int i = -1; i <= 0; i++) {
440 // Dangerous loop where careless static range analysis would yield a safe upper bound
441 // of -3. In reality, due to arithmetic wrap-around (when i = -1, j <= 2147483647;
442 // whereas when i = 0, j <= -3), this is an infinite loop that goes OOB.
443 for (int j = -3; j <= 2147483646 * i - 3; j++) {
444 sResult += a[j + 3];
445 }
446 }
447 }
448
449 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (before)
450 /// CHECK-DAG: BoundsCheck
451 //
452 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
453 /// CHECK-DAG: Deoptimize
454 //
455 /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
456 /// CHECK-NOT: BoundsCheck
457 private static void hiddenFiniteOOB() {
458 int[] a = { 111 } ;
459 for (int i = -1; i <= 0; i++) {
460 // Dangerous loop similar as above where the loop is now finite, but the
461 // loop still goes out of bounds for i = -1 due to the large upper bound.
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000462 for (int j = -4; j < 2147483646 * i - 3; j++) {
463 sResult += a[j + 4];
464 }
465 }
466 }
467
Aart Bik0d345cf2016-03-16 10:49:38 -0700468 /// CHECK-START: void Main.inductionOOB(int[]) BCE (before)
469 /// CHECK-DAG: BoundsCheck
470 //
471 /// CHECK-START: void Main.inductionOOB(int[]) BCE (after)
472 /// CHECK-DAG: BoundsCheck
473 //
474 /// CHECK-START: void Main.inductionOOB(int[]) BCE (after)
475 /// CHECK-NOT: Deoptimize
476 private static void inductionOOB(int[] a) {
477 // Careless range analysis would remove the bounds check.
478 // However, the narrower induction b wraps around arithmetically
479 // before it reaches the end of arrays longer than 127.
480 byte b = 0;
481 for (int i = 0; i < a.length; i++) {
482 a[b++] = i;
483 }
484 }
485
486 /// CHECK-START: void Main.controlOOB(int[]) BCE (before)
487 /// CHECK-DAG: BoundsCheck
488 //
489 /// CHECK-START: void Main.controlOOB(int[]) BCE (after)
490 /// CHECK-DAG: BoundsCheck
491 //
492 /// CHECK-START: void Main.controlOOB(int[]) BCE (after)
493 /// CHECK-NOT: Deoptimize
494 private static void controlOOB(int[] a) {
495 // As above, but now the loop control also wraps around.
496 for (byte i = 0; i < a.length; i++) {
497 a[i] = -i;
498 }
499 }
500
501 /// CHECK-START: void Main.conversionOOB(int[]) BCE (before)
502 /// CHECK-DAG: BoundsCheck
503 //
504 /// CHECK-START: void Main.conversionOOB(int[]) BCE (after)
505 /// CHECK-DAG: BoundsCheck
506 //
507 /// CHECK-START: void Main.conversionOOB(int[]) BCE (after)
508 /// CHECK-NOT: Deoptimize
509 private static void conversionOOB(int[] a) {
510 // As above, but with wrap around caused by an explicit conversion.
511 for (int i = 0; i < a.length; ) {
512 a[i] = i;
513 i = (byte) (i + 1);
514 }
515 }
516
Aart Bik52be7e72016-06-23 11:20:41 -0700517 /// CHECK-START: int Main.doNotHoist(int[]) BCE (before)
518 /// CHECK-DAG: BoundsCheck
519 //
520 /// CHECK-START: int Main.doNotHoist(int[]) BCE (after)
521 /// CHECK-NOT: BoundsCheck
522 public static int doNotHoist(int[] a) {
523 int n = a.length;
524 int x = 0;
525 // BCE applies, but hoisting would crash the loop.
526 for (int i = -10000; i < 10000; i++) {
527 for (int j = 0; j <= 1; j++) {
528 if (0 <= i && i < n)
529 x += a[i];
530 }
531 }
532 return x;
533 }
534
535
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000536 /// CHECK-START: int[] Main.add() BCE (before)
537 /// CHECK-DAG: BoundsCheck
538 //
539 /// CHECK-START: int[] Main.add() BCE (after)
540 /// CHECK-NOT: BoundsCheck
541 /// CHECK-NOT: Deoptimize
542 private static int[] add() {
543 int[] a = new int[10];
544 for (int i = 0; i <= 3; i++) {
545 for (int j = 0; j <= 6; j++) {
546 a[i + j] += 1;
547 }
548 }
549 return a;
550 }
551
552 /// CHECK-START: int[] Main.multiply1() BCE (before)
553 /// CHECK-DAG: BoundsCheck
554 //
555 /// CHECK-START: int[] Main.multiply1() BCE (after)
556 /// CHECK-NOT: BoundsCheck
557 /// CHECK-NOT: Deoptimize
558 private static int[] multiply1() {
559 int[] a = new int[10];
560 try {
561 for (int i = 0; i <= 3; i++) {
562 for (int j = 0; j <= 3; j++) {
563 // Range [0,9]: safe.
564 a[i * j] += 1;
565 }
566 }
567 } catch (Exception e) {
568 a[0] += 1000;
569 }
570 return a;
571 }
572
573 /// CHECK-START: int[] Main.multiply2() BCE (before)
574 /// CHECK-DAG: BoundsCheck
575 //
576 /// CHECK-START: int[] Main.multiply2() BCE (after)
577 /// CHECK-DAG: BoundsCheck
578 //
579 /// CHECK-START: int[] Main.multiply2() BCE (after)
580 /// CHECK-NOT: Deoptimize
581 static int[] multiply2() {
582 int[] a = new int[10];
583 try {
584 for (int i = -3; i <= 3; i++) {
585 for (int j = -3; j <= 3; j++) {
586 // Range [-9,9]: unsafe.
587 a[i * j] += 1;
588 }
589 }
590 } catch (Exception e) {
591 a[0] += 1000;
592 }
593 return a;
594 }
595
596 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
597 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
598 /// CHECK-DAG: NullCheck loop:<<Loop>>
599 /// CHECK-DAG: ArrayLength loop:<<Loop>>
600 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
601 //
602 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
603 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
604 /// CHECK-DAG: Deoptimize loop:none
605 //
606 /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
607 /// CHECK-NOT: NullCheck loop:{{B\d+}}
608 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
609 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
610 private static int linearDynamicBCE1(int[] x, int lo, int hi) {
611 int result = 0;
612 for (int i = lo; i < hi; i++) {
613 sResult += x[i];
614 }
615 return result;
616 }
617
618 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
619 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
620 /// CHECK-DAG: NullCheck loop:<<Loop>>
621 /// CHECK-DAG: ArrayLength loop:<<Loop>>
622 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
623 //
624 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
625 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
626 /// CHECK-DAG: Deoptimize loop:none
627 //
628 /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
629 /// CHECK-NOT: NullCheck loop:{{B\d+}}
630 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
631 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
632 private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
633 int result = 0;
634 for (int i = lo; i < hi; i++) {
635 sResult += x[offset + i];
636 }
637 return result;
638 }
639
640 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
641 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
642 /// CHECK-DAG: NullCheck loop:<<Loop>>
643 /// CHECK-DAG: ArrayLength loop:<<Loop>>
644 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
645 //
646 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
647 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
648 /// CHECK-DAG: Deoptimize loop:none
649 //
650 /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
651 /// CHECK-NOT: NullCheck loop:{{B\d+}}
652 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
653 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
654 private static int wrapAroundDynamicBCE(int[] x) {
655 int w = 9;
656 int result = 0;
657 for (int i = 0; i < 10; i++) {
658 result += x[w];
659 w = i;
660 }
661 return result;
662 }
663
664 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
665 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
666 /// CHECK-DAG: NullCheck loop:<<Loop>>
667 /// CHECK-DAG: ArrayLength loop:<<Loop>>
668 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
669 //
670 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
671 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
672 /// CHECK-DAG: Deoptimize loop:none
673 //
674 /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
675 /// CHECK-NOT: NullCheck loop:{{B\d+}}
676 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
677 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
678 private static int periodicDynamicBCE(int[] x) {
679 int k = 0;
680 int result = 0;
681 for (int i = 0; i < 10; i++) {
682 result += x[k];
683 k = 1 - k;
684 }
685 return result;
686 }
687
688 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
689 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
690 /// CHECK-DAG: NullCheck loop:<<Loop>>
691 /// CHECK-DAG: ArrayLength loop:<<Loop>>
692 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
693 //
694 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
695 /// CHECK-DAG: ArrayGet loop:{{B\d+}}
696 /// CHECK-DAG: Deoptimize loop:none
697 //
698 /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
699 /// CHECK-NOT: NullCheck loop:{{B\d+}}
700 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
701 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
702 static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
703 // This loop could be infinite for hi = max int. Since i is also used
704 // as subscript, however, dynamic bce can proceed.
705 int result = 0;
706 for (int i = lo; i <= hi; i++) {
707 result += x[i];
708 }
709 return result;
710 }
711
712 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
713 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
714 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
715 //
716 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
717 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
718 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
719 //
720 /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
721 /// CHECK-NOT: Deoptimize
722 static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
723 // As above, but now the index is not used as subscript,
724 // and dynamic bce is not applied.
725 int result = 0;
726 for (int k = 0, i = lo; i <= hi; i++) {
727 result += x[k++];
728 }
729 return result;
730 }
731
732 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
733 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
734 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
735 //
736 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
737 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
738 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
739 //
740 /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
741 /// CHECK-NOT: Deoptimize
742 static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
743 int result = 0;
744 // Mix of int and long induction.
745 int k = 0;
746 for (long i = lo; i < hi; i++) {
747 result += x[k++];
748 }
749 return result;
750 }
751
752 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (before)
753 /// CHECK-DAG: BoundsCheck loop:<<InnerLoop:B\d+>>
754 /// CHECK-DAG: ArrayGet loop:<<InnerLoop>>
755 /// CHECK-DAG: If loop:<<InnerLoop>>
756 /// CHECK-DAG: If loop:<<OuterLoop:B\d+>>
757 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
758 //
759 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
760 /// CHECK-DAG: ArrayGet loop:<<InnerLoop:B\d+>>
761 /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
762 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
763 //
764 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
765 /// CHECK-NOT: BoundsCheck
766 //
767 // No additional top tests were introduced.
768 /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
769 /// CHECK-DAG: If
770 /// CHECK-DAG: If
771 /// CHECK-NOT: If
772 static int dynamicBCEConstantRange(int[] x) {
773 int result = 0;
774 for (int i = 2; i <= 6; i++) {
775 // Range analysis sees that innermost loop is finite and always taken.
776 for (int j = i - 2; j <= i + 2; j++) {
777 result += x[j];
778 }
779 }
780 return result;
781 }
782
783 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
784 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop:B\d+>>
785 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
786 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
787 //
788 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
789 // Order matters:
790 /// CHECK: Deoptimize loop:<<Loop:B\d+>>
Aart Bik52be7e72016-06-23 11:20:41 -0700791 /// CHECK-NOT: Goto loop:<<Loop>>
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000792 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
793 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
794 /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
795 /// CHECK: Goto loop:<<Loop>>
796 //
797 /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
798 /// CHECK-DAG: Deoptimize loop:none
799 static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
800 // Deliberately test array length on a before the loop so that only bounds checks
801 // on constant subscripts remain, making them a viable candidate for hoisting.
802 if (a.length == 0) {
803 return -1;
804 }
805 // Loop that allows BCE on x[i].
806 int result = 0;
807 for (int i = lo; i < hi; i++) {
808 result += x[i];
809 if ((i % 10) != 0) {
810 // None of the subscripts inside a conditional are removed by dynamic bce,
811 // making them a candidate for deoptimization based on constant indices.
812 // Compiler should ensure the array loads are not subsequently hoisted
813 // "above" the deoptimization "barrier" on the bounds.
Aart Bika2106892016-05-04 14:00:55 -0700814 a[1][i] = 1;
815 a[2][i] = 2;
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000816 a[99][i] = 3;
817 }
818 }
819 return result;
820 }
821
822 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (before)
823 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
824 /// CHECK-DAG: ArrayGet loop:<<Loop>>
825 /// CHECK-DAG: ArrayGet loop:<<Loop>>
826 /// CHECK-DAG: ArrayGet loop:<<Loop>>
827 /// CHECK-DAG: ArrayGet loop:<<Loop>>
828 /// CHECK-DAG: ArrayGet loop:<<Loop>>
829 /// CHECK-DAG: ArrayGet loop:<<Loop>>
830 /// CHECK-DAG: ArrayGet loop:<<Loop>>
831 /// CHECK-DAG: ArrayGet loop:<<Loop>>
832 // For brevity, just test occurrence of at least one of each in the loop:
833 /// CHECK-DAG: NullCheck loop:<<Loop>>
834 /// CHECK-DAG: ArrayLength loop:<<Loop>>
835 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
836 //
837 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
838 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
839 /// CHECK-NOT: ArrayGet loop:<<Loop>>
840 //
841 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
842 /// CHECK-NOT: NullCheck loop:{{B\d+}}
843 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
844 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
845 //
846 /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
847 /// CHECK-DAG: Deoptimize loop:none
848 static int dynamicBCEAndConstantIndicesAllPrimTypes(int[] q,
849 boolean[] r,
850 byte[] s,
851 char[] t,
852 short[] u,
853 int[] v,
854 long[] w,
855 float[] x,
856 double[] y, int lo, int hi) {
857 int result = 0;
858 for (int i = lo; i < hi; i++) {
859 // All constant index array references can be hoisted out of the loop during BCE on q[i].
860 result += q[i] + (r[0] ? 1 : 0) + (int) s[0] + (int) t[0] + (int) u[0] + (int) v[0] +
861 (int) w[0] + (int) x[0] + (int) y[0];
862 }
863 return result;
864 }
865
866 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (before)
867 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
868 /// CHECK-DAG: NullCheck loop:<<Loop>>
869 /// CHECK-DAG: ArrayLength loop:<<Loop>>
870 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
871 /// CHECK-DAG: ArrayGet loop:<<Loop>>
872 /// CHECK-DAG: NullCheck loop:<<Loop>>
873 /// CHECK-DAG: ArrayLength loop:<<Loop>>
874 /// CHECK-DAG: BoundsCheck loop:<<Loop>>
875 //
876 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
877 /// CHECK-DAG: ArrayGet loop:<<Loop:B\d+>>
878 /// CHECK-DAG: Deoptimize loop:none
879 //
880 /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
881 /// CHECK-NOT: ArrayLength loop:{{B\d+}}
882 /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
883 static int dynamicBCEAndConstantIndexRefType(int[] q, Integer[] z, int lo, int hi) {
884 int result = 0;
885 for (int i = lo; i < hi; i++) {
886 // Similar to above, but now implicit call to intValue() may prevent hoisting
887 // z[0] itself during BCE on q[i]. Therefore, we just check BCE on q[i].
888 result += q[i] + z[0];
889 }
890 return result;
891 }
892
893 //
894 // Verifier.
895 //
896
897 public static void main(String[] args) {
898 // Set to run expensive tests for correctness too.
899 boolean HEAVY = false;
900
901 int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
902
Aart Bik0d345cf2016-03-16 10:49:38 -0700903 int[] a200 = new int[200];
904
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000905 // Sorting.
906 int[] sort = { 5, 4, 1, 9, 10, 2, 7, 6, 3, 8 };
907 bubble(sort);
908 for (int i = 0; i < 10; i++) {
909 expectEquals(sort[i], x[i]);
910 }
911
912 // Periodic adds (1, 3), one at the time.
913 expectEquals(0, periodicIdiom(-1));
914 for (int tc = 0; tc < 32; tc++) {
915 int expected = (tc >> 1) << 2;
Aart Bik7dc96932016-10-12 10:01:05 -0700916 if ((tc & 1) != 0) {
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000917 expected += 1;
Aart Bik7dc96932016-10-12 10:01:05 -0700918 }
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000919 expectEquals(expected, periodicIdiom(tc));
920 }
921
922 // Periodic adds (1, 3), one at the time.
923 expectEquals(0, periodicSequence2(-1));
924 for (int tc = 0; tc < 32; tc++) {
925 int expected = (tc >> 1) << 2;
Aart Bik7dc96932016-10-12 10:01:05 -0700926 if ((tc & 1) != 0) {
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000927 expected += 1;
Aart Bik7dc96932016-10-12 10:01:05 -0700928 }
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000929 expectEquals(expected, periodicSequence2(tc));
930 }
931
932 // Periodic adds (1, 3, 5, 7), all at once.
933 expectEquals(0, periodicSequence4(-1));
934 for (int tc = 0; tc < 32; tc++) {
935 expectEquals(tc * 16, periodicSequence4(tc));
936 }
937
Aart Bik7dc96932016-10-12 10:01:05 -0700938 // Periodic adds (1, 3), one at the time.
939 expectEquals(0, periodicXorSequence(-1));
940 for (int tc = 0; tc < 32; tc++) {
941 int expected = (tc >> 1) << 2;
942 if ((tc & 1) != 0) {
943 expected += 1;
944 }
945 expectEquals(expected, periodicXorSequence(tc));
946 }
947
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000948 // Large bounds.
949 expectEquals(55, justRightUp1());
950 expectEquals(55, justRightUp2());
951 expectEquals(55, justRightUp3());
952 expectEquals(55, justRightDown1());
953 expectEquals(55, justRightDown2());
954 expectEquals(55, justRightDown3());
Aart Bik52be7e72016-06-23 11:20:41 -0700955
956 // Large bounds OOB.
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +0000957 sResult = 0;
958 try {
959 justOOBUp();
960 } catch (ArrayIndexOutOfBoundsException e) {
961 sResult = 1;
962 }
963 expectEquals(1, sResult);
964 sResult = 0;
965 try {
966 justOOBDown();
967 } catch (ArrayIndexOutOfBoundsException e) {
968 sResult = 1;
969 }
970 expectEquals(1, sResult);
971
972 // Lower bound goes OOB.
973 sResult = 0;
974 try {
975 lowerOOB(x);
976 } catch (ArrayIndexOutOfBoundsException e) {
977 sResult += 1000;
978 }
979 expectEquals(1000, sResult);
980
981 // Upper bound goes OOB.
982 sResult = 0;
983 try {
984 upperOOB(x);
985 } catch (ArrayIndexOutOfBoundsException e) {
986 sResult += 1000;
987 }
988 expectEquals(1055, sResult);
989
990 // Do while up goes OOB.
991 sResult = 0;
992 try {
993 doWhileUpOOB();
994 } catch (ArrayIndexOutOfBoundsException e) {
995 sResult += 1000;
996 }
997 expectEquals(1055, sResult);
998
999 // Do while down goes OOB.
1000 sResult = 0;
1001 try {
1002 doWhileDownOOB();
1003 } catch (ArrayIndexOutOfBoundsException e) {
1004 sResult += 1000;
1005 }
1006 expectEquals(1055, sResult);
1007
Aart Bik52be7e72016-06-23 11:20:41 -07001008 // Triangular.
1009 sResult = 0;
1010 justRightTriangular1();
1011 expectEquals(1, sResult);
1012 if (HEAVY) {
1013 sResult = 0;
1014 justRightTriangular2();
1015 expectEquals(1, sResult);
1016 }
1017 sResult = 0;
1018 try {
1019 justOOBTriangular();
1020 } catch (ArrayIndexOutOfBoundsException e) {
1021 sResult += 1000;
1022 }
1023 expectEquals(1001, sResult);
1024
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001025 // Hidden OOB.
1026 sResult = 0;
1027 try {
1028 hiddenOOB1(10); // no OOB
1029 } catch (ArrayIndexOutOfBoundsException e) {
1030 sResult += 1000;
1031 }
1032 expectEquals(1, sResult);
1033 sResult = 0;
1034 try {
1035 hiddenOOB1(-2147483648); // OOB
1036 } catch (ArrayIndexOutOfBoundsException e) {
1037 sResult += 1000;
1038 }
1039 expectEquals(1001, sResult);
1040 sResult = 0;
1041 try {
1042 hiddenOOB2(1); // no OOB
1043 } catch (ArrayIndexOutOfBoundsException e) {
1044 sResult += 1000;
1045 }
1046 expectEquals(1, sResult);
Aart Bik52be7e72016-06-23 11:20:41 -07001047 sResult = 0;
1048 try {
1049 hiddenOOB3(-1); // no OOB
1050 } catch (ArrayIndexOutOfBoundsException e) {
1051 sResult += 1000;
1052 }
1053 expectEquals(11, sResult);
1054
1055 // Expensive hidden OOB test.
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001056 if (HEAVY) {
1057 sResult = 0;
1058 try {
1059 hiddenOOB2(2147483647); // OOB
1060 } catch (ArrayIndexOutOfBoundsException e) {
1061 sResult += 1000;
1062 }
1063 expectEquals(1002, sResult);
Aart Bik52be7e72016-06-23 11:20:41 -07001064 sResult = 0;
1065 try {
1066 hiddenOOB3(2147483647); // OOB
1067 } catch (ArrayIndexOutOfBoundsException e) {
1068 sResult += 1000;
1069 }
1070 expectEquals(1011, sResult);
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001071 }
Aart Bik52be7e72016-06-23 11:20:41 -07001072
1073 // More hidden OOB.
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001074 sResult = 0;
1075 try {
1076 hiddenInfiniteOOB();
1077 } catch (ArrayIndexOutOfBoundsException e) {
1078 sResult += 1000;
1079 }
1080 expectEquals(1011, sResult);
1081 sResult = 0;
1082 try {
1083 hiddenFiniteOOB();
1084 } catch (ArrayIndexOutOfBoundsException e) {
1085 sResult += 1000;
1086 }
1087 expectEquals(1111, sResult);
Aart Bik0d345cf2016-03-16 10:49:38 -07001088 sResult = 0;
1089 try {
1090 inductionOOB(a200);
1091 } catch (ArrayIndexOutOfBoundsException e) {
1092 sResult += 1000;
1093 }
1094 expectEquals(1000, sResult);
1095 for (int i = 0; i < 200; i++) {
1096 expectEquals(i < 128 ? i : 0, a200[i]);
1097 }
1098 sResult = 0;
1099 try {
1100 controlOOB(a200);
1101 } catch (ArrayIndexOutOfBoundsException e) {
1102 sResult += 1000;
1103 }
1104 expectEquals(1000, sResult);
1105 for (int i = 0; i < 200; i++) {
1106 expectEquals(i < 128 ? -i : 0, a200[i]);
1107 }
1108 sResult = 0;
1109 try {
1110 conversionOOB(a200);
1111 } catch (ArrayIndexOutOfBoundsException e) {
1112 sResult += 1000;
1113 }
1114 expectEquals(1000, sResult);
1115 for (int i = 0; i < 200; i++) {
1116 expectEquals(i < 128 ? i : 0, a200[i]);
1117 }
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001118
Aart Bik52be7e72016-06-23 11:20:41 -07001119 // No hoisting after BCE.
1120 expectEquals(110, doNotHoist(x));
1121
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001122 // Addition.
1123 {
1124 int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 };
1125 int[] a1 = add();
1126 for (int i = 0; i < 10; i++) {
1127 expectEquals(a1[i], e1[i]);
1128 }
1129 }
1130
1131 // Multiplication.
1132 {
1133 int[] e1 = { 7, 1, 2, 2, 1, 0, 2, 0, 0, 1 };
1134 int[] a1 = multiply1();
1135 for (int i = 0; i < 10; i++) {
1136 expectEquals(a1[i], e1[i]);
1137 }
1138 int[] e2 = { 1001, 0, 0, 1, 0, 0, 1, 0, 0, 1 };
1139 int[] a2 = multiply2();
1140 for (int i = 0; i < 10; i++) {
1141 expectEquals(a2[i], e2[i]);
1142 }
1143 }
1144
1145 // Dynamic BCE.
1146 sResult = 0;
1147 try {
1148 linearDynamicBCE1(x, -1, x.length);
1149 } catch (ArrayIndexOutOfBoundsException e) {
1150 sResult += 1000;
1151 }
1152 expectEquals(1000, sResult);
1153 sResult = 0;
1154 linearDynamicBCE1(x, 0, x.length);
1155 expectEquals(55, sResult);
1156 sResult = 0;
1157 try {
1158 linearDynamicBCE1(x, 0, x.length + 1);
1159 } catch (ArrayIndexOutOfBoundsException e) {
1160 sResult += 1000;
1161 }
1162 expectEquals(1055, sResult);
1163
1164 // Dynamic BCE with offset.
1165 sResult = 0;
1166 try {
1167 linearDynamicBCE2(x, 0, x.length, -1);
1168 } catch (ArrayIndexOutOfBoundsException e) {
1169 sResult += 1000;
1170 }
1171 expectEquals(1000, sResult);
1172 sResult = 0;
1173 linearDynamicBCE2(x, 0, x.length, 0);
1174 expectEquals(55, sResult);
1175 sResult = 0;
1176 try {
1177 linearDynamicBCE2(x, 0, x.length, 1);
1178 } catch (ArrayIndexOutOfBoundsException e) {
1179 sResult += 1000;
1180 }
1181 expectEquals(1054, sResult);
1182
1183 // Dynamic BCE candidates.
1184 expectEquals(55, wrapAroundDynamicBCE(x));
1185 expectEquals(15, periodicDynamicBCE(x));
1186 expectEquals(55, dynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1187 expectEquals(55, noDynamicBCEPossiblyInfiniteLoop(x, 0, 9));
1188 expectEquals(55, noDynamicBCEMixedInductionTypes(x, 0, 10));
1189 expectEquals(125, dynamicBCEConstantRange(x));
1190
1191 // Dynamic BCE combined with constant indices.
1192 int[][] a;
1193 a = new int[0][0];
1194 expectEquals(-1, dynamicBCEAndConstantIndices(x, a, 0, 10));
1195 a = new int[100][10];
1196 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1197 for (int i = 0; i < 10; i++) {
Aart Bika2106892016-05-04 14:00:55 -07001198 expectEquals((i % 10) != 0 ? 1 : 0, a[1][i]);
1199 expectEquals((i % 10) != 0 ? 2 : 0, a[2][i]);
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001200 expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
1201 }
Aart Bika2106892016-05-04 14:00:55 -07001202 a = new int[3][10];
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001203 sResult = 0;
1204 try {
1205 expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
1206 } catch (ArrayIndexOutOfBoundsException e) {
1207 sResult = 1;
1208 }
1209 expectEquals(1, sResult);
Aart Bika2106892016-05-04 14:00:55 -07001210 expectEquals(a[1][1], 1);
1211 expectEquals(a[2][1], 2);
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001212
1213 // Dynamic BCE combined with constant indices of all types.
1214 boolean[] x1 = { true };
1215 byte[] x2 = { 2 };
1216 char[] x3 = { 3 };
1217 short[] x4 = { 4 };
1218 int[] x5 = { 5 };
1219 long[] x6 = { 6 };
1220 float[] x7 = { 7 };
1221 double[] x8 = { 8 };
1222 expectEquals(415,
1223 dynamicBCEAndConstantIndicesAllPrimTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, 0, 10));
1224 Integer[] x9 = { 9 };
1225 expectEquals(145, dynamicBCEAndConstantIndexRefType(x, x9, 0, 10));
Aart Bik0d345cf2016-03-16 10:49:38 -07001226
1227 System.out.println("passed");
Nicolas Geoffraybef5eba2016-02-25 12:40:27 +00001228 }
1229
1230 private static void expectEquals(int expected, int result) {
1231 if (expected != result) {
1232 throw new Error("Expected: " + expected + ", found: " + result);
1233 }
1234 }
1235}