blob: 17039a3492b0489a34e6472df91b98eed8ce8cd5 [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
611 // Make sure this method is compiled with optimizing.
612 // CHECK-START: void Main.main(java.lang.String[]) register (after)
613 // CHECK: ParallelMove
614
Mingyao Yang0304e182015-01-30 16:41:29 -0800615 public static void main(String[] args) {
616 sieve(20);
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800617
618 int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
619 bubbleSort(array);
620 for (int i = 0; i < 8; i++) {
621 if (array[i] != i) {
622 System.out.println("bubble sort failed!");
623 }
624 }
625
626 array = new int[7];
627 pyramid1(array);
628 if (!isPyramid(array)) {
629 System.out.println("pyramid1 failed!");
630 }
631
632 array = new int[8];
633 pyramid2(array);
634 if (!isPyramid(array)) {
635 System.out.println("pyramid2 failed!");
636 }
637
638 java.util.Arrays.fill(array, -1);
639 pyramid3(array);
640 if (!isPyramid(array)) {
641 System.out.println("pyramid3 failed!");
642 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700643
644 // Make sure this value is kept after deoptimization.
645 int i = 1;
646 System.out.println(foo() + i);
Mingyao Yang0304e182015-01-30 16:41:29 -0800647 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700648
Mingyao Yang0304e182015-01-30 16:41:29 -0800649}