blob: 8960df896be27ca5ae07ab73305448851f323871 [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
David Brazdila06d66a2015-05-28 11:14:54 +010019 /// 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
Mingyao Yang0304e182015-01-30 16:41:29 -080026
David Brazdila06d66a2015-05-28 11:14:54 +010027 /// 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
Mingyao Yang0304e182015-01-30 16:41:29 -080034
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
David Brazdila06d66a2015-05-28 11:14:54 +010050 /// 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
Mingyao Yang0304e182015-01-30 16:41:29 -080057
David Brazdila06d66a2015-05-28 11:14:54 +010058 /// 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
65 /// 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
David Brazdila06d66a2015-05-28 11:14:54 +0100111 /// CHECK-START: void Main.constantIndexing1(int[]) BCE (before)
112 /// CHECK: BoundsCheck
113 /// CHECK: ArraySet
114 /// CHECK: BoundsCheck
115 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700116
David Brazdila06d66a2015-05-28 11:14:54 +0100117 /// 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
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700123
124 static void constantIndexing1(int[] array) {
125 array[5] = 1;
126 array[4] = 1;
127 }
128
129
David Brazdila06d66a2015-05-28 11:14:54 +0100130 /// CHECK-START: void Main.constantIndexing2(int[]) BCE (before)
131 /// CHECK: BoundsCheck
132 /// CHECK: ArraySet
133 /// CHECK: BoundsCheck
134 /// CHECK: ArraySet
135 /// CHECK: BoundsCheck
136 /// CHECK: ArraySet
137 /// CHECK: BoundsCheck
138 /// CHECK: ArraySet
Mingyao Yange295e6e2015-03-07 06:37:59 -0800139
David Brazdila06d66a2015-05-28 11:14:54 +0100140 /// 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
148 /// CHECK: ArraySet
149 /// CHECK-NOT: BoundsCheck
150 /// CHECK: ArraySet
151 /// 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
David Brazdila06d66a2015-05-28 11:14:54 +0100163 /// 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
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700180
David Brazdila06d66a2015-05-28 11:14:54 +0100181 /// 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
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700202
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
David Brazdila06d66a2015-05-28 11:14:54 +0100215 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before)
216 /// CHECK: BoundsCheck
217 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700218
David Brazdila06d66a2015-05-28 11:14:54 +0100219 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after)
220 /// CHECK-NOT: LessThanOrEqual
221 /// CHECK: BoundsCheck
222 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700223
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
David Brazdila06d66a2015-05-28 11:14:54 +0100231 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before)
232 /// CHECK: BoundsCheck
233 /// CHECK: ArraySet
234 /// CHECK: BoundsCheck
235 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700236
David Brazdila06d66a2015-05-28 11:14:54 +0100237 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after)
238 /// CHECK-NOT: Deoptimize
239 /// CHECK: BoundsCheck
240 /// CHECK: ArraySet
241 /// CHECK: BoundsCheck
242 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700243
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
David Brazdila06d66a2015-05-28 11:14:54 +0100252 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800267
David Brazdila06d66a2015-05-28 11:14:54 +0100268 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800283
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
David Brazdila06d66a2015-05-28 11:14:54 +0100319 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800332
David Brazdila06d66a2015-05-28 11:14:54 +0100333 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800346
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
David Brazdila06d66a2015-05-28 11:14:54 +0100375 /// CHECK-START: void Main.loopPattern3(int[]) BCE (before)
376 /// CHECK: BoundsCheck
377 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800378
David Brazdila06d66a2015-05-28 11:14:54 +0100379 /// CHECK-START: void Main.loopPattern3(int[]) BCE (after)
380 /// CHECK: BoundsCheck
381 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800382
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
David Brazdila06d66a2015-05-28 11:14:54 +0100396 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800407
David Brazdila06d66a2015-05-28 11:14:54 +0100408 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800419
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
David Brazdila06d66a2015-05-28 11:14:54 +0100440 /// CHECK-START: void Main.circularBufferProducer() BCE (before)
441 /// CHECK: BoundsCheck
442 /// CHECK: ArraySet
Mingyao Yang4559f002015-02-27 14:43:53 -0800443
David Brazdila06d66a2015-05-28 11:14:54 +0100444 /// CHECK-START: void Main.circularBufferProducer() BCE (after)
445 /// CHECK-NOT: BoundsCheck
446 /// CHECK: ArraySet
Mingyao Yang4559f002015-02-27 14:43:53 -0800447
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
David Brazdila06d66a2015-05-28 11:14:54 +0100458 /// CHECK-START: void Main.pyramid1(int[]) BCE (before)
459 /// CHECK: BoundsCheck
460 /// CHECK: ArraySet
461 /// CHECK: BoundsCheck
462 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800463
David Brazdila06d66a2015-05-28 11:14:54 +0100464 /// CHECK-START: void Main.pyramid1(int[]) BCE (after)
465 /// CHECK-NOT: BoundsCheck
466 /// CHECK: ArraySet
467 /// CHECK-NOT: BoundsCheck
468 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800469
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
David Brazdila06d66a2015-05-28 11:14:54 +0100479 /// CHECK-START: void Main.pyramid2(int[]) BCE (before)
480 /// CHECK: BoundsCheck
481 /// CHECK: ArraySet
482 /// CHECK: BoundsCheck
483 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800484
David Brazdila06d66a2015-05-28 11:14:54 +0100485 /// CHECK-START: void Main.pyramid2(int[]) BCE (after)
486 /// CHECK-NOT: BoundsCheck
487 /// CHECK: ArraySet
488 /// CHECK-NOT: BoundsCheck
489 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800490
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
David Brazdila06d66a2015-05-28 11:14:54 +0100500 /// CHECK-START: void Main.pyramid3(int[]) BCE (before)
501 /// CHECK: BoundsCheck
502 /// CHECK: ArraySet
503 /// CHECK: BoundsCheck
504 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800505
David Brazdila06d66a2015-05-28 11:14:54 +0100506 /// CHECK-START: void Main.pyramid3(int[]) BCE (after)
507 /// CHECK-NOT: BoundsCheck
508 /// CHECK: ArraySet
509 /// CHECK-NOT: BoundsCheck
510 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800511
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
David Brazdila06d66a2015-05-28 11:14:54 +0100521 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
522 /// CHECK: BoundsCheck
523 /// CHECK: ArrayGet
524 /// CHECK: BoundsCheck
525 /// CHECK: ArrayGet
Mingyao Yang57e04752015-02-09 18:13:26 -0800526
David Brazdila06d66a2015-05-28 11:14:54 +0100527 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
528 /// CHECK-NOT: BoundsCheck
529 /// CHECK: ArrayGet
530 /// CHECK-NOT: BoundsCheck
531 /// CHECK: ArrayGet
Mingyao Yang57e04752015-02-09 18:13:26 -0800532
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
David Brazdila06d66a2015-05-28 11:14:54 +0100549 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800562
David Brazdila06d66a2015-05-28 11:14:54 +0100563 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800574
David Brazdila06d66a2015-05-28 11:14:54 +0100575 /// 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
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800586
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
David Brazdila06d66a2015-05-28 11:14:54 +0100613 /// CHECK-START: void Main.foo1(int[], int, int) BCE (before)
614 /// CHECK: BoundsCheck
615 /// CHECK: ArraySet
616 /// CHECK-NOT: BoundsCheck
617 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700618
David Brazdila06d66a2015-05-28 11:14:54 +0100619 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700629
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
David Brazdila06d66a2015-05-28 11:14:54 +0100642 /// CHECK-START: void Main.foo2(int[], int, int) BCE (before)
643 /// CHECK: BoundsCheck
644 /// CHECK: ArraySet
645 /// CHECK-NOT: BoundsCheck
646 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700647
David Brazdila06d66a2015-05-28 11:14:54 +0100648 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700658
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
David Brazdila06d66a2015-05-28 11:14:54 +0100671 /// CHECK-START: void Main.foo3(int[], int) BCE (before)
672 /// CHECK: BoundsCheck
673 /// CHECK: ArraySet
674 /// CHECK-NOT: BoundsCheck
675 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700676
David Brazdila06d66a2015-05-28 11:14:54 +0100677 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700686
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
David Brazdila06d66a2015-05-28 11:14:54 +0100697 /// CHECK-START: void Main.foo4(int[], int) BCE (before)
698 /// CHECK: BoundsCheck
699 /// CHECK: ArraySet
700 /// CHECK-NOT: BoundsCheck
701 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700702
David Brazdila06d66a2015-05-28 11:14:54 +0100703 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700712
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
David Brazdila06d66a2015-05-28 11:14:54 +0100724 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700733
David Brazdila06d66a2015-05-28 11:14:54 +0100734 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700746
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
David Brazdila06d66a2015-05-28 11:14:54 +0100762 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700775
David Brazdila06d66a2015-05-28 11:14:54 +0100776 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700794
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
David Brazdila06d66a2015-05-28 11:14:54 +0100806 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
807 /// CHECK: BoundsCheck
808 /// CHECK: ArrayGet
809 /// CHECK: BoundsCheck
810 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700811
David Brazdila06d66a2015-05-28 11:14:54 +0100812 /// 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
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700822
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
David Brazdila06d66a2015-05-28 11:14:54 +0100840 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
841 /// CHECK: BoundsCheck
842 /// CHECK: ArraySet
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700843
David Brazdila06d66a2015-05-28 11:14:54 +0100844 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
845 /// CHECK-NOT: Deoptimize
846 /// CHECK: BoundsCheck
847 /// CHECK: ArraySet
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700848
849 void partialLooping(int[] array, int start, int end) {
850 // This loop doesn't cover the full range of [start, end) so
851 // adding deoptimization is too aggressive, since end can be
852 // greater than array.length but the loop is never going to work on
853 // more than 2 elements.
854 for (int i = start; i < end; i++) {
855 if (i == 2) {
856 return;
857 }
858 array[i] = 1;
859 }
860 }
861
862
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700863 static void testUnknownBounds() {
864 boolean caught = false;
865 Main main = new Main();
866 main.foo1(new int[10], 0, 10);
867 if (main.sum != 10) {
868 System.out.println("foo1 failed!");
869 }
870
871 caught = false;
872 main = new Main();
873 try {
874 main.foo1(new int[10], 0, 11);
875 } catch (ArrayIndexOutOfBoundsException e) {
876 caught = true;
877 }
878 if (!caught || main.sum != 10) {
879 System.out.println("foo1 exception failed!");
880 }
881
882 main = new Main();
883 main.foo2(new int[10], 0, 9);
884 if (main.sum != 10) {
885 System.out.println("foo2 failed!");
886 }
887
888 caught = false;
889 main = new Main();
890 try {
891 main.foo2(new int[10], 0, 10);
892 } catch (ArrayIndexOutOfBoundsException e) {
893 caught = true;
894 }
895 if (!caught || main.sum != 10) {
896 System.out.println("foo2 exception failed!");
897 }
898
899 main = new Main();
900 main.foo3(new int[10], 9);
901 if (main.sum != 7) {
902 System.out.println("foo3 failed!");
903 }
904
905 caught = false;
906 main = new Main();
907 try {
908 main.foo3(new int[10], 10);
909 } catch (ArrayIndexOutOfBoundsException e) {
910 caught = true;
911 }
912 if (!caught || main.sum != 7) {
913 System.out.println("foo3 exception failed!");
914 }
915
916 main = new Main();
917 main.foo4(new int[10], 10);
918 if (main.sum != 10) {
919 System.out.println("foo4 failed!");
920 }
921
922 caught = false;
923 main = new Main();
924 try {
925 main.foo4(new int[10], 11);
926 } catch (ArrayIndexOutOfBoundsException e) {
927 caught = true;
928 }
929 if (!caught || main.sum != 0) {
930 System.out.println("foo4 exception failed!");
931 }
932
933 main = new Main();
934 main.foo5(new int[10], 10);
935 if (main.sum != 24) {
936 System.out.println("foo5 failed!");
937 }
938
939 caught = false;
940 main = new Main();
941 try {
942 main.foo5(new int[10], 11);
943 } catch (ArrayIndexOutOfBoundsException e) {
944 caught = true;
945 }
946 if (!caught || main.sum != 2) {
947 System.out.println("foo5 exception failed!");
948 }
949
950 main = new Main();
951 main.foo6(new int[10], 2, 7);
952
Mingyao Yang9d750ef2015-04-26 18:15:30 -0700953 main = new Main();
954 int[] array = new int[4];
955 main.partialLooping(new int[3], 0, 4);
956 if ((array[0] != 1) && (array[1] != 1) &&
957 (array[2] != 0) && (array[3] != 0)) {
958 System.out.println("partialLooping failed!");
959 }
960
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700961 caught = false;
962 main = new Main();
963 try {
964 main.foo6(new int[10], 2, 8);
965 } catch (ArrayIndexOutOfBoundsException e) {
966 caught = true;
967 }
968 if (!caught) {
969 System.out.println("foo6 exception failed!");
970 }
971
972 caught = false;
973 main = new Main();
974 try {
975 main.foo6(new int[10], 1, 7);
976 } catch (ArrayIndexOutOfBoundsException e) {
977 caught = true;
978 }
979 if (!caught) {
980 System.out.println("foo6 exception failed!");
981 }
982
983 }
984
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700985 // Make sure this method is compiled with optimizing.
David Brazdila06d66a2015-05-28 11:14:54 +0100986 /// CHECK-START: void Main.main(java.lang.String[]) register (after)
987 /// CHECK: ParallelMove
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700988
Mingyao Yang0304e182015-01-30 16:41:29 -0800989 public static void main(String[] args) {
990 sieve(20);
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800991
992 int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
993 bubbleSort(array);
994 for (int i = 0; i < 8; i++) {
995 if (array[i] != i) {
996 System.out.println("bubble sort failed!");
997 }
998 }
999
1000 array = new int[7];
1001 pyramid1(array);
1002 if (!isPyramid(array)) {
1003 System.out.println("pyramid1 failed!");
1004 }
1005
1006 array = new int[8];
1007 pyramid2(array);
1008 if (!isPyramid(array)) {
1009 System.out.println("pyramid2 failed!");
1010 }
1011
1012 java.util.Arrays.fill(array, -1);
1013 pyramid3(array);
1014 if (!isPyramid(array)) {
1015 System.out.println("pyramid3 failed!");
1016 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001017
1018 // Make sure this value is kept after deoptimization.
1019 int i = 1;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001020 if (foo() + i != 100) {
1021 System.out.println("foo failed!");
1022 };
1023
1024 testUnknownBounds();
Mingyao Yang0304e182015-01-30 16:41:29 -08001025 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001026
Mingyao Yang0304e182015-01-30 16:41:29 -08001027}