blob: f60fd162f2f913c97c6426ea2cce0bd572eb6ca6 [file] [log] [blame]
Mingyao Yang0304e182015-01-30 16:41:29 -08001/*
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
17public class Main {
18
19 // CHECK-START: int Main.sieve(int) BCE (before)
20 // CHECK: BoundsCheck
21 // CHECK: ArraySet
22 // CHECK: BoundsCheck
23 // CHECK: ArrayGet
24 // CHECK: BoundsCheck
25 // CHECK: ArraySet
26
27 // CHECK-START: int Main.sieve(int) BCE (after)
28 // CHECK-NOT: BoundsCheck
29 // CHECK: ArraySet
30 // CHECK-NOT: BoundsCheck
31 // CHECK: ArrayGet
32 // CHECK: BoundsCheck
33 // CHECK: ArraySet
34
35 static int sieve(int size) {
36 int primeCount = 0;
37 boolean[] flags = new boolean[size + 1];
38 for (int i = 1; i < size; i++) flags[i] = true; // Can eliminate.
39 for (int i = 2; i < size; i++) {
40 if (flags[i]) { // Can eliminate.
41 primeCount++;
42 for (int k = i + 1; k <= size; k += i)
43 flags[k - 1] = false; // Can't eliminate yet due to (k+i) may overflow.
44 }
45 }
46 return primeCount;
47 }
48
Mingyao Yang8c8bad82015-02-09 18:13:26 -080049
Mingyao Yang0304e182015-01-30 16:41:29 -080050 // CHECK-START: void Main.narrow(int[], int) BCE (before)
51 // CHECK: BoundsCheck
52 // CHECK: ArraySet
53 // CHECK: BoundsCheck
54 // CHECK: ArraySet
55 // CHECK: BoundsCheck
56 // CHECK: ArraySet
57
58 // CHECK-START: void Main.narrow(int[], int) BCE (after)
59 // CHECK-NOT: BoundsCheck
60 // CHECK: ArraySet
61 // CHECK-NOT: BoundsCheck
62 // CHECK: ArraySet
63 // CHECK: BoundsCheck
64 // CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -080065 // CHECK-NOT: BoundsCheck
66 // CHECK: ArraySet
67 // CHECK: BoundsCheck
68 // CHECK: ArraySet
Mingyao Yang0304e182015-01-30 16:41:29 -080069
Mingyao Yang8c8bad82015-02-09 18:13:26 -080070 static void narrow(int[] array, int offset) {
Mingyao Yang0304e182015-01-30 16:41:29 -080071 if (offset < 0) {
72 return;
73 }
74 if (offset < array.length) {
75 // offset is in range [0, array.length-1].
76 // Bounds check can be eliminated.
77 array[offset] = 1;
78
79 int biased_offset1 = offset + 1;
80 // biased_offset1 is in range [1, array.length].
81 if (biased_offset1 < array.length) {
82 // biased_offset1 is in range [1, array.length-1].
83 // Bounds check can be eliminated.
84 array[biased_offset1] = 1;
85 }
86
87 int biased_offset2 = offset + 0x70000000;
88 // biased_offset2 is in range [0x70000000, array.length-1+0x70000000].
89 // It may overflow and be negative.
90 if (biased_offset2 < array.length) {
91 // Even with this test, biased_offset2 can be negative so we can't
92 // eliminate this bounds check.
93 array[biased_offset2] = 1;
94 }
Mingyao Yang8c8bad82015-02-09 18:13:26 -080095
96 // offset_sub1 won't underflow since offset is no less than 0.
97 int offset_sub1 = offset - Integer.MAX_VALUE;
98 if (offset_sub1 >= 0) {
99 array[offset_sub1] = 1; // Bounds check can be eliminated.
100 }
101
102 // offset_sub2 can underflow.
103 int offset_sub2 = offset_sub1 - Integer.MAX_VALUE;
104 if (offset_sub2 >= 0) {
105 array[offset_sub2] = 1; // Bounds check can't be eliminated.
106 }
Mingyao Yang0304e182015-01-30 16:41:29 -0800107 }
108 }
109
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800110
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700111 // CHECK-START: void Main.constantIndexing1(int[]) BCE (before)
112 // CHECK: BoundsCheck
113 // CHECK: ArraySet
114 // CHECK: BoundsCheck
115 // CHECK: ArraySet
116
117 // CHECK-START: void Main.constantIndexing1(int[]) BCE (after)
118 // CHECK-NOT: Deoptimize
119 // CHECK: BoundsCheck
120 // CHECK: ArraySet
121 // CHECK-NOT: BoundsCheck
122 // CHECK: ArraySet
123
124 static void constantIndexing1(int[] array) {
125 array[5] = 1;
126 array[4] = 1;
127 }
128
129
130 // CHECK-START: void Main.constantIndexing2(int[]) BCE (before)
131 // CHECK: BoundsCheck
132 // CHECK: ArraySet
Andreas Gampe0ba62732015-03-24 02:39:46 +0000133 // CHECK: BoundsCheck
134 // CHECK: ArraySet
Mingyao Yange295e6e2015-03-07 06:37:59 -0800135 // CHECK: BoundsCheck
136 // CHECK: ArraySet
137 // CHECK: BoundsCheck
138 // CHECK: ArraySet
139
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700140 // CHECK-START: void Main.constantIndexing2(int[]) BCE (after)
141 // CHECK: LessThanOrEqual
142 // CHECK: Deoptimize
143 // CHECK-NOT: BoundsCheck
144 // CHECK: ArraySet
145 // CHECK-NOT: BoundsCheck
146 // CHECK: ArraySet
147 // CHECK-NOT: BoundsCheck
Mingyao Yange295e6e2015-03-07 06:37:59 -0800148 // CHECK: ArraySet
149 // CHECK-NOT: BoundsCheck
150 // CHECK: ArraySet
Andreas Gampe0ba62732015-03-24 02:39:46 +0000151 // CHECK: BoundsCheck
152 // CHECK: ArraySet
Mingyao Yange295e6e2015-03-07 06:37:59 -0800153
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700154 static void constantIndexing2(int[] array) {
155 array[1] = 1;
156 array[2] = 1;
157 array[3] = 1;
Mingyao Yange295e6e2015-03-07 06:37:59 -0800158 array[4] = 1;
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700159 array[-1] = 1;
Mingyao Yange295e6e2015-03-07 06:37:59 -0800160 }
161
162
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700163 // CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before)
164 // CHECK: BoundsCheck
165 // CHECK: ArrayGet
166 // CHECK: BoundsCheck
167 // CHECK: ArraySet
168 // CHECK: BoundsCheck
169 // CHECK: ArrayGet
170 // CHECK: BoundsCheck
171 // CHECK: ArraySet
172 // CHECK: BoundsCheck
173 // CHECK: ArrayGet
174 // CHECK: BoundsCheck
175 // CHECK: ArraySet
176 // CHECK: BoundsCheck
177 // CHECK: ArrayGet
178 // CHECK: BoundsCheck
179 // CHECK: ArraySet
180
181 // CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after)
182 // CHECK: LessThanOrEqual
183 // CHECK: Deoptimize
184 // CHECK-NOT: BoundsCheck
185 // CHECK: ArrayGet
186 // CHECK: LessThanOrEqual
187 // CHECK: Deoptimize
188 // CHECK-NOT: BoundsCheck
189 // CHECK: ArraySet
190 // CHECK-NOT: BoundsCheck
191 // CHECK: ArrayGet
192 // CHECK-NOT: BoundsCheck
193 // CHECK: ArraySet
194 // CHECK-NOT: BoundsCheck
195 // CHECK: ArrayGet
196 // CHECK-NOT: BoundsCheck
197 // CHECK: ArraySet
198 // CHECK-NOT: BoundsCheck
199 // CHECK: ArrayGet
200 // CHECK-NOT: BoundsCheck
201 // CHECK: ArraySet
202
203 static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) {
204 if (!copy) {
205 return array1;
206 }
207 array2[0] = array1[0];
208 array2[1] = array1[1];
209 array2[2] = array1[2];
210 array2[3] = array1[3];
211 return array2;
212 }
213
214
215 // CHECK-START: void Main.constantIndexing4(int[]) BCE (before)
216 // CHECK: BoundsCheck
217 // CHECK: ArraySet
218
219 // CHECK-START: void Main.constantIndexing4(int[]) BCE (after)
220 // CHECK-NOT: LessThanOrEqual
221 // CHECK: BoundsCheck
222 // CHECK: ArraySet
223
224 // There is only one array access. It's not beneficial
225 // to create a compare with deoptimization instruction.
226 static void constantIndexing4(int[] array) {
227 array[0] = 1;
228 }
229
230
231 // CHECK-START: void Main.constantIndexing5(int[]) BCE (before)
232 // CHECK: BoundsCheck
233 // CHECK: ArraySet
234 // CHECK: BoundsCheck
235 // CHECK: ArraySet
236
237 // CHECK-START: void Main.constantIndexing5(int[]) BCE (after)
238 // CHECK-NOT: Deoptimize
239 // CHECK: BoundsCheck
240 // CHECK: ArraySet
241 // CHECK: BoundsCheck
242 // CHECK: ArraySet
243
244 static void constantIndexing5(int[] array) {
245 // We don't apply the deoptimization for very large constant index
246 // since it's likely to be an anomaly and will throw AIOOBE.
247 array[Integer.MAX_VALUE - 1000] = 1;
248 array[Integer.MAX_VALUE - 999] = 1;
249 array[Integer.MAX_VALUE - 998] = 1;
250 }
251
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800252 // CHECK-START: void Main.loopPattern1(int[]) BCE (before)
253 // CHECK: BoundsCheck
254 // CHECK: ArraySet
255 // CHECK: BoundsCheck
256 // CHECK: ArraySet
257 // CHECK: BoundsCheck
258 // CHECK: ArraySet
259 // CHECK: BoundsCheck
260 // CHECK: ArraySet
261 // CHECK: BoundsCheck
262 // CHECK: ArraySet
263 // CHECK: BoundsCheck
264 // CHECK: ArraySet
265 // CHECK: BoundsCheck
266 // CHECK: ArraySet
267
268 // CHECK-START: void Main.loopPattern1(int[]) BCE (after)
269 // CHECK-NOT: BoundsCheck
270 // CHECK: ArraySet
271 // CHECK-NOT: BoundsCheck
272 // CHECK: ArraySet
273 // CHECK-NOT: BoundsCheck
274 // CHECK: ArraySet
275 // CHECK: BoundsCheck
276 // CHECK: ArraySet
277 // CHECK: BoundsCheck
278 // CHECK: ArraySet
279 // CHECK: BoundsCheck
280 // CHECK: ArraySet
281 // CHECK-NOT: BoundsCheck
282 // CHECK: ArraySet
283
284 static void loopPattern1(int[] array) {
285 for (int i = 0; i < array.length; i++) {
286 array[i] = 1; // Bounds check can be eliminated.
287 }
288
289 for (int i = 1; i < array.length; i++) {
290 array[i] = 1; // Bounds check can be eliminated.
291 }
292
293 for (int i = 1; i < array.length - 1; i++) {
294 array[i] = 1; // Bounds check can be eliminated.
295 }
296
297 for (int i = -1; i < array.length; i++) {
298 array[i] = 1; // Bounds check can't be eliminated.
299 }
300
301 for (int i = 0; i <= array.length; i++) {
302 array[i] = 1; // Bounds check can't be eliminated.
303 }
304
305 for (int i = 0; i < array.length; i += 2) {
306 // We don't have any assumption on max array length yet.
307 // Bounds check can't be eliminated due to overflow concern.
308 array[i] = 1;
309 }
310
311 for (int i = 1; i < array.length; i += 2) {
312 // Bounds check can be eliminated since i is odd so the last
313 // i that's less than array.length is at most (Integer.MAX_VALUE - 2).
314 array[i] = 1;
315 }
316 }
317
318
319 // CHECK-START: void Main.loopPattern2(int[]) BCE (before)
320 // CHECK: BoundsCheck
321 // CHECK: ArraySet
322 // CHECK: BoundsCheck
323 // CHECK: ArraySet
324 // CHECK: BoundsCheck
325 // CHECK: ArraySet
326 // CHECK: BoundsCheck
327 // CHECK: ArraySet
328 // CHECK: BoundsCheck
329 // CHECK: ArraySet
330 // CHECK: BoundsCheck
331 // CHECK: ArraySet
332
333 // CHECK-START: void Main.loopPattern2(int[]) BCE (after)
334 // CHECK-NOT: BoundsCheck
335 // CHECK: ArraySet
336 // CHECK-NOT: BoundsCheck
337 // CHECK: ArraySet
338 // CHECK-NOT: BoundsCheck
339 // CHECK: ArraySet
340 // CHECK: BoundsCheck
341 // CHECK: ArraySet
342 // CHECK: BoundsCheck
343 // CHECK: ArraySet
344 // CHECK-NOT: BoundsCheck
345 // CHECK: ArraySet
346
347 static void loopPattern2(int[] array) {
348 for (int i = array.length - 1; i >= 0; i--) {
349 array[i] = 1; // Bounds check can be eliminated.
350 }
351
352 for (int i = array.length; i > 0; i--) {
353 array[i - 1] = 1; // Bounds check can be eliminated.
354 }
355
356 for (int i = array.length - 1; i > 0; i--) {
357 array[i] = 1; // Bounds check can be eliminated.
358 }
359
360 for (int i = array.length; i >= 0; i--) {
361 array[i] = 1; // Bounds check can't be eliminated.
362 }
363
364 for (int i = array.length; i >= 0; i--) {
365 array[i - 1] = 1; // Bounds check can't be eliminated.
366 }
367
368 for (int i = array.length; i > 0; i -= 20) {
369 // For i >= 0, (i - 20 - 1) is guaranteed not to underflow.
370 array[i - 1] = 1; // Bounds check can be eliminated.
371 }
372 }
373
374
375 // CHECK-START: void Main.loopPattern3(int[]) BCE (before)
376 // CHECK: BoundsCheck
377 // CHECK: ArraySet
378
379 // CHECK-START: void Main.loopPattern3(int[]) BCE (after)
380 // CHECK: BoundsCheck
381 // CHECK: ArraySet
382
383 static void loopPattern3(int[] array) {
384 java.util.Random random = new java.util.Random();
385 for (int i = 0; ; i++) {
386 if (random.nextInt() % 1000 == 0 && i < array.length) {
387 // Can't eliminate the bound check since not every i++ is
388 // matched with a array length check, so there is some chance that i
389 // overflows and is negative.
390 array[i] = 1;
391 }
392 }
393 }
394
395
396 // CHECK-START: void Main.constantNewArray() BCE (before)
397 // CHECK: BoundsCheck
398 // CHECK: ArraySet
399 // CHECK: BoundsCheck
400 // CHECK: ArraySet
401 // CHECK: BoundsCheck
402 // CHECK: ArraySet
403 // CHECK: BoundsCheck
404 // CHECK: ArraySet
405 // CHECK: BoundsCheck
406 // CHECK: ArraySet
407
408 // CHECK-START: void Main.constantNewArray() BCE (after)
409 // CHECK-NOT: BoundsCheck
410 // CHECK: ArraySet
411 // CHECK: BoundsCheck
412 // CHECK: ArraySet
413 // CHECK-NOT: BoundsCheck
414 // CHECK: ArraySet
415 // CHECK-NOT: BoundsCheck
416 // CHECK: ArraySet
417 // CHECK: BoundsCheck
418 // CHECK: ArraySet
419
420 static void constantNewArray() {
421 int[] array = new int[10];
422 for (int i = 0; i < 10; i++) {
423 array[i] = 1; // Bounds check can be eliminated.
424 }
425
426 for (int i = 0; i <= 10; i++) {
427 array[i] = 1; // Bounds check can't be eliminated.
428 }
429
430 array[0] = 1; // Bounds check can be eliminated.
431 array[9] = 1; // Bounds check can be eliminated.
432 array[10] = 1; // Bounds check can't be eliminated.
433 }
434
Mingyao Yang4559f002015-02-27 14:43:53 -0800435
436 static byte readData() {
437 return 1;
438 }
439
440 // CHECK-START: void Main.circularBufferProducer() BCE (before)
441 // CHECK: BoundsCheck
442 // CHECK: ArraySet
443
444 // CHECK-START: void Main.circularBufferProducer() BCE (after)
445 // CHECK-NOT: BoundsCheck
446 // CHECK: ArraySet
447
448 static void circularBufferProducer() {
449 byte[] array = new byte[4096];
450 int i = 0;
451 while (true) {
452 array[i & (array.length - 1)] = readData();
453 i++;
454 }
455 }
456
457
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800458 // CHECK-START: void Main.pyramid1(int[]) BCE (before)
459 // CHECK: BoundsCheck
460 // CHECK: ArraySet
461 // CHECK: BoundsCheck
462 // CHECK: ArraySet
463
464 // CHECK-START: void Main.pyramid1(int[]) BCE (after)
465 // CHECK-NOT: BoundsCheck
466 // CHECK: ArraySet
467 // CHECK-NOT: BoundsCheck
468 // CHECK: ArraySet
469
470 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
471 static void pyramid1(int[] array) {
472 for (int i = 0; i < (array.length + 1) / 2; i++) {
473 array[i] = i;
474 array[array.length - 1 - i] = i;
475 }
476 }
477
478
479 // CHECK-START: void Main.pyramid2(int[]) BCE (before)
480 // CHECK: BoundsCheck
481 // CHECK: ArraySet
482 // CHECK: BoundsCheck
483 // CHECK: ArraySet
484
485 // CHECK-START: void Main.pyramid2(int[]) BCE (after)
486 // CHECK-NOT: BoundsCheck
487 // CHECK: ArraySet
488 // CHECK-NOT: BoundsCheck
489 // CHECK: ArraySet
490
491 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
492 static void pyramid2(int[] array) {
493 for (int i = 0; i < (array.length + 1) >> 1; i++) {
494 array[i] = i;
495 array[array.length - 1 - i] = i;
496 }
497 }
498
499
500 // CHECK-START: void Main.pyramid3(int[]) BCE (before)
501 // CHECK: BoundsCheck
502 // CHECK: ArraySet
503 // CHECK: BoundsCheck
504 // CHECK: ArraySet
505
506 // CHECK-START: void Main.pyramid3(int[]) BCE (after)
507 // CHECK-NOT: BoundsCheck
508 // CHECK: ArraySet
509 // CHECK-NOT: BoundsCheck
510 // CHECK: ArraySet
511
512 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
513 static void pyramid3(int[] array) {
514 for (int i = 0; i < (array.length + 1) >>> 1; i++) {
515 array[i] = i;
516 array[array.length - 1 - i] = i;
517 }
518 }
519
520
Mingyao Yang57e04752015-02-09 18:13:26 -0800521 // CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
522 // CHECK: BoundsCheck
523 // CHECK: ArrayGet
524 // CHECK: BoundsCheck
525 // CHECK: ArrayGet
526
527 // CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
528 // CHECK-NOT: BoundsCheck
529 // CHECK: ArrayGet
530 // CHECK-NOT: BoundsCheck
531 // CHECK: ArrayGet
532
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800533 static boolean isPyramid(int[] array) {
534 int i = 0;
535 int j = array.length - 1;
536 while (i <= j) {
537 if (array[i] != i) {
538 return false;
539 }
540 if (array[j] != i) {
541 return false;
542 }
543 i++; j--;
544 }
545 return true;
546 }
547
548
549 // CHECK-START: void Main.bubbleSort(int[]) GVN (before)
550 // CHECK: BoundsCheck
551 // CHECK: ArrayGet
552 // CHECK: BoundsCheck
553 // CHECK: ArrayGet
554 // CHECK: BoundsCheck
555 // CHECK: ArrayGet
556 // CHECK: BoundsCheck
557 // CHECK: ArrayGet
558 // CHECK: BoundsCheck
559 // CHECK: ArraySet
560 // CHECK: BoundsCheck
561 // CHECK: ArraySet
562
563 // CHECK-START: void Main.bubbleSort(int[]) GVN (after)
564 // CHECK: BoundsCheck
565 // CHECK: ArrayGet
566 // CHECK: BoundsCheck
567 // CHECK: ArrayGet
568 // CHECK-NOT: ArrayGet
569 // CHECK-NOT: ArrayGet
570 // CHECK-NOT: BoundsCheck
571 // CHECK: ArraySet
572 // CHECK-NOT: BoundsCheck
573 // CHECK: ArraySet
574
575 // CHECK-START: void Main.bubbleSort(int[]) BCE (after)
576 // CHECK-NOT: BoundsCheck
577 // CHECK: ArrayGet
578 // CHECK-NOT: BoundsCheck
579 // CHECK: ArrayGet
580 // CHECK-NOT: ArrayGet
581 // CHECK-NOT: ArrayGet
582 // CHECK-NOT: BoundsCheck
583 // CHECK: ArraySet
584 // CHECK-NOT: BoundsCheck
585 // CHECK: ArraySet
586
587 static void bubbleSort(int[] array) {
588 for (int i = 0; i < array.length - 1; i++) {
589 for (int j = 0; j < array.length - i - 1; j++) {
590 if (array[j] > array[j + 1]) {
591 int temp = array[j + 1];
592 array[j + 1] = array[j];
593 array[j] = temp;
594 }
595 }
596 }
597 }
598
599
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700600 static int foo() {
601 try {
602 // This will cause AIOOBE.
603 constantIndexing2(new int[3]);
604 } catch (ArrayIndexOutOfBoundsException e) {
605 return 99;
606 }
607 return 0;
608 }
609
610
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700611 int sum;
612
613 // CHECK-START: void Main.foo1(int[], int, int) BCE (before)
614 // CHECK: BoundsCheck
615 // CHECK: ArraySet
616 // CHECK-NOT: BoundsCheck
617 // CHECK: ArrayGet
618
619 // CHECK-START: void Main.foo1(int[], int, int) BCE (after)
620 // CHECK: Deoptimize
621 // CHECK: Deoptimize
622 // CHECK: Deoptimize
623 // CHECK-NOT: Deoptimize
624 // CHECK: Phi
625 // CHECK-NOT: BoundsCheck
626 // CHECK: ArraySet
627 // CHECK-NOT: BoundsCheck
628 // CHECK: ArrayGet
629
630 void foo1(int[] array, int start, int end) {
631 // Three HDeoptimize will be added. One for
632 // start >= 0, one for end <= array.length,
633 // and one for null check on array (to hoist null
634 // check and array.length out of loop).
635 for (int i = start ; i < end; i++) {
636 array[i] = 1;
637 sum += array[i];
638 }
639 }
640
641
642 // CHECK-START: void Main.foo2(int[], int, int) BCE (before)
643 // CHECK: BoundsCheck
644 // CHECK: ArraySet
645 // CHECK-NOT: BoundsCheck
646 // CHECK: ArrayGet
647
648 // CHECK-START: void Main.foo2(int[], int, int) BCE (after)
649 // CHECK: Deoptimize
650 // CHECK: Deoptimize
651 // CHECK: Deoptimize
652 // CHECK-NOT: Deoptimize
653 // CHECK: Phi
654 // CHECK-NOT: BoundsCheck
655 // CHECK: ArraySet
656 // CHECK-NOT: BoundsCheck
657 // CHECK: ArrayGet
658
659 void foo2(int[] array, int start, int end) {
660 // Three HDeoptimize will be added. One for
661 // start >= 0, one for end <= array.length,
662 // and one for null check on array (to hoist null
663 // check and array.length out of loop).
664 for (int i = start ; i <= end; i++) {
665 array[i] = 1;
666 sum += array[i];
667 }
668 }
669
670
671 // CHECK-START: void Main.foo3(int[], int) BCE (before)
672 // CHECK: BoundsCheck
673 // CHECK: ArraySet
674 // CHECK-NOT: BoundsCheck
675 // CHECK: ArrayGet
676
677 // CHECK-START: void Main.foo3(int[], int) BCE (after)
678 // CHECK: Deoptimize
679 // CHECK: Deoptimize
680 // CHECK-NOT: Deoptimize
681 // CHECK: Phi
682 // CHECK-NOT: BoundsCheck
683 // CHECK: ArraySet
684 // CHECK-NOT: BoundsCheck
685 // CHECK: ArrayGet
686
687 void foo3(int[] array, int end) {
688 // Two HDeoptimize will be added. One for end < array.length,
689 // and one for null check on array (to hoist null check
690 // and array.length out of loop).
691 for (int i = 3 ; i <= end; i++) {
692 array[i] = 1;
693 sum += array[i];
694 }
695 }
696
697 // CHECK-START: void Main.foo4(int[], int) BCE (before)
698 // CHECK: BoundsCheck
699 // CHECK: ArraySet
700 // CHECK-NOT: BoundsCheck
701 // CHECK: ArrayGet
702
703 // CHECK-START: void Main.foo4(int[], int) BCE (after)
704 // CHECK: Deoptimize
705 // CHECK: Deoptimize
706 // CHECK-NOT: Deoptimize
707 // CHECK: Phi
708 // CHECK-NOT: BoundsCheck
709 // CHECK: ArraySet
710 // CHECK-NOT: BoundsCheck
711 // CHECK: ArrayGet
712
713 void foo4(int[] array, int end) {
714 // Two HDeoptimize will be added. One for end <= array.length,
715 // and one for null check on array (to hoist null check
716 // and array.length out of loop).
717 for (int i = end ; i > 0; i--) {
718 array[i - 1] = 1;
719 sum += array[i - 1];
720 }
721 }
722
723
724 // CHECK-START: void Main.foo5(int[], int) BCE (before)
725 // CHECK: BoundsCheck
726 // CHECK: ArraySet
727 // CHECK: BoundsCheck
728 // CHECK: ArrayGet
729 // CHECK: BoundsCheck
730 // CHECK: ArrayGet
731 // CHECK: BoundsCheck
732 // CHECK: ArrayGet
733
734 // CHECK-START: void Main.foo5(int[], int) BCE (after)
735 // CHECK-NOT: BoundsCheck
736 // CHECK: ArraySet
737 // CHECK: Deoptimize
738 // CHECK-NOT: Deoptimize
739 // CHECK: Phi
740 // CHECK-NOT: BoundsCheck
741 // CHECK: ArrayGet
742 // CHECK-NOT: BoundsCheck
743 // CHECK: ArrayGet
744 // CHECK-NOT: BoundsCheck
745 // CHECK: ArrayGet
746
747 void foo5(int[] array, int end) {
748 // Bounds check in this loop can be eliminated without deoptimization.
749 for (int i = array.length - 1 ; i >= 0; i--) {
750 array[i] = 1;
751 }
752 // One HDeoptimize will be added.
753 // It's for (end - 2 <= array.length - 2).
754 for (int i = end - 2 ; i > 0; i--) {
755 sum += array[i - 1];
756 sum += array[i];
757 sum += array[i + 1];
758 }
759 }
760
761
762 // CHECK-START: void Main.foo6(int[], int, int) BCE (before)
763 // CHECK: BoundsCheck
764 // CHECK: ArrayGet
765 // CHECK: BoundsCheck
766 // CHECK: ArrayGet
767 // CHECK: BoundsCheck
768 // CHECK: ArrayGet
769 // CHECK: BoundsCheck
770 // CHECK: ArrayGet
771 // CHECK: BoundsCheck
772 // CHECK: ArrayGet
773 // CHECK-NOT: BoundsCheck
774 // CHECK: ArraySet
775
776 // CHECK-START: void Main.foo6(int[], int, int) BCE (after)
777 // CHECK: Deoptimize
778 // CHECK: Deoptimize
779 // CHECK: Deoptimize
780 // CHECK-NOT: Deoptimize
781 // CHECK: Phi
782 // CHECK-NOT: BoundsCheck
783 // CHECK: ArrayGet
784 // CHECK-NOT: BoundsCheck
785 // CHECK: ArrayGet
786 // CHECK-NOT: BoundsCheck
787 // CHECK: ArrayGet
788 // CHECK-NOT: BoundsCheck
789 // CHECK: ArrayGet
790 // CHECK-NOT: BoundsCheck
791 // CHECK: ArrayGet
792 // CHECK-NOT: BoundsCheck
793 // CHECK: ArraySet
794
795 void foo6(int[] array, int start, int end) {
796 // Three HDeoptimize will be added. One for
797 // start >= 2, one for end <= array.length - 3,
798 // and one for null check on array (to hoist null
799 // check and array.length out of loop).
800 for (int i = end; i >= start; i--) {
801 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5;
802 }
803 }
804
805
806 // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
807 // CHECK: BoundsCheck
808 // CHECK: ArrayGet
809 // CHECK: BoundsCheck
810 // CHECK: ArrayGet
811
812 // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
813 // CHECK: Deoptimize
814 // CHECK: Deoptimize
815 // CHECK: Deoptimize
816 // CHECK-NOT: Deoptimize
817 // CHECK: Phi
818 // CHECK: BoundsCheck
819 // CHECK: ArrayGet
820 // CHECK-NOT: BoundsCheck
821 // CHECK: ArrayGet
822
823 void foo7(int[] array, int start, int end, boolean lowEnd) {
824 // Three HDeoptimize will be added. One for
825 // start >= 0, one for end <= array.length,
826 // and one for null check on array (to hoist null
827 // check and array.length out of loop).
828 for (int i = start ; i < end; i++) {
829 if (lowEnd) {
830 // This array access isn't certain. So we don't
831 // use +1000 offset in decision making for deoptimization
832 // conditions.
833 sum += array[i + 1000];
834 }
835 sum += array[i];
836 }
837 }
838
839
840 static void testUnknownBounds() {
841 boolean caught = false;
842 Main main = new Main();
843 main.foo1(new int[10], 0, 10);
844 if (main.sum != 10) {
845 System.out.println("foo1 failed!");
846 }
847
848 caught = false;
849 main = new Main();
850 try {
851 main.foo1(new int[10], 0, 11);
852 } catch (ArrayIndexOutOfBoundsException e) {
853 caught = true;
854 }
855 if (!caught || main.sum != 10) {
856 System.out.println("foo1 exception failed!");
857 }
858
859 main = new Main();
860 main.foo2(new int[10], 0, 9);
861 if (main.sum != 10) {
862 System.out.println("foo2 failed!");
863 }
864
865 caught = false;
866 main = new Main();
867 try {
868 main.foo2(new int[10], 0, 10);
869 } catch (ArrayIndexOutOfBoundsException e) {
870 caught = true;
871 }
872 if (!caught || main.sum != 10) {
873 System.out.println("foo2 exception failed!");
874 }
875
876 main = new Main();
877 main.foo3(new int[10], 9);
878 if (main.sum != 7) {
879 System.out.println("foo3 failed!");
880 }
881
882 caught = false;
883 main = new Main();
884 try {
885 main.foo3(new int[10], 10);
886 } catch (ArrayIndexOutOfBoundsException e) {
887 caught = true;
888 }
889 if (!caught || main.sum != 7) {
890 System.out.println("foo3 exception failed!");
891 }
892
893 main = new Main();
894 main.foo4(new int[10], 10);
895 if (main.sum != 10) {
896 System.out.println("foo4 failed!");
897 }
898
899 caught = false;
900 main = new Main();
901 try {
902 main.foo4(new int[10], 11);
903 } catch (ArrayIndexOutOfBoundsException e) {
904 caught = true;
905 }
906 if (!caught || main.sum != 0) {
907 System.out.println("foo4 exception failed!");
908 }
909
910 main = new Main();
911 main.foo5(new int[10], 10);
912 if (main.sum != 24) {
913 System.out.println("foo5 failed!");
914 }
915
916 caught = false;
917 main = new Main();
918 try {
919 main.foo5(new int[10], 11);
920 } catch (ArrayIndexOutOfBoundsException e) {
921 caught = true;
922 }
923 if (!caught || main.sum != 2) {
924 System.out.println("foo5 exception failed!");
925 }
926
927 main = new Main();
928 main.foo6(new int[10], 2, 7);
929
930 caught = false;
931 main = new Main();
932 try {
933 main.foo6(new int[10], 2, 8);
934 } catch (ArrayIndexOutOfBoundsException e) {
935 caught = true;
936 }
937 if (!caught) {
938 System.out.println("foo6 exception failed!");
939 }
940
941 caught = false;
942 main = new Main();
943 try {
944 main.foo6(new int[10], 1, 7);
945 } catch (ArrayIndexOutOfBoundsException e) {
946 caught = true;
947 }
948 if (!caught) {
949 System.out.println("foo6 exception failed!");
950 }
951
952 }
953
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700954 // Make sure this method is compiled with optimizing.
955 // CHECK-START: void Main.main(java.lang.String[]) register (after)
956 // CHECK: ParallelMove
957
Mingyao Yang0304e182015-01-30 16:41:29 -0800958 public static void main(String[] args) {
959 sieve(20);
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800960
961 int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
962 bubbleSort(array);
963 for (int i = 0; i < 8; i++) {
964 if (array[i] != i) {
965 System.out.println("bubble sort failed!");
966 }
967 }
968
969 array = new int[7];
970 pyramid1(array);
971 if (!isPyramid(array)) {
972 System.out.println("pyramid1 failed!");
973 }
974
975 array = new int[8];
976 pyramid2(array);
977 if (!isPyramid(array)) {
978 System.out.println("pyramid2 failed!");
979 }
980
981 java.util.Arrays.fill(array, -1);
982 pyramid3(array);
983 if (!isPyramid(array)) {
984 System.out.println("pyramid3 failed!");
985 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700986
987 // Make sure this value is kept after deoptimization.
988 int i = 1;
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700989 if (foo() + i != 100) {
990 System.out.println("foo failed!");
991 };
992
993 testUnknownBounds();
Mingyao Yang0304e182015-01-30 16:41:29 -0800994 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700995
Mingyao Yang0304e182015-01-30 16:41:29 -0800996}