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