blob: 8f9a32ab3ae7cff6ae06c95d5651d0f61b105acb [file] [log] [blame]
Mingyao Yang0304e182015-01-30 16:41:29 -08001/*
Roland Levillain6a92a032015-07-23 12:15:01 +01002 * 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 */
Mingyao Yang0304e182015-01-30 16:41:29 -080016
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
Nicolas Geoffray5949fa02015-12-18 10:57:10 +0000130 /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100131 /// 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
Nicolas Geoffray5949fa02015-12-18 10:57:10 +0000140 /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100141 /// 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
Nicolas Geoffray5949fa02015-12-18 10:57:10 +0000154 static void $opt$noinline$constantIndexing2(int[] array) {
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700155 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;
Nicolas Geoffray5949fa02015-12-18 10:57:10 +0000160 if (array[1] == 1) {
161 throw new Error("");
162 }
Mingyao Yange295e6e2015-03-07 06:37:59 -0800163 }
164
165
David Brazdila06d66a2015-05-28 11:14:54 +0100166 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before)
167 /// CHECK: BoundsCheck
168 /// CHECK: ArrayGet
169 /// CHECK: BoundsCheck
170 /// CHECK: ArraySet
171 /// CHECK: BoundsCheck
172 /// CHECK: ArrayGet
173 /// CHECK: BoundsCheck
174 /// CHECK: ArraySet
175 /// CHECK: BoundsCheck
176 /// CHECK: ArrayGet
177 /// CHECK: BoundsCheck
178 /// CHECK: ArraySet
179 /// CHECK: BoundsCheck
180 /// CHECK: ArrayGet
181 /// CHECK: BoundsCheck
182 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700183
David Brazdila06d66a2015-05-28 11:14:54 +0100184 /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after)
185 /// CHECK: LessThanOrEqual
186 /// CHECK: Deoptimize
187 /// CHECK-NOT: BoundsCheck
188 /// CHECK: ArrayGet
189 /// CHECK: LessThanOrEqual
190 /// CHECK: Deoptimize
191 /// CHECK-NOT: BoundsCheck
192 /// CHECK: ArraySet
193 /// CHECK-NOT: BoundsCheck
194 /// CHECK: ArrayGet
195 /// CHECK-NOT: BoundsCheck
196 /// CHECK: ArraySet
197 /// CHECK-NOT: BoundsCheck
198 /// CHECK: ArrayGet
199 /// CHECK-NOT: BoundsCheck
200 /// CHECK: ArraySet
201 /// CHECK-NOT: BoundsCheck
202 /// CHECK: ArrayGet
203 /// CHECK-NOT: BoundsCheck
204 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700205
206 static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) {
207 if (!copy) {
208 return array1;
209 }
210 array2[0] = array1[0];
211 array2[1] = array1[1];
212 array2[2] = array1[2];
213 array2[3] = array1[3];
214 return array2;
215 }
216
217
David Brazdila06d66a2015-05-28 11:14:54 +0100218 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before)
219 /// CHECK: BoundsCheck
220 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700221
David Brazdila06d66a2015-05-28 11:14:54 +0100222 /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after)
223 /// CHECK-NOT: LessThanOrEqual
224 /// CHECK: BoundsCheck
225 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700226
227 // There is only one array access. It's not beneficial
228 // to create a compare with deoptimization instruction.
229 static void constantIndexing4(int[] array) {
230 array[0] = 1;
231 }
232
233
David Brazdila06d66a2015-05-28 11:14:54 +0100234 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before)
235 /// CHECK: BoundsCheck
236 /// CHECK: ArraySet
237 /// CHECK: BoundsCheck
238 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700239
David Brazdila06d66a2015-05-28 11:14:54 +0100240 /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after)
241 /// CHECK-NOT: Deoptimize
242 /// CHECK: BoundsCheck
243 /// CHECK: ArraySet
244 /// CHECK: BoundsCheck
245 /// CHECK: ArraySet
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700246
247 static void constantIndexing5(int[] array) {
248 // We don't apply the deoptimization for very large constant index
249 // since it's likely to be an anomaly and will throw AIOOBE.
250 array[Integer.MAX_VALUE - 1000] = 1;
251 array[Integer.MAX_VALUE - 999] = 1;
252 array[Integer.MAX_VALUE - 998] = 1;
253 }
254
Andreas Gampe639bdd12015-06-03 11:22:45 -0700255 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (before)
256 /// CHECK: BoundsCheck
257 /// CHECK: ArraySet
258 /// CHECK: BoundsCheck
259 /// CHECK: ArraySet
260
261 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (after)
262 /// CHECK: Deoptimize
263
264 static void constantIndexing6(int[] array) {
265 array[3] = 1;
266 array[4] = 1;
267 }
268
269 // A helper into which the actual throwing function should be inlined.
270 static void constantIndexingForward6(int[] array) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700271 assertIsManaged();
Andreas Gampe639bdd12015-06-03 11:22:45 -0700272 constantIndexing6(array);
273 }
274
David Brazdila06d66a2015-05-28 11:14:54 +0100275 /// CHECK-START: void Main.loopPattern1(int[]) BCE (before)
276 /// CHECK: BoundsCheck
277 /// CHECK: ArraySet
278 /// CHECK: BoundsCheck
279 /// CHECK: ArraySet
280 /// CHECK: BoundsCheck
281 /// CHECK: ArraySet
282 /// CHECK: BoundsCheck
283 /// CHECK: ArraySet
284 /// CHECK: BoundsCheck
285 /// CHECK: ArraySet
286 /// CHECK: BoundsCheck
287 /// CHECK: ArraySet
288 /// CHECK: BoundsCheck
289 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800290
David Brazdila06d66a2015-05-28 11:14:54 +0100291 /// CHECK-START: void Main.loopPattern1(int[]) BCE (after)
292 /// CHECK-NOT: BoundsCheck
293 /// CHECK: ArraySet
294 /// CHECK-NOT: BoundsCheck
295 /// CHECK: ArraySet
296 /// CHECK-NOT: BoundsCheck
297 /// CHECK: ArraySet
298 /// CHECK: BoundsCheck
299 /// CHECK: ArraySet
300 /// CHECK: BoundsCheck
301 /// CHECK: ArraySet
302 /// CHECK: BoundsCheck
303 /// CHECK: ArraySet
304 /// CHECK-NOT: BoundsCheck
305 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800306
307 static void loopPattern1(int[] array) {
308 for (int i = 0; i < array.length; i++) {
309 array[i] = 1; // Bounds check can be eliminated.
310 }
311
312 for (int i = 1; i < array.length; i++) {
313 array[i] = 1; // Bounds check can be eliminated.
314 }
315
316 for (int i = 1; i < array.length - 1; i++) {
317 array[i] = 1; // Bounds check can be eliminated.
318 }
319
320 for (int i = -1; i < array.length; i++) {
321 array[i] = 1; // Bounds check can't be eliminated.
322 }
323
324 for (int i = 0; i <= array.length; i++) {
325 array[i] = 1; // Bounds check can't be eliminated.
326 }
327
328 for (int i = 0; i < array.length; i += 2) {
329 // We don't have any assumption on max array length yet.
330 // Bounds check can't be eliminated due to overflow concern.
331 array[i] = 1;
332 }
333
334 for (int i = 1; i < array.length; i += 2) {
335 // Bounds check can be eliminated since i is odd so the last
336 // i that's less than array.length is at most (Integer.MAX_VALUE - 2).
337 array[i] = 1;
338 }
339 }
340
341
David Brazdila06d66a2015-05-28 11:14:54 +0100342 /// CHECK-START: void Main.loopPattern2(int[]) BCE (before)
343 /// CHECK: BoundsCheck
344 /// CHECK: ArraySet
345 /// CHECK: BoundsCheck
346 /// CHECK: ArraySet
347 /// CHECK: BoundsCheck
348 /// CHECK: ArraySet
349 /// CHECK: BoundsCheck
350 /// CHECK: ArraySet
351 /// CHECK: BoundsCheck
352 /// CHECK: ArraySet
353 /// CHECK: BoundsCheck
354 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800355
David Brazdila06d66a2015-05-28 11:14:54 +0100356 /// CHECK-START: void Main.loopPattern2(int[]) BCE (after)
357 /// CHECK-NOT: BoundsCheck
358 /// CHECK: ArraySet
359 /// CHECK-NOT: BoundsCheck
360 /// CHECK: ArraySet
361 /// CHECK-NOT: BoundsCheck
362 /// CHECK: ArraySet
363 /// CHECK: BoundsCheck
364 /// CHECK: ArraySet
365 /// CHECK: BoundsCheck
366 /// CHECK: ArraySet
367 /// CHECK-NOT: BoundsCheck
368 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800369
370 static void loopPattern2(int[] array) {
371 for (int i = array.length - 1; i >= 0; i--) {
372 array[i] = 1; // Bounds check can be eliminated.
373 }
374
375 for (int i = array.length; i > 0; i--) {
376 array[i - 1] = 1; // Bounds check can be eliminated.
377 }
378
379 for (int i = array.length - 1; i > 0; i--) {
380 array[i] = 1; // Bounds check can be eliminated.
381 }
382
383 for (int i = array.length; i >= 0; i--) {
384 array[i] = 1; // Bounds check can't be eliminated.
385 }
386
387 for (int i = array.length; i >= 0; i--) {
388 array[i - 1] = 1; // Bounds check can't be eliminated.
389 }
390
391 for (int i = array.length; i > 0; i -= 20) {
392 // For i >= 0, (i - 20 - 1) is guaranteed not to underflow.
393 array[i - 1] = 1; // Bounds check can be eliminated.
394 }
395 }
396
397
David Brazdila06d66a2015-05-28 11:14:54 +0100398 /// CHECK-START: void Main.loopPattern3(int[]) BCE (before)
399 /// CHECK: BoundsCheck
400 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800401
David Brazdila06d66a2015-05-28 11:14:54 +0100402 /// CHECK-START: void Main.loopPattern3(int[]) BCE (after)
403 /// CHECK: BoundsCheck
404 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800405
406 static void loopPattern3(int[] array) {
407 java.util.Random random = new java.util.Random();
408 for (int i = 0; ; i++) {
409 if (random.nextInt() % 1000 == 0 && i < array.length) {
410 // Can't eliminate the bound check since not every i++ is
411 // matched with a array length check, so there is some chance that i
412 // overflows and is negative.
413 array[i] = 1;
414 }
415 }
416 }
417
418
David Brazdila06d66a2015-05-28 11:14:54 +0100419 /// CHECK-START: void Main.constantNewArray() BCE (before)
420 /// CHECK: BoundsCheck
421 /// CHECK: ArraySet
422 /// CHECK: BoundsCheck
423 /// CHECK: ArraySet
424 /// CHECK: BoundsCheck
425 /// CHECK: ArraySet
426 /// CHECK: BoundsCheck
427 /// CHECK: ArraySet
428 /// CHECK: BoundsCheck
429 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800430
David Brazdila06d66a2015-05-28 11:14:54 +0100431 /// CHECK-START: void Main.constantNewArray() BCE (after)
432 /// CHECK-NOT: BoundsCheck
433 /// CHECK: ArraySet
434 /// CHECK: BoundsCheck
435 /// CHECK: ArraySet
436 /// CHECK-NOT: BoundsCheck
437 /// CHECK: ArraySet
438 /// CHECK-NOT: BoundsCheck
439 /// CHECK: ArraySet
440 /// CHECK: BoundsCheck
441 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800442
443 static void constantNewArray() {
444 int[] array = new int[10];
445 for (int i = 0; i < 10; i++) {
446 array[i] = 1; // Bounds check can be eliminated.
447 }
448
449 for (int i = 0; i <= 10; i++) {
450 array[i] = 1; // Bounds check can't be eliminated.
451 }
452
453 array[0] = 1; // Bounds check can be eliminated.
454 array[9] = 1; // Bounds check can be eliminated.
455 array[10] = 1; // Bounds check can't be eliminated.
456 }
457
Mingyao Yang4559f002015-02-27 14:43:53 -0800458
459 static byte readData() {
460 return 1;
461 }
462
David Brazdila06d66a2015-05-28 11:14:54 +0100463 /// CHECK-START: void Main.circularBufferProducer() BCE (before)
464 /// CHECK: BoundsCheck
465 /// CHECK: ArraySet
Mingyao Yang4559f002015-02-27 14:43:53 -0800466
David Brazdila06d66a2015-05-28 11:14:54 +0100467 /// CHECK-START: void Main.circularBufferProducer() BCE (after)
468 /// CHECK-NOT: BoundsCheck
469 /// CHECK: ArraySet
Mingyao Yang4559f002015-02-27 14:43:53 -0800470
471 static void circularBufferProducer() {
472 byte[] array = new byte[4096];
473 int i = 0;
474 while (true) {
475 array[i & (array.length - 1)] = readData();
476 i++;
477 }
478 }
479
480
David Brazdila06d66a2015-05-28 11:14:54 +0100481 /// CHECK-START: void Main.pyramid1(int[]) BCE (before)
482 /// CHECK: BoundsCheck
483 /// CHECK: ArraySet
484 /// CHECK: BoundsCheck
485 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800486
David Brazdila06d66a2015-05-28 11:14:54 +0100487 /// CHECK-START: void Main.pyramid1(int[]) BCE (after)
488 /// CHECK-NOT: BoundsCheck
489 /// CHECK: ArraySet
490 /// CHECK-NOT: BoundsCheck
491 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800492
493 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
494 static void pyramid1(int[] array) {
495 for (int i = 0; i < (array.length + 1) / 2; i++) {
496 array[i] = i;
497 array[array.length - 1 - i] = i;
498 }
499 }
500
501
David Brazdila06d66a2015-05-28 11:14:54 +0100502 /// CHECK-START: void Main.pyramid2(int[]) BCE (before)
503 /// CHECK: BoundsCheck
504 /// CHECK: ArraySet
505 /// CHECK: BoundsCheck
506 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800507
David Brazdila06d66a2015-05-28 11:14:54 +0100508 /// CHECK-START: void Main.pyramid2(int[]) BCE (after)
509 /// CHECK-NOT: BoundsCheck
510 /// CHECK: ArraySet
511 /// CHECK-NOT: BoundsCheck
512 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800513
514 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
515 static void pyramid2(int[] array) {
516 for (int i = 0; i < (array.length + 1) >> 1; i++) {
517 array[i] = i;
518 array[array.length - 1 - i] = i;
519 }
520 }
521
522
David Brazdila06d66a2015-05-28 11:14:54 +0100523 /// CHECK-START: void Main.pyramid3(int[]) BCE (before)
524 /// CHECK: BoundsCheck
525 /// CHECK: ArraySet
526 /// CHECK: BoundsCheck
527 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800528
David Brazdila06d66a2015-05-28 11:14:54 +0100529 /// CHECK-START: void Main.pyramid3(int[]) BCE (after)
530 /// CHECK-NOT: BoundsCheck
531 /// CHECK: ArraySet
532 /// CHECK-NOT: BoundsCheck
533 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800534
535 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
536 static void pyramid3(int[] array) {
537 for (int i = 0; i < (array.length + 1) >>> 1; i++) {
538 array[i] = i;
539 array[array.length - 1 - i] = i;
540 }
541 }
542
543
David Brazdila06d66a2015-05-28 11:14:54 +0100544 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
545 /// CHECK: BoundsCheck
546 /// CHECK: ArrayGet
547 /// CHECK: BoundsCheck
548 /// CHECK: ArrayGet
Mingyao Yang57e04752015-02-09 18:13:26 -0800549
David Brazdila06d66a2015-05-28 11:14:54 +0100550 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
551 /// CHECK-NOT: BoundsCheck
552 /// CHECK: ArrayGet
553 /// CHECK-NOT: BoundsCheck
554 /// CHECK: ArrayGet
Mingyao Yang57e04752015-02-09 18:13:26 -0800555
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800556 static boolean isPyramid(int[] array) {
557 int i = 0;
558 int j = array.length - 1;
559 while (i <= j) {
560 if (array[i] != i) {
561 return false;
562 }
563 if (array[j] != i) {
564 return false;
565 }
566 i++; j--;
567 }
568 return true;
569 }
570
571
David Brazdila06d66a2015-05-28 11:14:54 +0100572 /// CHECK-START: void Main.bubbleSort(int[]) GVN (before)
573 /// CHECK: BoundsCheck
574 /// CHECK: ArrayGet
575 /// CHECK: BoundsCheck
576 /// CHECK: ArrayGet
577 /// CHECK: BoundsCheck
578 /// CHECK: ArrayGet
579 /// CHECK: BoundsCheck
580 /// CHECK: ArrayGet
581 /// CHECK: BoundsCheck
582 /// CHECK: ArraySet
583 /// CHECK: BoundsCheck
584 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800585
David Brazdila06d66a2015-05-28 11:14:54 +0100586 /// CHECK-START: void Main.bubbleSort(int[]) GVN (after)
587 /// CHECK: BoundsCheck
588 /// CHECK: ArrayGet
589 /// CHECK: BoundsCheck
590 /// CHECK: ArrayGet
591 /// CHECK-NOT: ArrayGet
592 /// CHECK-NOT: ArrayGet
593 /// CHECK-NOT: BoundsCheck
594 /// CHECK: ArraySet
595 /// CHECK-NOT: BoundsCheck
596 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800597
David Brazdila06d66a2015-05-28 11:14:54 +0100598 /// CHECK-START: void Main.bubbleSort(int[]) BCE (after)
599 /// CHECK-NOT: BoundsCheck
600 /// CHECK: ArrayGet
601 /// CHECK-NOT: BoundsCheck
602 /// CHECK: ArrayGet
603 /// CHECK-NOT: ArrayGet
604 /// CHECK-NOT: ArrayGet
605 /// CHECK-NOT: BoundsCheck
606 /// CHECK: ArraySet
607 /// CHECK-NOT: BoundsCheck
608 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800609
610 static void bubbleSort(int[] array) {
611 for (int i = 0; i < array.length - 1; i++) {
612 for (int j = 0; j < array.length - i - 1; j++) {
613 if (array[j] > array[j + 1]) {
614 int temp = array[j + 1];
615 array[j + 1] = array[j];
616 array[j] = temp;
617 }
618 }
619 }
620 }
621
Aart Bik5d75afe2015-12-14 11:57:01 -0800622 static int[][] mA;
623
624 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before)
Aart Bik09e8d5f2016-01-22 16:49:55 -0800625 // Array references mA[i] and ..[j] both in inner loop.
626 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Bounds1:i\d+>>] loop:<<InnerLoop:B\d+>>
627 /// CHECK-DAG: <<Array1>> NullCheck [<<Field1:l\d+>>] loop:<<InnerLoop>>
628 /// CHECK-DAG: <<Len1:i\d+>> ArrayLength [<<Array1>>] loop:<<InnerLoop>>
629 /// CHECK-DAG: <<Bounds1>> BoundsCheck [<<Index1:i\d+>>,<<Len1>>] loop:<<InnerLoop>>
630 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Bounds2:i\d+>>] loop:<<InnerLoop>>
631 /// CHECK-DAG: <<Array2>> NullCheck [<<Get1>>] loop:<<InnerLoop>>
632 /// CHECK-DAG: <<Len2:i\d+>> ArrayLength [<<Array2>>] loop:<<InnerLoop>>
633 /// CHECK-DAG: <<Bounds2>> BoundsCheck [<<Index2:i\d+>>,<<Len2>>] loop:<<InnerLoop>>
Vladimir Marko17fb8932016-02-02 14:53:47 +0000634 // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
635 /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>>
Aart Bik09e8d5f2016-01-22 16:49:55 -0800636 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>>
637 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop:B\d+>>
638 /// CHECK-DAG: <<Field1>> StaticFieldGet loop:none
639 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
640 //
641 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
642 // Array reference mA[i] hoisted to same level as deopt.
643 /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
644 /// CHECK-DAG: ArrayLength loop:<<OuterLoop>>
645 /// CHECK-DAG: <<Get1:l\d+>> ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>] loop:<<OuterLoop>>
646 // Array reference ..[j] still in inner loop, with a direct index.
647 /// CHECK-DAG: <<Get2:i\d+>> ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>] loop:<<InnerLoop:B\d+>>
Vladimir Marko17fb8932016-02-02 14:53:47 +0000648 // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
649 /// CHECK-DAG: InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>>
Aart Bik09e8d5f2016-01-22 16:49:55 -0800650 /// CHECK-DAG: <<Index2>> Phi loop:<<InnerLoop>>
651 /// CHECK-DAG: <<Index1>> Phi loop:<<OuterLoop>>
652 // Synthetic phi.
653 /// CHECK-DAG: <<Array2>> Phi loop:<<OuterLoop>>
654 /// CHECK-DAG: <<Array1>> StaticFieldGet loop:none
655 /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
656 //
Aart Bik5d75afe2015-12-14 11:57:01 -0800657 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
658 /// CHECK-NOT: NullCheck
Aart Bik5d75afe2015-12-14 11:57:01 -0800659 /// CHECK-NOT: BoundsCheck
Aart Bik5d75afe2015-12-14 11:57:01 -0800660 static void dynamicBCEAndIntrinsic(int n) {
661 for (int i = 0; i < n; i++) {
662 for (int j = 0; j < n; j++) {
663 // Since intrinsic call cannot modify fields or arrays,
664 // dynamic BCE and hoisting can be applied to the inner loop.
665 mA[i][j] = Math.abs(mA[i][j]);
666 }
667 }
668 }
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800669
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700670 static int foo() {
671 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700672 assertIsManaged();
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700673 // This will cause AIOOBE.
Nicolas Geoffray5949fa02015-12-18 10:57:10 +0000674 $opt$noinline$constantIndexing2(new int[3]);
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700675 } catch (ArrayIndexOutOfBoundsException e) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700676 assertIsManaged(); // This is to ensure that single-frame deoptimization works.
Nicolas Geoffray5949fa02015-12-18 10:57:10 +0000677 // Will need to be updated if $opt$noinline$constantIndexing2 is inlined.
Andreas Gampe639bdd12015-06-03 11:22:45 -0700678 try {
679 // This will cause AIOOBE.
680 constantIndexingForward6(new int[3]);
681 } catch (ArrayIndexOutOfBoundsException e2) {
David Brazdil95177982015-10-30 12:56:58 -0500682 // Having deopted, we expect to be running interpreted at this point.
683 // Does not apply to debuggable, however, since we do not inline.
Andreas Gampe639bdd12015-06-03 11:22:45 -0700684 return 99;
685 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700686 }
687 return 0;
688 }
689
690
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700691 int sum;
692
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700693 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100694 /// CHECK: BoundsCheck
695 /// CHECK: ArraySet
696 /// CHECK-NOT: BoundsCheck
697 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700698
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700699 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100700 /// CHECK: Phi
701 /// CHECK-NOT: BoundsCheck
702 /// CHECK: ArraySet
703 /// CHECK-NOT: BoundsCheck
704 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800705 // Added blocks at end for deoptimization.
706 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700707 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -0700708 /// CHECK: Deoptimize
709 /// CHECK: Deoptimize
710 /// CHECK: Deoptimize
711 /// CHECK-NOT: Deoptimize
712 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800713 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700714 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700715
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700716 void foo1(int[] array, int start, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800717 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700718 // and one for null check on array (to hoist null
719 // check and array.length out of loop).
720 for (int i = start ; i < end; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700721 if (expectInterpreter) {
722 assertIsInterpreted();
723 } else {
724 assertIsManaged();
725 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700726 array[i] = 1;
727 sum += array[i];
728 }
729 }
730
731
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700732 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100733 /// CHECK: BoundsCheck
734 /// CHECK: ArraySet
735 /// CHECK-NOT: BoundsCheck
736 /// CHECK: ArrayGet
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700737 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100738 /// CHECK: Phi
739 /// CHECK-NOT: BoundsCheck
740 /// CHECK: ArraySet
741 /// CHECK-NOT: BoundsCheck
742 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800743 // Added blocks at end for deoptimization.
744 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700745 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -0700746 /// CHECK: Deoptimize
747 /// CHECK: Deoptimize
748 /// CHECK: Deoptimize
749 /// CHECK-NOT: Deoptimize
750 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800751 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700752 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700753
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700754 void foo2(int[] array, int start, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800755 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700756 // and one for null check on array (to hoist null
757 // check and array.length out of loop).
758 for (int i = start ; i <= end; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700759 if (expectInterpreter) {
760 assertIsInterpreted();
761 } else {
762 assertIsManaged();
763 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700764 array[i] = 1;
765 sum += array[i];
766 }
767 }
768
769
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700770 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100771 /// CHECK: BoundsCheck
772 /// CHECK: ArraySet
773 /// CHECK-NOT: BoundsCheck
774 /// CHECK: ArrayGet
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700775 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100776 /// CHECK: Phi
777 /// CHECK-NOT: BoundsCheck
778 /// CHECK: ArraySet
779 /// CHECK-NOT: BoundsCheck
780 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800781 // Added blocks at end for deoptimization.
782 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700783 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800784 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700785 /// CHECK: Deoptimize
786 /// CHECK: Deoptimize
787 /// CHECK-NOT: Deoptimize
788 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800789 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700790 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700791
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700792 void foo3(int[] array, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800793 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700794 // and one for null check on array (to hoist null check
795 // and array.length out of loop).
796 for (int i = 3 ; i <= end; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700797 if (expectInterpreter) {
798 assertIsInterpreted();
799 } else {
800 assertIsManaged();
801 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700802 array[i] = 1;
803 sum += array[i];
804 }
805 }
806
Mingyao Yang3584bce2015-05-19 16:01:59 -0700807
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700808 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100809 /// CHECK: BoundsCheck
810 /// CHECK: ArraySet
811 /// CHECK-NOT: BoundsCheck
812 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700813
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700814 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100815 /// CHECK: Phi
816 /// CHECK-NOT: BoundsCheck
817 /// CHECK: ArraySet
818 /// CHECK-NOT: BoundsCheck
819 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800820 // Added blocks at end for deoptimization.
821 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700822 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800823 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700824 /// CHECK: Deoptimize
825 /// CHECK: Deoptimize
826 /// CHECK-NOT: Deoptimize
827 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800828 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700829 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700830
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700831 void foo4(int[] array, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800832 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700833 // and one for null check on array (to hoist null check
834 // and array.length out of loop).
835 for (int i = end ; i > 0; i--) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700836 if (expectInterpreter) {
837 assertIsInterpreted();
838 } else {
839 assertIsManaged();
840 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700841 array[i - 1] = 1;
842 sum += array[i - 1];
843 }
844 }
845
846
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700847 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100848 /// CHECK: BoundsCheck
849 /// CHECK: ArraySet
850 /// CHECK: BoundsCheck
851 /// CHECK: ArrayGet
852 /// CHECK: BoundsCheck
853 /// CHECK: ArrayGet
854 /// CHECK: BoundsCheck
855 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700856
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700857 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100858 /// CHECK-NOT: BoundsCheck
859 /// CHECK: ArraySet
David Brazdila06d66a2015-05-28 11:14:54 +0100860 /// CHECK: Phi
861 /// CHECK-NOT: BoundsCheck
862 /// CHECK: ArrayGet
863 /// CHECK-NOT: BoundsCheck
864 /// CHECK: ArrayGet
865 /// CHECK-NOT: BoundsCheck
866 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800867 // Added blocks at end for deoptimization.
868 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700869 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800870 /// CHECK: Deoptimize
871 /// CHECK: Deoptimize
872 /// CHECK: Deoptimize
873 /// CHECK: Deoptimize
874 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700875 /// CHECK: Deoptimize
876 /// CHECK-NOT: Deoptimize
877 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800878 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700879 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700880
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700881 void foo5(int[] array, int end, boolean expectInterpreter) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700882 // Bounds check in this loop can be eliminated without deoptimization.
883 for (int i = array.length - 1 ; i >= 0; i--) {
884 array[i] = 1;
885 }
Aart Bik4a342772015-11-30 10:17:46 -0800886 // Several HDeoptimize will be added. Two for each index.
887 // The null check is not necessary.
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700888 for (int i = end - 2 ; i > 0; i--) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700889 if (expectInterpreter) {
890 assertIsInterpreted();
891 } else {
892 assertIsManaged();
893 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700894 sum += array[i - 1];
895 sum += array[i];
896 sum += array[i + 1];
897 }
898 }
899
900
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700901 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100902 /// CHECK: BoundsCheck
903 /// CHECK: ArrayGet
904 /// CHECK: BoundsCheck
905 /// CHECK: ArrayGet
906 /// CHECK: BoundsCheck
907 /// CHECK: ArrayGet
908 /// CHECK: BoundsCheck
909 /// CHECK: ArrayGet
910 /// CHECK: BoundsCheck
911 /// CHECK: ArrayGet
912 /// CHECK-NOT: BoundsCheck
913 /// CHECK: ArraySet
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700914 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100915 /// CHECK: Phi
916 /// CHECK-NOT: BoundsCheck
917 /// CHECK: ArrayGet
918 /// CHECK-NOT: BoundsCheck
919 /// CHECK: ArrayGet
920 /// CHECK-NOT: BoundsCheck
921 /// CHECK: ArrayGet
922 /// CHECK-NOT: BoundsCheck
923 /// CHECK: ArrayGet
924 /// CHECK-NOT: BoundsCheck
925 /// CHECK: ArrayGet
926 /// CHECK-NOT: BoundsCheck
927 /// CHECK: ArraySet
Aart Bik4a342772015-11-30 10:17:46 -0800928 // Added blocks at end for deoptimization.
929 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700930 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800931 /// CHECK: Deoptimize
932 /// CHECK: Deoptimize
933 /// CHECK: Deoptimize
934 /// CHECK: Deoptimize
935 /// CHECK: Deoptimize
936 /// CHECK: Deoptimize
937 /// CHECK: Deoptimize
938 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700939 /// CHECK: Deoptimize
940 /// CHECK: Deoptimize
941 /// CHECK: Deoptimize
942 /// CHECK-NOT: Deoptimize
943 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700944 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800945 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700946
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700947 void foo6(int[] array, int start, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800948 // Several HDeoptimize will be added.
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700949 for (int i = end; i >= start; i--) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700950 if (expectInterpreter) {
951 assertIsInterpreted();
952 } else {
953 assertIsManaged();
954 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700955 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5;
956 }
957 }
958
959
David Brazdila06d66a2015-05-28 11:14:54 +0100960 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
961 /// CHECK: BoundsCheck
962 /// CHECK: ArrayGet
963 /// CHECK: BoundsCheck
964 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700965
David Brazdila06d66a2015-05-28 11:14:54 +0100966 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100967 /// CHECK: Phi
968 /// CHECK: BoundsCheck
969 /// CHECK: ArrayGet
970 /// CHECK-NOT: BoundsCheck
971 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800972 // Added blocks at end for deoptimization.
973 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700974 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -0700975 /// CHECK: Deoptimize
976 /// CHECK: Deoptimize
977 /// CHECK: Deoptimize
978 /// CHECK-NOT: Deoptimize
979 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800980 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700981 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700982
983 void foo7(int[] array, int start, int end, boolean lowEnd) {
Aart Bik4a342772015-11-30 10:17:46 -0800984 // Three HDeoptimize will be added. One for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700985 // and one for null check on array (to hoist null
986 // check and array.length out of loop).
987 for (int i = start ; i < end; i++) {
988 if (lowEnd) {
989 // This array access isn't certain. So we don't
990 // use +1000 offset in decision making for deoptimization
991 // conditions.
992 sum += array[i + 1000];
993 }
994 sum += array[i];
995 }
996 }
997
998
Mingyao Yang3584bce2015-05-19 16:01:59 -0700999 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before)
1000 /// CHECK: BoundsCheck
1001 /// CHECK: ArrayGet
1002 /// CHECK: BoundsCheck
1003 /// CHECK: ArraySet
1004
1005 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after)
1006 /// CHECK: Phi
1007 /// CHECK-NOT: BoundsCheck
1008 /// CHECK: ArrayGet
1009 /// CHECK: Phi
1010 /// CHECK-NOT: BoundsCheck
1011 /// CHECK: ArraySet
Aart Bik4a342772015-11-30 10:17:46 -08001012 // Added blocks at end for deoptimization.
1013 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -07001014 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -08001015 /// CHECK: Deoptimize
1016 /// CHECK: Deoptimize
1017 /// CHECK: Deoptimize
Aart Bikd59c7062015-11-21 05:21:52 +00001018 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -08001019 /// CHECK: Goto
1020 /// CHECK: Goto
1021 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -07001022 /// CHECK: Deoptimize
1023 /// CHECK: Deoptimize
1024 /// CHECK: Deoptimize
1025 /// CHECK-NOT: Deoptimize
1026 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -08001027 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -07001028 /// CHECK: Goto
1029
1030 void foo8(int[][] matrix, int start, int end) {
Aart Bik4a342772015-11-30 10:17:46 -08001031 // Three HDeoptimize will be added for the outer loop,
1032 // two for the index, and null check on matrix. Same
1033 // for the inner loop.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001034 for (int i = start; i < end; i++) {
1035 int[] row = matrix[i];
1036 for (int j = start; j < end; j++) {
1037 row[j] = 1;
1038 }
1039 }
1040 }
1041
1042
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001043 /// CHECK-START: void Main.foo9(int[], boolean) BCE (before)
Mingyao Yang3584bce2015-05-19 16:01:59 -07001044 /// CHECK: NullCheck
1045 /// CHECK: BoundsCheck
1046 /// CHECK: ArrayGet
1047
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001048 /// CHECK-START: void Main.foo9(int[], boolean) BCE (after)
Mingyao Yang3584bce2015-05-19 16:01:59 -07001049 // The loop is guaranteed to be entered. No need to transform the
1050 // loop for loop body entry test.
1051 /// CHECK: Deoptimize
1052 /// CHECK: Deoptimize
Aart Bik4a342772015-11-30 10:17:46 -08001053 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -07001054 /// CHECK-NOT: Deoptimize
1055 /// CHECK: Phi
1056 /// CHECK-NOT: NullCheck
1057 /// CHECK-NOT: BoundsCheck
1058 /// CHECK: ArrayGet
1059
Aart Bik4a342772015-11-30 10:17:46 -08001060 /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier_after_bce (after)
1061 // Simplification removes the redundant check
1062 /// CHECK: Deoptimize
1063 /// CHECK: Deoptimize
1064 /// CHECK-NOT: Deoptimize
1065
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001066 void foo9(int[] array, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -08001067 // Two HDeoptimize will be added. Two for the index
1068 // and one for null check on array.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001069 for (int i = 0 ; i < 10; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001070 if (expectInterpreter) {
1071 assertIsInterpreted();
1072 } else {
1073 assertIsManaged();
1074 }
Mingyao Yang3584bce2015-05-19 16:01:59 -07001075 sum += array[i];
1076 }
1077 }
1078
1079
David Brazdila06d66a2015-05-28 11:14:54 +01001080 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
1081 /// CHECK: BoundsCheck
1082 /// CHECK: ArraySet
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001083
David Brazdila06d66a2015-05-28 11:14:54 +01001084 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
1085 /// CHECK-NOT: Deoptimize
1086 /// CHECK: BoundsCheck
1087 /// CHECK: ArraySet
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001088
1089 void partialLooping(int[] array, int start, int end) {
1090 // This loop doesn't cover the full range of [start, end) so
1091 // adding deoptimization is too aggressive, since end can be
1092 // greater than array.length but the loop is never going to work on
1093 // more than 2 elements.
1094 for (int i = start; i < end; i++) {
1095 if (i == 2) {
1096 return;
1097 }
1098 array[i] = 1;
1099 }
1100 }
1101
1102
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001103 static void testUnknownBounds() {
1104 boolean caught = false;
1105 Main main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001106 main.foo1(new int[10], 0, 10, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001107 if (main.sum != 10) {
1108 System.out.println("foo1 failed!");
1109 }
1110
1111 caught = false;
1112 main = new Main();
1113 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001114 main.foo1(new int[10], 0, 11, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001115 } catch (ArrayIndexOutOfBoundsException e) {
1116 caught = true;
1117 }
1118 if (!caught || main.sum != 10) {
1119 System.out.println("foo1 exception failed!");
1120 }
1121
1122 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001123 main.foo2(new int[10], 0, 9, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001124 if (main.sum != 10) {
1125 System.out.println("foo2 failed!");
1126 }
1127
1128 caught = false;
1129 main = new Main();
1130 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001131 main.foo2(new int[10], 0, 10, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001132 } catch (ArrayIndexOutOfBoundsException e) {
1133 caught = true;
1134 }
1135 if (!caught || main.sum != 10) {
1136 System.out.println("foo2 exception failed!");
1137 }
1138
1139 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001140 main.foo3(new int[10], 9, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001141 if (main.sum != 7) {
1142 System.out.println("foo3 failed!");
1143 }
1144
1145 caught = false;
1146 main = new Main();
1147 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001148 main.foo3(new int[10], 10, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001149 } catch (ArrayIndexOutOfBoundsException e) {
1150 caught = true;
1151 }
1152 if (!caught || main.sum != 7) {
1153 System.out.println("foo3 exception failed!");
1154 }
1155
1156 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001157 main.foo4(new int[10], 10, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001158 if (main.sum != 10) {
1159 System.out.println("foo4 failed!");
1160 }
1161
1162 caught = false;
1163 main = new Main();
1164 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001165 main.foo4(new int[10], 11, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001166 } catch (ArrayIndexOutOfBoundsException e) {
1167 caught = true;
1168 }
1169 if (!caught || main.sum != 0) {
1170 System.out.println("foo4 exception failed!");
1171 }
1172
1173 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001174 main.foo5(new int[10], 10, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001175 if (main.sum != 24) {
1176 System.out.println("foo5 failed!");
1177 }
1178
1179 caught = false;
1180 main = new Main();
1181 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001182 main.foo5(new int[10], 11, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001183 } catch (ArrayIndexOutOfBoundsException e) {
1184 caught = true;
1185 }
1186 if (!caught || main.sum != 2) {
1187 System.out.println("foo5 exception failed!");
1188 }
1189
1190 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001191 main.foo6(new int[10], 2, 7, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001192
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001193 main = new Main();
Mingyao Yang3584bce2015-05-19 16:01:59 -07001194 int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001195 main.foo9(array9, false);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001196 if (main.sum != 45) {
1197 System.out.println("foo9 failed!");
1198 }
1199
1200 main = new Main();
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001201 int[] array = new int[4];
1202 main.partialLooping(new int[3], 0, 4);
1203 if ((array[0] != 1) && (array[1] != 1) &&
1204 (array[2] != 0) && (array[3] != 0)) {
1205 System.out.println("partialLooping failed!");
1206 }
1207
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001208 caught = false;
1209 main = new Main();
1210 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001211 main.foo6(new int[10], 2, 8, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001212 } catch (ArrayIndexOutOfBoundsException e) {
1213 caught = true;
1214 }
1215 if (!caught) {
1216 System.out.println("foo6 exception failed!");
1217 }
1218
1219 caught = false;
1220 main = new Main();
1221 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001222 main.foo6(new int[10], 1, 7, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001223 } catch (ArrayIndexOutOfBoundsException e) {
1224 caught = true;
1225 }
1226 if (!caught) {
1227 System.out.println("foo6 exception failed!");
1228 }
1229
1230 }
1231
Mingyao Yang718493c2015-07-22 15:56:34 -07001232 public void testExceptionMessage() {
1233 short[] B1 = new short[5];
1234 int[] B2 = new int[5];
1235 Exception err = null;
1236 try {
1237 testExceptionMessage1(B1, B2, null, -1, 6);
1238 } catch (Exception e) {
1239 err = e;
1240 }
1241 System.out.println(err);
1242 }
1243
1244 void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) {
1245 int j = finish + 77;
1246 // Bug: 22665511
1247 // A deoptimization will be triggered here right before the loop. Need to make
1248 // sure the value of j is preserved for the interpreter.
1249 for (int i = start; i <= finish; i++) {
1250 a2[j - 1] = a1[i + 1];
1251 }
1252 }
1253
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001254 // Make sure this method is compiled with optimizing.
David Brazdila06d66a2015-05-28 11:14:54 +01001255 /// CHECK-START: void Main.main(java.lang.String[]) register (after)
1256 /// CHECK: ParallelMove
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001257
Mingyao Yang0304e182015-01-30 16:41:29 -08001258 public static void main(String[] args) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001259 System.loadLibrary(args[0]);
1260
1261 if (!compiledWithOptimizing() ||
1262 !hasOatFile() ||
1263 runtimeIsSoftFail() ||
1264 isInterpreted()) {
1265 disableStackFrameAsserts();
1266 }
1267
Mingyao Yang0304e182015-01-30 16:41:29 -08001268 sieve(20);
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001269
1270 int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
1271 bubbleSort(array);
1272 for (int i = 0; i < 8; i++) {
1273 if (array[i] != i) {
1274 System.out.println("bubble sort failed!");
1275 }
1276 }
1277
Aart Bik5d75afe2015-12-14 11:57:01 -08001278 mA = new int[4][4];
1279 for (int i = 0; i < 4; i++) {
1280 for (int j = 0; j < 4; j++) {
1281 mA[i][j] = -1;
1282 }
1283 }
1284 dynamicBCEAndIntrinsic(4);
1285 for (int i = 0; i < 4; i++) {
1286 for (int j = 0; j < 4; j++) {
1287 if (mA[i][i] != 1) {
1288 System.out.println("dynamic bce failed!");
1289 }
1290 }
1291 }
1292
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001293 array = new int[7];
1294 pyramid1(array);
1295 if (!isPyramid(array)) {
1296 System.out.println("pyramid1 failed!");
1297 }
1298
1299 array = new int[8];
1300 pyramid2(array);
1301 if (!isPyramid(array)) {
1302 System.out.println("pyramid2 failed!");
1303 }
1304
1305 java.util.Arrays.fill(array, -1);
1306 pyramid3(array);
1307 if (!isPyramid(array)) {
1308 System.out.println("pyramid3 failed!");
1309 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001310
1311 // Make sure this value is kept after deoptimization.
1312 int i = 1;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001313 if (foo() + i != 100) {
1314 System.out.println("foo failed!");
1315 };
1316
1317 testUnknownBounds();
Mingyao Yang718493c2015-07-22 15:56:34 -07001318 new Main().testExceptionMessage();
Mingyao Yang0304e182015-01-30 16:41:29 -08001319 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001320
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001321 public static native boolean compiledWithOptimizing();
1322 public static native void disableStackFrameAsserts();
1323 public static native void assertIsManaged();
1324 public static native void assertIsInterpreted();
1325 public static native boolean hasOatFile();
1326 public static native boolean runtimeIsSoftFail();
1327 public static native boolean isInterpreted();
Mingyao Yang0304e182015-01-30 16:41:29 -08001328}