blob: 6e7ba406e0c37252c67ab25e76b4d073c5cc0b4e [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
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
Andreas Gampe639bdd12015-06-03 11:22:45 -0700252 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (before)
253 /// CHECK: BoundsCheck
254 /// CHECK: ArraySet
255 /// CHECK: BoundsCheck
256 /// CHECK: ArraySet
257
258 /// CHECK-START: void Main.constantIndexing6(int[]) BCE (after)
259 /// CHECK: Deoptimize
260
261 static void constantIndexing6(int[] array) {
262 array[3] = 1;
263 array[4] = 1;
264 }
265
266 // A helper into which the actual throwing function should be inlined.
267 static void constantIndexingForward6(int[] array) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700268 assertIsManaged();
Andreas Gampe639bdd12015-06-03 11:22:45 -0700269 constantIndexing6(array);
270 }
271
David Brazdila06d66a2015-05-28 11:14:54 +0100272 /// CHECK-START: void Main.loopPattern1(int[]) BCE (before)
273 /// CHECK: BoundsCheck
274 /// CHECK: ArraySet
275 /// CHECK: BoundsCheck
276 /// CHECK: ArraySet
277 /// CHECK: BoundsCheck
278 /// CHECK: ArraySet
279 /// CHECK: BoundsCheck
280 /// CHECK: ArraySet
281 /// CHECK: BoundsCheck
282 /// CHECK: ArraySet
283 /// CHECK: BoundsCheck
284 /// CHECK: ArraySet
285 /// CHECK: BoundsCheck
286 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800287
David Brazdila06d66a2015-05-28 11:14:54 +0100288 /// CHECK-START: void Main.loopPattern1(int[]) BCE (after)
289 /// CHECK-NOT: BoundsCheck
290 /// CHECK: ArraySet
291 /// CHECK-NOT: BoundsCheck
292 /// CHECK: ArraySet
293 /// CHECK-NOT: BoundsCheck
294 /// CHECK: ArraySet
295 /// CHECK: BoundsCheck
296 /// CHECK: ArraySet
297 /// CHECK: BoundsCheck
298 /// CHECK: ArraySet
299 /// CHECK: BoundsCheck
300 /// CHECK: ArraySet
301 /// CHECK-NOT: BoundsCheck
302 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800303
304 static void loopPattern1(int[] array) {
305 for (int i = 0; i < array.length; i++) {
306 array[i] = 1; // Bounds check can be eliminated.
307 }
308
309 for (int i = 1; i < array.length; i++) {
310 array[i] = 1; // Bounds check can be eliminated.
311 }
312
313 for (int i = 1; i < array.length - 1; i++) {
314 array[i] = 1; // Bounds check can be eliminated.
315 }
316
317 for (int i = -1; i < array.length; i++) {
318 array[i] = 1; // Bounds check can't be eliminated.
319 }
320
321 for (int i = 0; i <= array.length; i++) {
322 array[i] = 1; // Bounds check can't be eliminated.
323 }
324
325 for (int i = 0; i < array.length; i += 2) {
326 // We don't have any assumption on max array length yet.
327 // Bounds check can't be eliminated due to overflow concern.
328 array[i] = 1;
329 }
330
331 for (int i = 1; i < array.length; i += 2) {
332 // Bounds check can be eliminated since i is odd so the last
333 // i that's less than array.length is at most (Integer.MAX_VALUE - 2).
334 array[i] = 1;
335 }
336 }
337
338
David Brazdila06d66a2015-05-28 11:14:54 +0100339 /// CHECK-START: void Main.loopPattern2(int[]) BCE (before)
340 /// CHECK: BoundsCheck
341 /// CHECK: ArraySet
342 /// CHECK: BoundsCheck
343 /// CHECK: ArraySet
344 /// CHECK: BoundsCheck
345 /// CHECK: ArraySet
346 /// CHECK: BoundsCheck
347 /// CHECK: ArraySet
348 /// CHECK: BoundsCheck
349 /// CHECK: ArraySet
350 /// CHECK: BoundsCheck
351 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800352
David Brazdila06d66a2015-05-28 11:14:54 +0100353 /// CHECK-START: void Main.loopPattern2(int[]) BCE (after)
354 /// CHECK-NOT: BoundsCheck
355 /// CHECK: ArraySet
356 /// CHECK-NOT: BoundsCheck
357 /// CHECK: ArraySet
358 /// CHECK-NOT: BoundsCheck
359 /// CHECK: ArraySet
360 /// CHECK: BoundsCheck
361 /// CHECK: ArraySet
362 /// CHECK: BoundsCheck
363 /// CHECK: ArraySet
364 /// CHECK-NOT: BoundsCheck
365 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800366
367 static void loopPattern2(int[] array) {
368 for (int i = array.length - 1; i >= 0; i--) {
369 array[i] = 1; // Bounds check can be eliminated.
370 }
371
372 for (int i = array.length; i > 0; i--) {
373 array[i - 1] = 1; // Bounds check can be eliminated.
374 }
375
376 for (int i = array.length - 1; i > 0; i--) {
377 array[i] = 1; // Bounds check can be eliminated.
378 }
379
380 for (int i = array.length; i >= 0; i--) {
381 array[i] = 1; // Bounds check can't be eliminated.
382 }
383
384 for (int i = array.length; i >= 0; i--) {
385 array[i - 1] = 1; // Bounds check can't be eliminated.
386 }
387
388 for (int i = array.length; i > 0; i -= 20) {
389 // For i >= 0, (i - 20 - 1) is guaranteed not to underflow.
390 array[i - 1] = 1; // Bounds check can be eliminated.
391 }
392 }
393
394
David Brazdila06d66a2015-05-28 11:14:54 +0100395 /// CHECK-START: void Main.loopPattern3(int[]) BCE (before)
396 /// CHECK: BoundsCheck
397 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800398
David Brazdila06d66a2015-05-28 11:14:54 +0100399 /// CHECK-START: void Main.loopPattern3(int[]) BCE (after)
400 /// CHECK: BoundsCheck
401 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800402
403 static void loopPattern3(int[] array) {
404 java.util.Random random = new java.util.Random();
405 for (int i = 0; ; i++) {
406 if (random.nextInt() % 1000 == 0 && i < array.length) {
407 // Can't eliminate the bound check since not every i++ is
408 // matched with a array length check, so there is some chance that i
409 // overflows and is negative.
410 array[i] = 1;
411 }
412 }
413 }
414
415
David Brazdila06d66a2015-05-28 11:14:54 +0100416 /// CHECK-START: void Main.constantNewArray() BCE (before)
417 /// CHECK: BoundsCheck
418 /// CHECK: ArraySet
419 /// CHECK: BoundsCheck
420 /// CHECK: ArraySet
421 /// CHECK: BoundsCheck
422 /// CHECK: ArraySet
423 /// CHECK: BoundsCheck
424 /// CHECK: ArraySet
425 /// CHECK: BoundsCheck
426 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800427
David Brazdila06d66a2015-05-28 11:14:54 +0100428 /// CHECK-START: void Main.constantNewArray() BCE (after)
429 /// CHECK-NOT: BoundsCheck
430 /// CHECK: ArraySet
431 /// CHECK: BoundsCheck
432 /// CHECK: ArraySet
433 /// CHECK-NOT: BoundsCheck
434 /// CHECK: ArraySet
435 /// CHECK-NOT: BoundsCheck
436 /// CHECK: ArraySet
437 /// CHECK: BoundsCheck
438 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800439
440 static void constantNewArray() {
441 int[] array = new int[10];
442 for (int i = 0; i < 10; i++) {
443 array[i] = 1; // Bounds check can be eliminated.
444 }
445
446 for (int i = 0; i <= 10; i++) {
447 array[i] = 1; // Bounds check can't be eliminated.
448 }
449
450 array[0] = 1; // Bounds check can be eliminated.
451 array[9] = 1; // Bounds check can be eliminated.
452 array[10] = 1; // Bounds check can't be eliminated.
453 }
454
Mingyao Yang4559f002015-02-27 14:43:53 -0800455
456 static byte readData() {
457 return 1;
458 }
459
David Brazdila06d66a2015-05-28 11:14:54 +0100460 /// CHECK-START: void Main.circularBufferProducer() BCE (before)
461 /// CHECK: BoundsCheck
462 /// CHECK: ArraySet
Mingyao Yang4559f002015-02-27 14:43:53 -0800463
David Brazdila06d66a2015-05-28 11:14:54 +0100464 /// CHECK-START: void Main.circularBufferProducer() BCE (after)
465 /// CHECK-NOT: BoundsCheck
466 /// CHECK: ArraySet
Mingyao Yang4559f002015-02-27 14:43:53 -0800467
468 static void circularBufferProducer() {
469 byte[] array = new byte[4096];
470 int i = 0;
471 while (true) {
472 array[i & (array.length - 1)] = readData();
473 i++;
474 }
475 }
476
477
David Brazdila06d66a2015-05-28 11:14:54 +0100478 /// CHECK-START: void Main.pyramid1(int[]) BCE (before)
479 /// CHECK: BoundsCheck
480 /// CHECK: ArraySet
481 /// CHECK: BoundsCheck
482 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800483
David Brazdila06d66a2015-05-28 11:14:54 +0100484 /// CHECK-START: void Main.pyramid1(int[]) BCE (after)
485 /// CHECK-NOT: BoundsCheck
486 /// CHECK: ArraySet
487 /// CHECK-NOT: BoundsCheck
488 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800489
490 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
491 static void pyramid1(int[] array) {
492 for (int i = 0; i < (array.length + 1) / 2; i++) {
493 array[i] = i;
494 array[array.length - 1 - i] = i;
495 }
496 }
497
498
David Brazdila06d66a2015-05-28 11:14:54 +0100499 /// CHECK-START: void Main.pyramid2(int[]) BCE (before)
500 /// CHECK: BoundsCheck
501 /// CHECK: ArraySet
502 /// CHECK: BoundsCheck
503 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800504
David Brazdila06d66a2015-05-28 11:14:54 +0100505 /// CHECK-START: void Main.pyramid2(int[]) BCE (after)
506 /// CHECK-NOT: BoundsCheck
507 /// CHECK: ArraySet
508 /// CHECK-NOT: BoundsCheck
509 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800510
511 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
512 static void pyramid2(int[] array) {
513 for (int i = 0; i < (array.length + 1) >> 1; i++) {
514 array[i] = i;
515 array[array.length - 1 - i] = i;
516 }
517 }
518
519
David Brazdila06d66a2015-05-28 11:14:54 +0100520 /// CHECK-START: void Main.pyramid3(int[]) BCE (before)
521 /// CHECK: BoundsCheck
522 /// CHECK: ArraySet
523 /// CHECK: BoundsCheck
524 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800525
David Brazdila06d66a2015-05-28 11:14:54 +0100526 /// CHECK-START: void Main.pyramid3(int[]) BCE (after)
527 /// CHECK-NOT: BoundsCheck
528 /// CHECK: ArraySet
529 /// CHECK-NOT: BoundsCheck
530 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800531
532 // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
533 static void pyramid3(int[] array) {
534 for (int i = 0; i < (array.length + 1) >>> 1; i++) {
535 array[i] = i;
536 array[array.length - 1 - i] = i;
537 }
538 }
539
540
David Brazdila06d66a2015-05-28 11:14:54 +0100541 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
542 /// CHECK: BoundsCheck
543 /// CHECK: ArrayGet
544 /// CHECK: BoundsCheck
545 /// CHECK: ArrayGet
Mingyao Yang57e04752015-02-09 18:13:26 -0800546
David Brazdila06d66a2015-05-28 11:14:54 +0100547 /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
548 /// CHECK-NOT: BoundsCheck
549 /// CHECK: ArrayGet
550 /// CHECK-NOT: BoundsCheck
551 /// CHECK: ArrayGet
Mingyao Yang57e04752015-02-09 18:13:26 -0800552
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800553 static boolean isPyramid(int[] array) {
554 int i = 0;
555 int j = array.length - 1;
556 while (i <= j) {
557 if (array[i] != i) {
558 return false;
559 }
560 if (array[j] != i) {
561 return false;
562 }
563 i++; j--;
564 }
565 return true;
566 }
567
568
David Brazdila06d66a2015-05-28 11:14:54 +0100569 /// CHECK-START: void Main.bubbleSort(int[]) GVN (before)
570 /// CHECK: BoundsCheck
571 /// CHECK: ArrayGet
572 /// CHECK: BoundsCheck
573 /// CHECK: ArrayGet
574 /// CHECK: BoundsCheck
575 /// CHECK: ArrayGet
576 /// CHECK: BoundsCheck
577 /// CHECK: ArrayGet
578 /// CHECK: BoundsCheck
579 /// CHECK: ArraySet
580 /// CHECK: BoundsCheck
581 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800582
David Brazdila06d66a2015-05-28 11:14:54 +0100583 /// CHECK-START: void Main.bubbleSort(int[]) GVN (after)
584 /// CHECK: BoundsCheck
585 /// CHECK: ArrayGet
586 /// CHECK: BoundsCheck
587 /// CHECK: ArrayGet
588 /// CHECK-NOT: ArrayGet
589 /// CHECK-NOT: ArrayGet
590 /// CHECK-NOT: BoundsCheck
591 /// CHECK: ArraySet
592 /// CHECK-NOT: BoundsCheck
593 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800594
David Brazdila06d66a2015-05-28 11:14:54 +0100595 /// CHECK-START: void Main.bubbleSort(int[]) BCE (after)
596 /// CHECK-NOT: BoundsCheck
597 /// CHECK: ArrayGet
598 /// CHECK-NOT: BoundsCheck
599 /// CHECK: ArrayGet
600 /// CHECK-NOT: ArrayGet
601 /// CHECK-NOT: ArrayGet
602 /// CHECK-NOT: BoundsCheck
603 /// CHECK: ArraySet
604 /// CHECK-NOT: BoundsCheck
605 /// CHECK: ArraySet
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800606
607 static void bubbleSort(int[] array) {
608 for (int i = 0; i < array.length - 1; i++) {
609 for (int j = 0; j < array.length - i - 1; j++) {
610 if (array[j] > array[j + 1]) {
611 int temp = array[j + 1];
612 array[j + 1] = array[j];
613 array[j] = temp;
614 }
615 }
616 }
617 }
618
Aart Bik5d75afe2015-12-14 11:57:01 -0800619 static int[][] mA;
620
621 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before)
622 /// CHECK-DAG: NullCheck
623 /// CHECK-DAG: ArrayLength
624 /// CHECK-DAG: BoundsCheck
625 /// CHECK-DAG: ArrayGet
626 /// CHECK-DAG: NullCheck
627 /// CHECK-DAG: ArrayLength
628 /// CHECK-DAG: BoundsCheck
629 /// CHECK-DAG: ArrayGet
630 /// CHECK-DAG: InvokeStaticOrDirect
631 /// CHECK-DAG: ArraySet
632
633 /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
634 /// CHECK-NOT: NullCheck
635 /// CHECK-NOT: ArrayLength
636 /// CHECK-NOT: BoundsCheck
637 /// CHECK-DAG: ArrayGet
638 /// CHECK-NOT: ArrayGet
639 /// CHECK-DAG: InvokeStaticOrDirect
640 /// CHECK-DAG: ArraySet
641 /// CHECK-DAG: Exit
642 /// CHECK-DAG: Deoptimize
643
644 static void dynamicBCEAndIntrinsic(int n) {
645 for (int i = 0; i < n; i++) {
646 for (int j = 0; j < n; j++) {
647 // Since intrinsic call cannot modify fields or arrays,
648 // dynamic BCE and hoisting can be applied to the inner loop.
649 mA[i][j] = Math.abs(mA[i][j]);
650 }
651 }
652 }
Mingyao Yang8c8bad82015-02-09 18:13:26 -0800653
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700654 static int foo() {
655 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700656 assertIsManaged();
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700657 // This will cause AIOOBE.
658 constantIndexing2(new int[3]);
659 } catch (ArrayIndexOutOfBoundsException e) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700660 assertIsManaged(); // This is to ensure that single-frame deoptimization works.
David Brazdil95177982015-10-30 12:56:58 -0500661 // Will need to be updated if constantIndexing2 is inlined.
Andreas Gampe639bdd12015-06-03 11:22:45 -0700662 try {
663 // This will cause AIOOBE.
664 constantIndexingForward6(new int[3]);
665 } catch (ArrayIndexOutOfBoundsException e2) {
David Brazdil95177982015-10-30 12:56:58 -0500666 // Having deopted, we expect to be running interpreted at this point.
667 // Does not apply to debuggable, however, since we do not inline.
Andreas Gampe639bdd12015-06-03 11:22:45 -0700668 return 99;
669 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -0700670 }
671 return 0;
672 }
673
674
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700675 int sum;
676
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700677 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100678 /// CHECK: BoundsCheck
679 /// CHECK: ArraySet
680 /// CHECK-NOT: BoundsCheck
681 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700682
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700683 /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100684 /// CHECK: Phi
685 /// CHECK-NOT: BoundsCheck
686 /// CHECK: ArraySet
687 /// CHECK-NOT: BoundsCheck
688 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800689 // Added blocks at end for deoptimization.
690 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700691 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -0700692 /// CHECK: Deoptimize
693 /// CHECK: Deoptimize
694 /// CHECK: Deoptimize
695 /// CHECK-NOT: Deoptimize
696 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800697 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700698 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700699
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700700 void foo1(int[] array, int start, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800701 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700702 // and one for null check on array (to hoist null
703 // check and array.length out of loop).
704 for (int i = start ; i < end; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700705 if (expectInterpreter) {
706 assertIsInterpreted();
707 } else {
708 assertIsManaged();
709 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700710 array[i] = 1;
711 sum += array[i];
712 }
713 }
714
715
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700716 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100717 /// CHECK: BoundsCheck
718 /// CHECK: ArraySet
719 /// CHECK-NOT: BoundsCheck
720 /// CHECK: ArrayGet
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700721 /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100722 /// CHECK: Phi
723 /// CHECK-NOT: BoundsCheck
724 /// CHECK: ArraySet
725 /// CHECK-NOT: BoundsCheck
726 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800727 // Added blocks at end for deoptimization.
728 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700729 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -0700730 /// CHECK: Deoptimize
731 /// CHECK: Deoptimize
732 /// CHECK: Deoptimize
733 /// CHECK-NOT: Deoptimize
734 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800735 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700736 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700737
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700738 void foo2(int[] array, int start, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800739 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700740 // and one for null check on array (to hoist null
741 // check and array.length out of loop).
742 for (int i = start ; i <= end; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700743 if (expectInterpreter) {
744 assertIsInterpreted();
745 } else {
746 assertIsManaged();
747 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700748 array[i] = 1;
749 sum += array[i];
750 }
751 }
752
753
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700754 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100755 /// CHECK: BoundsCheck
756 /// CHECK: ArraySet
757 /// CHECK-NOT: BoundsCheck
758 /// CHECK: ArrayGet
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700759 /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100760 /// CHECK: Phi
761 /// CHECK-NOT: BoundsCheck
762 /// CHECK: ArraySet
763 /// CHECK-NOT: BoundsCheck
764 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800765 // Added blocks at end for deoptimization.
766 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700767 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800768 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700769 /// CHECK: Deoptimize
770 /// CHECK: Deoptimize
771 /// CHECK-NOT: Deoptimize
772 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800773 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700774 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700775
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700776 void foo3(int[] array, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800777 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700778 // and one for null check on array (to hoist null check
779 // and array.length out of loop).
780 for (int i = 3 ; i <= end; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700781 if (expectInterpreter) {
782 assertIsInterpreted();
783 } else {
784 assertIsManaged();
785 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700786 array[i] = 1;
787 sum += array[i];
788 }
789 }
790
Mingyao Yang3584bce2015-05-19 16:01:59 -0700791
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700792 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100793 /// CHECK: BoundsCheck
794 /// CHECK: ArraySet
795 /// CHECK-NOT: BoundsCheck
796 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700797
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700798 /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100799 /// CHECK: Phi
800 /// CHECK-NOT: BoundsCheck
801 /// CHECK: ArraySet
802 /// CHECK-NOT: BoundsCheck
803 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800804 // Added blocks at end for deoptimization.
805 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700806 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800807 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700808 /// CHECK: Deoptimize
809 /// CHECK: Deoptimize
810 /// CHECK-NOT: Deoptimize
811 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800812 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700813 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700814
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700815 void foo4(int[] array, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800816 // Three HDeoptimize will be added. Two for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700817 // and one for null check on array (to hoist null check
818 // and array.length out of loop).
819 for (int i = end ; i > 0; i--) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700820 if (expectInterpreter) {
821 assertIsInterpreted();
822 } else {
823 assertIsManaged();
824 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700825 array[i - 1] = 1;
826 sum += array[i - 1];
827 }
828 }
829
830
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700831 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100832 /// CHECK: BoundsCheck
833 /// CHECK: ArraySet
834 /// CHECK: BoundsCheck
835 /// CHECK: ArrayGet
836 /// CHECK: BoundsCheck
837 /// CHECK: ArrayGet
838 /// CHECK: BoundsCheck
839 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700840
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700841 /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100842 /// CHECK-NOT: BoundsCheck
843 /// CHECK: ArraySet
David Brazdila06d66a2015-05-28 11:14:54 +0100844 /// CHECK: Phi
845 /// CHECK-NOT: BoundsCheck
846 /// CHECK: ArrayGet
847 /// CHECK-NOT: BoundsCheck
848 /// CHECK: ArrayGet
849 /// CHECK-NOT: BoundsCheck
850 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800851 // Added blocks at end for deoptimization.
852 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700853 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800854 /// CHECK: Deoptimize
855 /// CHECK: Deoptimize
856 /// CHECK: Deoptimize
857 /// CHECK: Deoptimize
858 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700859 /// CHECK: Deoptimize
860 /// CHECK-NOT: Deoptimize
861 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800862 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700863 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700864
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700865 void foo5(int[] array, int end, boolean expectInterpreter) {
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700866 // Bounds check in this loop can be eliminated without deoptimization.
867 for (int i = array.length - 1 ; i >= 0; i--) {
868 array[i] = 1;
869 }
Aart Bik4a342772015-11-30 10:17:46 -0800870 // Several HDeoptimize will be added. Two for each index.
871 // The null check is not necessary.
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700872 for (int i = end - 2 ; i > 0; i--) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700873 if (expectInterpreter) {
874 assertIsInterpreted();
875 } else {
876 assertIsManaged();
877 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700878 sum += array[i - 1];
879 sum += array[i];
880 sum += array[i + 1];
881 }
882 }
883
884
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700885 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before)
David Brazdila06d66a2015-05-28 11:14:54 +0100886 /// CHECK: BoundsCheck
887 /// CHECK: ArrayGet
888 /// CHECK: BoundsCheck
889 /// CHECK: ArrayGet
890 /// CHECK: BoundsCheck
891 /// CHECK: ArrayGet
892 /// CHECK: BoundsCheck
893 /// CHECK: ArrayGet
894 /// CHECK: BoundsCheck
895 /// CHECK: ArrayGet
896 /// CHECK-NOT: BoundsCheck
897 /// CHECK: ArraySet
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700898 /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100899 /// CHECK: Phi
900 /// CHECK-NOT: BoundsCheck
901 /// CHECK: ArrayGet
902 /// CHECK-NOT: BoundsCheck
903 /// CHECK: ArrayGet
904 /// CHECK-NOT: BoundsCheck
905 /// CHECK: ArrayGet
906 /// CHECK-NOT: BoundsCheck
907 /// CHECK: ArrayGet
908 /// CHECK-NOT: BoundsCheck
909 /// CHECK: ArrayGet
910 /// CHECK-NOT: BoundsCheck
911 /// CHECK: ArraySet
Aart Bik4a342772015-11-30 10:17:46 -0800912 // Added blocks at end for deoptimization.
913 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700914 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800915 /// CHECK: Deoptimize
916 /// CHECK: Deoptimize
917 /// CHECK: Deoptimize
918 /// CHECK: Deoptimize
919 /// CHECK: Deoptimize
920 /// CHECK: Deoptimize
921 /// CHECK: Deoptimize
922 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -0700923 /// CHECK: Deoptimize
924 /// CHECK: Deoptimize
925 /// CHECK: Deoptimize
926 /// CHECK-NOT: Deoptimize
927 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700928 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800929 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700930
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700931 void foo6(int[] array, int start, int end, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -0800932 // Several HDeoptimize will be added.
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700933 for (int i = end; i >= start; i--) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -0700934 if (expectInterpreter) {
935 assertIsInterpreted();
936 } else {
937 assertIsManaged();
938 }
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700939 array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5;
940 }
941 }
942
943
David Brazdila06d66a2015-05-28 11:14:54 +0100944 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
945 /// CHECK: BoundsCheck
946 /// CHECK: ArrayGet
947 /// CHECK: BoundsCheck
948 /// CHECK: ArrayGet
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700949
David Brazdila06d66a2015-05-28 11:14:54 +0100950 /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
David Brazdila06d66a2015-05-28 11:14:54 +0100951 /// CHECK: Phi
952 /// CHECK: BoundsCheck
953 /// CHECK: ArrayGet
954 /// CHECK-NOT: BoundsCheck
955 /// CHECK: ArrayGet
Aart Bik4a342772015-11-30 10:17:46 -0800956 // Added blocks at end for deoptimization.
957 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700958 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -0700959 /// CHECK: Deoptimize
960 /// CHECK: Deoptimize
961 /// CHECK: Deoptimize
962 /// CHECK-NOT: Deoptimize
963 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -0800964 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -0700965 /// CHECK: Goto
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700966
967 void foo7(int[] array, int start, int end, boolean lowEnd) {
Aart Bik4a342772015-11-30 10:17:46 -0800968 // Three HDeoptimize will be added. One for the index
Mingyao Yang206d6fd2015-04-13 16:46:28 -0700969 // and one for null check on array (to hoist null
970 // check and array.length out of loop).
971 for (int i = start ; i < end; i++) {
972 if (lowEnd) {
973 // This array access isn't certain. So we don't
974 // use +1000 offset in decision making for deoptimization
975 // conditions.
976 sum += array[i + 1000];
977 }
978 sum += array[i];
979 }
980 }
981
982
Mingyao Yang3584bce2015-05-19 16:01:59 -0700983 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before)
984 /// CHECK: BoundsCheck
985 /// CHECK: ArrayGet
986 /// CHECK: BoundsCheck
987 /// CHECK: ArraySet
988
989 /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after)
990 /// CHECK: Phi
991 /// CHECK-NOT: BoundsCheck
992 /// CHECK: ArrayGet
993 /// CHECK: Phi
994 /// CHECK-NOT: BoundsCheck
995 /// CHECK: ArraySet
Aart Bik4a342772015-11-30 10:17:46 -0800996 // Added blocks at end for deoptimization.
997 /// CHECK: Exit
Mingyao Yang3584bce2015-05-19 16:01:59 -0700998 /// CHECK: If
Aart Bik4a342772015-11-30 10:17:46 -0800999 /// CHECK: Deoptimize
1000 /// CHECK: Deoptimize
1001 /// CHECK: Deoptimize
Aart Bikd59c7062015-11-21 05:21:52 +00001002 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -08001003 /// CHECK: Goto
1004 /// CHECK: Goto
1005 /// CHECK: If
Mingyao Yang3584bce2015-05-19 16:01:59 -07001006 /// CHECK: Deoptimize
1007 /// CHECK: Deoptimize
1008 /// CHECK: Deoptimize
1009 /// CHECK-NOT: Deoptimize
1010 /// CHECK: Goto
Aart Bik4a342772015-11-30 10:17:46 -08001011 /// CHECK: Goto
Mingyao Yang3584bce2015-05-19 16:01:59 -07001012 /// CHECK: Goto
1013
1014 void foo8(int[][] matrix, int start, int end) {
Aart Bik4a342772015-11-30 10:17:46 -08001015 // Three HDeoptimize will be added for the outer loop,
1016 // two for the index, and null check on matrix. Same
1017 // for the inner loop.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001018 for (int i = start; i < end; i++) {
1019 int[] row = matrix[i];
1020 for (int j = start; j < end; j++) {
1021 row[j] = 1;
1022 }
1023 }
1024 }
1025
1026
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001027 /// CHECK-START: void Main.foo9(int[], boolean) BCE (before)
Mingyao Yang3584bce2015-05-19 16:01:59 -07001028 /// CHECK: NullCheck
1029 /// CHECK: BoundsCheck
1030 /// CHECK: ArrayGet
1031
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001032 /// CHECK-START: void Main.foo9(int[], boolean) BCE (after)
Mingyao Yang3584bce2015-05-19 16:01:59 -07001033 // The loop is guaranteed to be entered. No need to transform the
1034 // loop for loop body entry test.
1035 /// CHECK: Deoptimize
1036 /// CHECK: Deoptimize
Aart Bik4a342772015-11-30 10:17:46 -08001037 /// CHECK: Deoptimize
Mingyao Yang3584bce2015-05-19 16:01:59 -07001038 /// CHECK-NOT: Deoptimize
1039 /// CHECK: Phi
1040 /// CHECK-NOT: NullCheck
1041 /// CHECK-NOT: BoundsCheck
1042 /// CHECK: ArrayGet
1043
Aart Bik4a342772015-11-30 10:17:46 -08001044 /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier_after_bce (after)
1045 // Simplification removes the redundant check
1046 /// CHECK: Deoptimize
1047 /// CHECK: Deoptimize
1048 /// CHECK-NOT: Deoptimize
1049
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001050 void foo9(int[] array, boolean expectInterpreter) {
Aart Bik4a342772015-11-30 10:17:46 -08001051 // Two HDeoptimize will be added. Two for the index
1052 // and one for null check on array.
Mingyao Yang3584bce2015-05-19 16:01:59 -07001053 for (int i = 0 ; i < 10; i++) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001054 if (expectInterpreter) {
1055 assertIsInterpreted();
1056 } else {
1057 assertIsManaged();
1058 }
Mingyao Yang3584bce2015-05-19 16:01:59 -07001059 sum += array[i];
1060 }
1061 }
1062
1063
David Brazdila06d66a2015-05-28 11:14:54 +01001064 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
1065 /// CHECK: BoundsCheck
1066 /// CHECK: ArraySet
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001067
David Brazdila06d66a2015-05-28 11:14:54 +01001068 /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
1069 /// CHECK-NOT: Deoptimize
1070 /// CHECK: BoundsCheck
1071 /// CHECK: ArraySet
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001072
1073 void partialLooping(int[] array, int start, int end) {
1074 // This loop doesn't cover the full range of [start, end) so
1075 // adding deoptimization is too aggressive, since end can be
1076 // greater than array.length but the loop is never going to work on
1077 // more than 2 elements.
1078 for (int i = start; i < end; i++) {
1079 if (i == 2) {
1080 return;
1081 }
1082 array[i] = 1;
1083 }
1084 }
1085
1086
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001087 static void testUnknownBounds() {
1088 boolean caught = false;
1089 Main main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001090 main.foo1(new int[10], 0, 10, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001091 if (main.sum != 10) {
1092 System.out.println("foo1 failed!");
1093 }
1094
1095 caught = false;
1096 main = new Main();
1097 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001098 main.foo1(new int[10], 0, 11, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001099 } catch (ArrayIndexOutOfBoundsException e) {
1100 caught = true;
1101 }
1102 if (!caught || main.sum != 10) {
1103 System.out.println("foo1 exception failed!");
1104 }
1105
1106 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001107 main.foo2(new int[10], 0, 9, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001108 if (main.sum != 10) {
1109 System.out.println("foo2 failed!");
1110 }
1111
1112 caught = false;
1113 main = new Main();
1114 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001115 main.foo2(new int[10], 0, 10, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001116 } catch (ArrayIndexOutOfBoundsException e) {
1117 caught = true;
1118 }
1119 if (!caught || main.sum != 10) {
1120 System.out.println("foo2 exception failed!");
1121 }
1122
1123 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001124 main.foo3(new int[10], 9, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001125 if (main.sum != 7) {
1126 System.out.println("foo3 failed!");
1127 }
1128
1129 caught = false;
1130 main = new Main();
1131 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001132 main.foo3(new int[10], 10, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001133 } catch (ArrayIndexOutOfBoundsException e) {
1134 caught = true;
1135 }
1136 if (!caught || main.sum != 7) {
1137 System.out.println("foo3 exception failed!");
1138 }
1139
1140 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001141 main.foo4(new int[10], 10, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001142 if (main.sum != 10) {
1143 System.out.println("foo4 failed!");
1144 }
1145
1146 caught = false;
1147 main = new Main();
1148 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001149 main.foo4(new int[10], 11, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001150 } catch (ArrayIndexOutOfBoundsException e) {
1151 caught = true;
1152 }
1153 if (!caught || main.sum != 0) {
1154 System.out.println("foo4 exception failed!");
1155 }
1156
1157 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001158 main.foo5(new int[10], 10, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001159 if (main.sum != 24) {
1160 System.out.println("foo5 failed!");
1161 }
1162
1163 caught = false;
1164 main = new Main();
1165 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001166 main.foo5(new int[10], 11, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001167 } catch (ArrayIndexOutOfBoundsException e) {
1168 caught = true;
1169 }
1170 if (!caught || main.sum != 2) {
1171 System.out.println("foo5 exception failed!");
1172 }
1173
1174 main = new Main();
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001175 main.foo6(new int[10], 2, 7, false);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001176
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001177 main = new Main();
Mingyao Yang3584bce2015-05-19 16:01:59 -07001178 int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001179 main.foo9(array9, false);
Mingyao Yang3584bce2015-05-19 16:01:59 -07001180 if (main.sum != 45) {
1181 System.out.println("foo9 failed!");
1182 }
1183
1184 main = new Main();
Mingyao Yang9d750ef2015-04-26 18:15:30 -07001185 int[] array = new int[4];
1186 main.partialLooping(new int[3], 0, 4);
1187 if ((array[0] != 1) && (array[1] != 1) &&
1188 (array[2] != 0) && (array[3] != 0)) {
1189 System.out.println("partialLooping failed!");
1190 }
1191
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001192 caught = false;
1193 main = new Main();
1194 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001195 main.foo6(new int[10], 2, 8, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001196 } catch (ArrayIndexOutOfBoundsException e) {
1197 caught = true;
1198 }
1199 if (!caught) {
1200 System.out.println("foo6 exception failed!");
1201 }
1202
1203 caught = false;
1204 main = new Main();
1205 try {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001206 main.foo6(new int[10], 1, 7, true);
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001207 } catch (ArrayIndexOutOfBoundsException e) {
1208 caught = true;
1209 }
1210 if (!caught) {
1211 System.out.println("foo6 exception failed!");
1212 }
1213
1214 }
1215
Mingyao Yang718493c2015-07-22 15:56:34 -07001216 public void testExceptionMessage() {
1217 short[] B1 = new short[5];
1218 int[] B2 = new int[5];
1219 Exception err = null;
1220 try {
1221 testExceptionMessage1(B1, B2, null, -1, 6);
1222 } catch (Exception e) {
1223 err = e;
1224 }
1225 System.out.println(err);
1226 }
1227
1228 void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) {
1229 int j = finish + 77;
1230 // Bug: 22665511
1231 // A deoptimization will be triggered here right before the loop. Need to make
1232 // sure the value of j is preserved for the interpreter.
1233 for (int i = start; i <= finish; i++) {
1234 a2[j - 1] = a1[i + 1];
1235 }
1236 }
1237
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001238 // Make sure this method is compiled with optimizing.
David Brazdila06d66a2015-05-28 11:14:54 +01001239 /// CHECK-START: void Main.main(java.lang.String[]) register (after)
1240 /// CHECK: ParallelMove
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001241
Mingyao Yang0304e182015-01-30 16:41:29 -08001242 public static void main(String[] args) {
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001243 System.loadLibrary(args[0]);
1244
1245 if (!compiledWithOptimizing() ||
1246 !hasOatFile() ||
1247 runtimeIsSoftFail() ||
1248 isInterpreted()) {
1249 disableStackFrameAsserts();
1250 }
1251
Mingyao Yang0304e182015-01-30 16:41:29 -08001252 sieve(20);
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001253
1254 int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
1255 bubbleSort(array);
1256 for (int i = 0; i < 8; i++) {
1257 if (array[i] != i) {
1258 System.out.println("bubble sort failed!");
1259 }
1260 }
1261
Aart Bik5d75afe2015-12-14 11:57:01 -08001262 mA = new int[4][4];
1263 for (int i = 0; i < 4; i++) {
1264 for (int j = 0; j < 4; j++) {
1265 mA[i][j] = -1;
1266 }
1267 }
1268 dynamicBCEAndIntrinsic(4);
1269 for (int i = 0; i < 4; i++) {
1270 for (int j = 0; j < 4; j++) {
1271 if (mA[i][i] != 1) {
1272 System.out.println("dynamic bce failed!");
1273 }
1274 }
1275 }
1276
Mingyao Yang8c8bad82015-02-09 18:13:26 -08001277 array = new int[7];
1278 pyramid1(array);
1279 if (!isPyramid(array)) {
1280 System.out.println("pyramid1 failed!");
1281 }
1282
1283 array = new int[8];
1284 pyramid2(array);
1285 if (!isPyramid(array)) {
1286 System.out.println("pyramid2 failed!");
1287 }
1288
1289 java.util.Arrays.fill(array, -1);
1290 pyramid3(array);
1291 if (!isPyramid(array)) {
1292 System.out.println("pyramid3 failed!");
1293 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001294
1295 // Make sure this value is kept after deoptimization.
1296 int i = 1;
Mingyao Yang206d6fd2015-04-13 16:46:28 -07001297 if (foo() + i != 100) {
1298 System.out.println("foo failed!");
1299 };
1300
1301 testUnknownBounds();
Mingyao Yang718493c2015-07-22 15:56:34 -07001302 new Main().testExceptionMessage();
Mingyao Yang0304e182015-01-30 16:41:29 -08001303 }
Mingyao Yangd43b3ac2015-04-01 14:03:04 -07001304
Andreas Gampe0dfc9bc2015-09-30 17:13:59 -07001305 public static native boolean compiledWithOptimizing();
1306 public static native void disableStackFrameAsserts();
1307 public static native void assertIsManaged();
1308 public static native void assertIsInterpreted();
1309 public static native boolean hasOatFile();
1310 public static native boolean runtimeIsSoftFail();
1311 public static native boolean isInterpreted();
Mingyao Yang0304e182015-01-30 16:41:29 -08001312}