1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17public class Main {
18
19  /// CHECK-START: int Main.sieve(int) BCE (before)
20  /// CHECK: BoundsCheck
21  /// CHECK: ArraySet
22  /// CHECK: BoundsCheck
23  /// CHECK: ArrayGet
24  /// CHECK: BoundsCheck
25  /// CHECK: ArraySet
26
27  /// CHECK-START: int Main.sieve(int) BCE (after)
28  /// CHECK-NOT: BoundsCheck
29  /// CHECK: ArraySet
30  /// CHECK-NOT: BoundsCheck
31  /// CHECK: ArrayGet
32  /// CHECK: BoundsCheck
33  /// CHECK: ArraySet
34
35  static int sieve(int size) {
36    int primeCount = 0;
37    boolean[] flags = new boolean[size + 1];
38    for (int i = 1; i < size; i++) flags[i] = true; // Can eliminate.
39    for (int i = 2; i < size; i++) {
40      if (flags[i]) { // Can eliminate.
41        primeCount++;
42        for (int k = i + 1; k <= size; k += i)
43          flags[k - 1] = false; // Can't eliminate yet due to (k+i) may overflow.
44      }
45    }
46    return primeCount;
47  }
48
49
50  /// CHECK-START: void Main.narrow(int[], int) BCE (before)
51  /// CHECK: BoundsCheck
52  /// CHECK: ArraySet
53  /// CHECK: BoundsCheck
54  /// CHECK: ArraySet
55  /// CHECK: BoundsCheck
56  /// CHECK: ArraySet
57
58  /// CHECK-START: void Main.narrow(int[], int) BCE (after)
59  /// CHECK-NOT: BoundsCheck
60  /// CHECK: ArraySet
61  /// CHECK-NOT: BoundsCheck
62  /// CHECK: ArraySet
63  /// CHECK: BoundsCheck
64  /// CHECK: ArraySet
65  /// CHECK-NOT: BoundsCheck
66  /// CHECK: ArraySet
67  /// CHECK: BoundsCheck
68  /// CHECK: ArraySet
69
70  static void narrow(int[] array, int offset) {
71    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      }
95
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      }
107    }
108  }
109
110
111  /// CHECK-START: void Main.constantIndexing1(int[]) BCE (before)
112  /// CHECK: BoundsCheck
113  /// CHECK: ArraySet
114  /// CHECK: BoundsCheck
115  /// CHECK: ArraySet
116
117  /// CHECK-START: void Main.constantIndexing1(int[]) BCE (after)
118  /// CHECK-NOT: Deoptimize
119  /// CHECK: BoundsCheck
120  /// CHECK: ArraySet
121  /// CHECK-NOT: BoundsCheck
122  /// CHECK: ArraySet
123
124  static void constantIndexing1(int[] array) {
125    // Decreasing order: bc for 5 but not for 4.
126    array[5] = 11;
127    array[4] = 11;
128  }
129
130
131  /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (before)
132  /// CHECK: BoundsCheck
133  /// CHECK: ArraySet
134  /// CHECK: BoundsCheck
135  /// CHECK: ArraySet
136  /// CHECK: BoundsCheck
137  /// CHECK: ArraySet
138  /// CHECK: BoundsCheck
139  /// CHECK: ArraySet
140
141  /// CHECK-START: void Main.$opt$noinline$constantIndexing2(int[]) BCE (after)
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
152  static void $opt$noinline$constantIndexing2(int[] array) {
153    array[1] = 1;
154    array[2] = 1;
155    array[3] = 1;
156    array[4] = 1;
157    if (array[1] != 1) {
158      throw new Error("");
159    }
160  }
161
162  /// CHECK-START: void Main.constantIndexing2b(int[]) BCE (before)
163  /// CHECK: BoundsCheck
164  /// CHECK: ArraySet
165  /// CHECK: BoundsCheck
166  /// CHECK: ArraySet
167  /// CHECK: BoundsCheck
168  /// CHECK: ArraySet
169  /// CHECK: BoundsCheck
170  /// CHECK: ArraySet
171  /// CHECK: BoundsCheck
172  /// CHECK: ArraySet
173
174  /// CHECK-START: void Main.constantIndexing2b(int[]) BCE (after)
175  /// CHECK-NOT: Deoptimize
176  /// CHECK: BoundsCheck
177  /// CHECK: ArraySet
178  /// CHECK: BoundsCheck
179  /// CHECK: ArraySet
180  /// CHECK: BoundsCheck
181  /// CHECK: ArraySet
182  /// CHECK: BoundsCheck
183  /// CHECK: ArraySet
184  /// CHECK: BoundsCheck
185  /// CHECK: ArraySet
186
187  static void constantIndexing2b(int[] array) {
188    array[0] = 6;
189    array[1] = 6;
190    array[2] = 6;
191    array[3] = 6;
192    array[-1] = 1;  // prevents the whole opt on [-1:4]
193  }
194
195  /// CHECK-START: void Main.constantIndexing2c(int[]) BCE (before)
196  /// CHECK: BoundsCheck
197  /// CHECK: ArraySet
198  /// CHECK: BoundsCheck
199  /// CHECK: ArraySet
200  /// CHECK: BoundsCheck
201  /// CHECK: ArraySet
202  /// CHECK: BoundsCheck
203  /// CHECK: ArraySet
204
205  /// CHECK-START: void Main.constantIndexing2c(int[]) BCE (after)
206  /// CHECK: Deoptimize
207  /// CHECK-NOT: BoundsCheck
208  /// CHECK: ArraySet
209  /// CHECK-NOT: BoundsCheck
210  /// CHECK: ArraySet
211  /// CHECK-NOT: BoundsCheck
212  /// CHECK: ArraySet
213  /// CHECK-NOT: BoundsCheck
214  /// CHECK: ArraySet
215
216  static void constantIndexing2c(int[] array) {
217    array[0] = 7;
218    array[1] = 7;
219    array[2] = 7;
220    array[3] = 7;
221  }
222
223  /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before)
224  /// CHECK: BoundsCheck
225  /// CHECK: ArrayGet
226  /// CHECK: BoundsCheck
227  /// CHECK: ArraySet
228  /// CHECK: BoundsCheck
229  /// CHECK: ArrayGet
230  /// CHECK: BoundsCheck
231  /// CHECK: ArraySet
232  /// CHECK: BoundsCheck
233  /// CHECK: ArrayGet
234  /// CHECK: BoundsCheck
235  /// CHECK: ArraySet
236  /// CHECK: BoundsCheck
237  /// CHECK: ArrayGet
238  /// CHECK: BoundsCheck
239  /// CHECK: ArraySet
240
241  /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after)
242  /// CHECK: Deoptimize
243  /// CHECK-NOT: BoundsCheck
244  /// CHECK: ArrayGet
245  /// CHECK: Deoptimize
246  /// CHECK-NOT: BoundsCheck
247  /// CHECK: ArraySet
248  /// CHECK-NOT: BoundsCheck
249  /// CHECK: ArrayGet
250  /// CHECK-NOT: BoundsCheck
251  /// CHECK: ArraySet
252  /// CHECK-NOT: BoundsCheck
253  /// CHECK: ArrayGet
254  /// CHECK-NOT: BoundsCheck
255  /// CHECK: ArraySet
256  /// CHECK-NOT: BoundsCheck
257  /// CHECK: ArrayGet
258  /// CHECK-NOT: BoundsCheck
259  /// CHECK: ArraySet
260
261  static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) {
262    if (!copy) {
263      return array1;
264    }
265    array2[0] = array1[0];
266    array2[1] = array1[1];
267    array2[2] = array1[2];
268    array2[3] = array1[3];
269    return array2;
270  }
271
272
273  /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before)
274  /// CHECK: BoundsCheck
275  /// CHECK: ArraySet
276
277  /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after)
278  /// CHECK-NOT: Deoptimize
279  /// CHECK: BoundsCheck
280  /// CHECK: ArraySet
281
282  // There is only one array access. It's not beneficial
283  // to create a compare with deoptimization instruction.
284  static void constantIndexing4(int[] array) {
285    array[0] = -1;
286  }
287
288
289  /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before)
290  /// CHECK: BoundsCheck
291  /// CHECK: ArraySet
292  /// CHECK: BoundsCheck
293  /// CHECK: ArraySet
294
295  /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after)
296  /// CHECK-NOT: Deoptimize
297  /// CHECK: BoundsCheck
298  /// CHECK: ArraySet
299  /// CHECK: BoundsCheck
300  /// CHECK: ArraySet
301
302  static void constantIndexing5(int[] array) {
303    // We don't apply the deoptimization for very large constant index
304    // since it's likely to be an anomaly and will throw AIOOBE.
305    array[Integer.MAX_VALUE - 1000] = 1;
306    array[Integer.MAX_VALUE - 999] = 1;
307    array[Integer.MAX_VALUE - 998] = 1;
308  }
309
310  /// CHECK-START: void Main.constantIndexing6(int[]) BCE (before)
311  /// CHECK: BoundsCheck
312  /// CHECK: ArraySet
313  /// CHECK: BoundsCheck
314  /// CHECK: ArraySet
315
316  /// CHECK-START: void Main.constantIndexing6(int[]) BCE (after)
317  /// CHECK: Deoptimize
318  /// CHECK-NOT: BoundsCheck
319  /// CHECK: ArraySet
320  /// CHECK-NOT: BoundsCheck
321  /// CHECK: ArraySet
322
323  static void constantIndexing6(int[] array) {
324    array[3] = 111;
325    array[4] = 111;
326  }
327
328  /// CHECK-START: void Main.constantIndexing7(int[], int) BCE (before)
329  /// CHECK: BoundsCheck
330  /// CHECK: ArraySet
331  /// CHECK: BoundsCheck
332  /// CHECK: ArraySet
333  /// CHECK: BoundsCheck
334  /// CHECK: ArraySet
335  /// CHECK: BoundsCheck
336  /// CHECK: ArraySet
337
338  /// CHECK-START: void Main.constantIndexing7(int[], int) BCE (after)
339  /// CHECK: Deoptimize
340  /// CHECK: Deoptimize
341  /// CHECK-NOT: BoundsCheck
342  /// CHECK: ArraySet
343  /// CHECK-NOT: BoundsCheck
344  /// CHECK: ArraySet
345  /// CHECK-NOT: BoundsCheck
346  /// CHECK: ArraySet
347  /// CHECK-NOT: BoundsCheck
348  /// CHECK: ArraySet
349
350  static void constantIndexing7(int[] array, int base) {
351    // With constant offsets to symbolic base.
352    array[base]     = 10;
353    array[base + 1] = 20;
354    array[base + 2] = 30;
355    array[base + 3] = 40;
356  }
357
358  /// CHECK-START: void Main.constantIndexing8(int[], int) BCE (before)
359  /// CHECK: BoundsCheck
360  /// CHECK: ArraySet
361  /// CHECK: BoundsCheck
362  /// CHECK: ArraySet
363  /// CHECK: BoundsCheck
364  /// CHECK: ArraySet
365  /// CHECK: BoundsCheck
366  /// CHECK: ArraySet
367
368  /// CHECK-START: void Main.constantIndexing8(int[], int) BCE (after)
369  /// CHECK: Deoptimize
370  /// CHECK: Deoptimize
371  /// CHECK-NOT: BoundsCheck
372  /// CHECK: ArraySet
373  /// CHECK-NOT: BoundsCheck
374  /// CHECK: ArraySet
375  /// CHECK-NOT: BoundsCheck
376  /// CHECK: ArraySet
377  /// CHECK-NOT: BoundsCheck
378  /// CHECK: ArraySet
379
380  static void constantIndexing8(int[] array, int base) {
381    // With constant offsets "both ways" to symbolic base.
382    array[base - 1] = 100;
383    array[base]     = 200;
384    array[base + 1] = 300;
385    array[base + 2] = 400;
386  }
387
388  /// CHECK-START: void Main.constantIndexing9(int[], int) BCE (before)
389  /// CHECK: BoundsCheck
390  /// CHECK: ArraySet
391  /// CHECK: BoundsCheck
392  /// CHECK: ArraySet
393  /// CHECK: BoundsCheck
394  /// CHECK: ArraySet
395  /// CHECK: BoundsCheck
396  /// CHECK: ArraySet
397
398  /// CHECK-START: void Main.constantIndexing9(int[], int) BCE (after)
399  /// CHECK: Deoptimize
400  /// CHECK: Deoptimize
401  /// CHECK-NOT: BoundsCheck
402  /// CHECK: ArraySet
403  /// CHECK-NOT: BoundsCheck
404  /// CHECK: ArraySet
405  /// CHECK-NOT: BoundsCheck
406  /// CHECK: ArraySet
407  /// CHECK-NOT: BoundsCheck
408  /// CHECK: ArraySet
409  /// CHECK-NOT: BoundsCheck
410
411  static void constantIndexing9(int[] array, int base) {
412    // Final range is base..base+3 so conditional
413    // references may be included in the end.
414    array[base] = 0;
415    if (base != 12345)
416      array[base + 2] = 2;
417    array[base + 3] = 3;
418    if (base != 67890)
419      array[base + 1] = 1;
420  }
421
422  /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (before)
423  /// CHECK: BoundsCheck
424  /// CHECK: ArraySet
425  /// CHECK: BoundsCheck
426  /// CHECK: ArraySet
427  /// CHECK: BoundsCheck
428  /// CHECK: ArraySet
429  /// CHECK: BoundsCheck
430  /// CHECK: ArraySet
431
432  /// CHECK-START: void Main.constantIndexing10(int[], int) BCE (after)
433  /// CHECK: Deoptimize
434  /// CHECK: Deoptimize
435  /// CHECK-NOT: BoundsCheck
436  /// CHECK: ArraySet
437  /// CHECK-NOT: BoundsCheck
438  /// CHECK: ArraySet
439  /// CHECK-NOT: BoundsCheck
440  /// CHECK: ArraySet
441  /// CHECK-NOT: BoundsCheck
442  /// CHECK: ArraySet
443
444  static void constantIndexing10(int[] array, int base) {
445    // Offset hidden in incremented base.
446    array[base] = 1;
447    array[++base] = 2;
448    array[++base] = 3;
449    array[++base] = 4;
450  }
451
452  static void runAllConstantIndices() {
453    int[] a1 = { 0 };
454    int[] a6 = { 0, 0, 0, 0, 0, 0 };
455
456    boolean caught = false;
457    try {
458      constantIndexing1(a1);
459    } catch (ArrayIndexOutOfBoundsException e) {
460      caught = true;
461    }
462    if (!caught) {
463      System.out.println("constant indices 1 failed!");
464    }
465
466    constantIndexing1(a6);
467    if (a6[4] != 11 || a6[5] != 11) {
468      System.out.println("constant indices 1 failed!");
469    }
470
471    $opt$noinline$constantIndexing2(a6);
472    if (a6[0] != 0 || a6[1] != 1 || a6[2] != 1 ||
473        a6[3] != 1 || a6[4] != 1 || a6[5] != 11) {
474      System.out.println("constant indices 2 failed!");
475    }
476
477    caught = false;
478    try {
479      constantIndexing2b(a6);
480    } catch (ArrayIndexOutOfBoundsException e) {
481      caught = true;
482    }
483    if (!caught || a6[0] != 6 || a6[1] != 6 || a6[2] != 6 ||
484                   a6[3] != 6 || a6[4] != 1 || a6[5] != 11) {
485      System.out.println("constant indices 2b failed!");
486    }
487
488    caught = false;
489    try {
490      constantIndexing2c(a1);
491    } catch (ArrayIndexOutOfBoundsException e) {
492      caught = true;
493    }
494    if (!caught || a1[0] != 7) {
495      System.out.println("constant indices 2c failed!");
496    }
497
498    constantIndexing2c(a6);
499    if (a6[0] != 7 || a6[1] != 7 || a6[2] != 7 ||
500        a6[3] != 7 || a6[4] != 1 || a6[5] != 11) {
501      System.out.println("constant indices 2c failed!");
502    }
503
504    int[] b4 = new int[4];
505    constantIndexing3(a6, b4, true);
506    if (b4[0] != 7 || b4[1] != 7 || b4[2] != 7 || b4[3] != 7) {
507      System.out.println("constant indices 3 failed!");
508    }
509
510    constantIndexing4(a1);
511    if (a1[0] != -1) {
512      System.out.println("constant indices 4 failed!");
513    }
514
515    caught = false;
516    try {
517      constantIndexing5(a6);
518    } catch (ArrayIndexOutOfBoundsException e) {
519      caught = true;
520    }
521    if (!caught) {
522      System.out.println("constant indices 5 failed!");
523    }
524
525    constantIndexing6(a6);
526    if (a6[0] != 7   || a6[1] != 7   || a6[2] != 7 ||
527        a6[3] != 111 || a6[4] != 111 || a6[5] != 11) {
528      System.out.println("constant indices 6 failed!");
529    }
530
531    constantIndexing7(a6, 1);
532    if (a6[0] != 7  || a6[1] != 10 || a6[2] != 20 ||
533        a6[3] != 30 || a6[4] != 40 || a6[5] != 11) {
534      System.out.println("constant indices 7 failed!");
535    }
536
537    caught = false;
538    try {
539      constantIndexing7(a6, 5);
540    } catch (ArrayIndexOutOfBoundsException e) {
541      caught = true;
542    }
543    if (!caught || a6[0] != 7  || a6[1] != 10 || a6[2] != 20 ||
544                   a6[3] != 30 || a6[4] != 40 || a6[5] != 10) {
545      System.out.println("constant indices 7 failed!");
546    }
547
548    constantIndexing8(a6, 1);
549    if (a6[0] != 100 || a6[1] != 200 || a6[2] != 300 ||
550        a6[3] != 400 || a6[4] != 40  || a6[5] != 10) {
551      System.out.println("constant indices 8 failed!");
552    }
553
554    caught = false;
555    try {
556      constantIndexing8(a6, 0);
557    } catch (ArrayIndexOutOfBoundsException e) {
558      caught = true;
559    }
560    if (!caught || a6[0] != 100) {
561      System.out.println("constant indices 8 failed!");
562    }
563
564    constantIndexing9(a6, 0);
565    if (a6[0] != 0 || a6[1] != 1  || a6[2] != 2  ||
566        a6[3] != 3 || a6[4] != 40 || a6[5] != 10) {
567      System.out.println("constant indices 9 failed!");
568    }
569
570    constantIndexing10(a6, 0);
571    if (a6[0] != 1 || a6[1] != 2  || a6[2] != 3  ||
572        a6[3] != 4 || a6[4] != 40 || a6[5] != 10) {
573      System.out.println("constant indices 10 failed!");
574    }
575  }
576
577  // A helper into which the actual throwing function should be inlined.
578  static void constantIndexingForward6(int[] array) {
579    assertIsManaged();
580    constantIndexing6(array);
581  }
582
583  /// CHECK-START: void Main.loopPattern1(int[]) BCE (before)
584  /// CHECK: BoundsCheck
585  /// CHECK: ArraySet
586  /// CHECK: BoundsCheck
587  /// CHECK: ArraySet
588  /// CHECK: BoundsCheck
589  /// CHECK: ArraySet
590  /// CHECK: BoundsCheck
591  /// CHECK: ArraySet
592  /// CHECK: BoundsCheck
593  /// CHECK: ArraySet
594  /// CHECK: BoundsCheck
595  /// CHECK: ArraySet
596  /// CHECK: BoundsCheck
597  /// CHECK: ArraySet
598
599  /// CHECK-START: void Main.loopPattern1(int[]) BCE (after)
600  /// CHECK-NOT: BoundsCheck
601  /// CHECK: ArraySet
602  /// CHECK-NOT: BoundsCheck
603  /// CHECK: ArraySet
604  /// CHECK-NOT: BoundsCheck
605  /// CHECK: ArraySet
606  /// CHECK: BoundsCheck
607  /// CHECK: ArraySet
608  /// CHECK: BoundsCheck
609  /// CHECK: ArraySet
610  /// CHECK: BoundsCheck
611  /// CHECK: ArraySet
612  /// CHECK-NOT: BoundsCheck
613  /// CHECK: ArraySet
614
615  static void loopPattern1(int[] array) {
616    for (int i = 0; i < array.length; i++) {
617      array[i] = 1;  // Bounds check can be eliminated.
618    }
619
620    for (int i = 1; i < array.length; i++) {
621      array[i] = 1;  // Bounds check can be eliminated.
622    }
623
624    for (int i = 1; i < array.length - 1; i++) {
625      array[i] = 1;  // Bounds check can be eliminated.
626    }
627
628    for (int i = -1; i < array.length; i++) {
629      array[i] = 1;  // Bounds check can't be eliminated.
630    }
631
632    for (int i = 0; i <= array.length; i++) {
633      array[i] = 1;  // Bounds check can't be eliminated.
634    }
635
636    for (int i = 0; i < array.length; i += 2) {
637      // We don't have any assumption on max array length yet.
638      // Bounds check can't be eliminated due to overflow concern.
639      array[i] = 1;
640    }
641
642    for (int i = 1; i < array.length; i += 2) {
643      // Bounds check can be eliminated since i is odd so the last
644      // i that's less than array.length is at most (Integer.MAX_VALUE - 2).
645      array[i] = 1;
646    }
647  }
648
649
650  /// CHECK-START: void Main.loopPattern2(int[]) BCE (before)
651  /// CHECK: BoundsCheck
652  /// CHECK: ArraySet
653  /// CHECK: BoundsCheck
654  /// CHECK: ArraySet
655  /// CHECK: BoundsCheck
656  /// CHECK: ArraySet
657  /// CHECK: BoundsCheck
658  /// CHECK: ArraySet
659  /// CHECK: BoundsCheck
660  /// CHECK: ArraySet
661  /// CHECK: BoundsCheck
662  /// CHECK: ArraySet
663
664  /// CHECK-START: void Main.loopPattern2(int[]) BCE (after)
665  /// CHECK-NOT: BoundsCheck
666  /// CHECK: ArraySet
667  /// CHECK-NOT: BoundsCheck
668  /// CHECK: ArraySet
669  /// CHECK-NOT: BoundsCheck
670  /// CHECK: ArraySet
671  /// CHECK: BoundsCheck
672  /// CHECK: ArraySet
673  /// CHECK: BoundsCheck
674  /// CHECK: ArraySet
675  /// CHECK-NOT: BoundsCheck
676  /// CHECK: ArraySet
677
678  static void loopPattern2(int[] array) {
679    for (int i = array.length - 1; i >= 0; i--) {
680      array[i] = 1;  // Bounds check can be eliminated.
681    }
682
683    for (int i = array.length; i > 0; i--) {
684      array[i - 1] = 1;  // Bounds check can be eliminated.
685    }
686
687    for (int i = array.length - 1; i > 0; i--) {
688      array[i] = 1;  // Bounds check can be eliminated.
689    }
690
691    for (int i = array.length; i >= 0; i--) {
692      array[i] = 1;  // Bounds check can't be eliminated.
693    }
694
695    for (int i = array.length; i >= 0; i--) {
696      array[i - 1] = 1;  // Bounds check can't be eliminated.
697    }
698
699    for (int i = array.length; i > 0; i -= 20) {
700      // For i >= 0, (i - 20 - 1) is guaranteed not to underflow.
701      array[i - 1] = 1;  // Bounds check can be eliminated.
702    }
703  }
704
705
706  /// CHECK-START: void Main.loopPattern3(int[]) BCE (before)
707  /// CHECK: BoundsCheck
708  /// CHECK: ArraySet
709
710  /// CHECK-START: void Main.loopPattern3(int[]) BCE (after)
711  /// CHECK: BoundsCheck
712  /// CHECK: ArraySet
713
714  static void loopPattern3(int[] array) {
715    java.util.Random random = new java.util.Random();
716    for (int i = 0; ; i++) {
717      if (random.nextInt() % 1000 == 0 && i < array.length) {
718        // Can't eliminate the bound check since not every i++ is
719        // matched with a array length check, so there is some chance that i
720        // overflows and is negative.
721        array[i] = 1;
722      }
723    }
724  }
725
726
727  /// CHECK-START: void Main.constantNewArray() BCE (before)
728  /// CHECK: BoundsCheck
729  /// CHECK: ArraySet
730  /// CHECK: BoundsCheck
731  /// CHECK: ArraySet
732  /// CHECK: BoundsCheck
733  /// CHECK: ArraySet
734  /// CHECK: BoundsCheck
735  /// CHECK: ArraySet
736  /// CHECK: BoundsCheck
737  /// CHECK: ArraySet
738
739  /// CHECK-START: void Main.constantNewArray() BCE (after)
740  /// CHECK-NOT: BoundsCheck
741  /// CHECK: ArraySet
742  /// CHECK: BoundsCheck
743  /// CHECK: ArraySet
744  /// CHECK-NOT: BoundsCheck
745  /// CHECK: ArraySet
746  /// CHECK-NOT: BoundsCheck
747  /// CHECK: ArraySet
748  /// CHECK: BoundsCheck
749  /// CHECK: ArraySet
750
751  static void constantNewArray() {
752    int[] array = new int[10];
753    for (int i = 0; i < 10; i++) {
754      array[i] = 1;  // Bounds check can be eliminated.
755    }
756
757    for (int i = 0; i <= 10; i++) {
758      array[i] = 1;  // Bounds check can't be eliminated.
759    }
760
761    array[0] = 1;  // Bounds check can be eliminated.
762    array[9] = 1;  // Bounds check can be eliminated.
763    array[10] = 1; // Bounds check can't be eliminated.
764  }
765
766
767  static byte readData() {
768    return 1;
769  }
770
771  /// CHECK-START: void Main.circularBufferProducer() BCE (before)
772  /// CHECK: BoundsCheck
773  /// CHECK: ArraySet
774
775  /// CHECK-START: void Main.circularBufferProducer() BCE (after)
776  /// CHECK-NOT: BoundsCheck
777  /// CHECK: ArraySet
778
779  static void circularBufferProducer() {
780    byte[] array = new byte[4096];
781    int i = 0;
782    while (true) {
783      array[i & (array.length - 1)] = readData();
784      i++;
785    }
786  }
787
788
789  /// CHECK-START: void Main.pyramid1(int[]) BCE (before)
790  /// CHECK: BoundsCheck
791  /// CHECK: ArraySet
792  /// CHECK: BoundsCheck
793  /// CHECK: ArraySet
794
795  /// CHECK-START: void Main.pyramid1(int[]) BCE (after)
796  /// CHECK-NOT: BoundsCheck
797  /// CHECK: ArraySet
798  /// CHECK-NOT: BoundsCheck
799  /// CHECK: ArraySet
800
801  // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
802  static void pyramid1(int[] array) {
803    for (int i = 0; i < (array.length + 1) / 2; i++) {
804      array[i] = i;
805      array[array.length - 1 - i] = i;
806    }
807  }
808
809
810  /// CHECK-START: void Main.pyramid2(int[]) BCE (before)
811  /// CHECK: BoundsCheck
812  /// CHECK: ArraySet
813  /// CHECK: BoundsCheck
814  /// CHECK: ArraySet
815
816  /// CHECK-START: void Main.pyramid2(int[]) BCE (after)
817  /// CHECK-NOT: BoundsCheck
818  /// CHECK: ArraySet
819  /// CHECK-NOT: BoundsCheck
820  /// CHECK: ArraySet
821
822  // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
823  static void pyramid2(int[] array) {
824    for (int i = 0; i < (array.length + 1) >> 1; i++) {
825      array[i] = i;
826      array[array.length - 1 - i] = i;
827    }
828  }
829
830
831  /// CHECK-START: void Main.pyramid3(int[]) BCE (before)
832  /// CHECK: BoundsCheck
833  /// CHECK: ArraySet
834  /// CHECK: BoundsCheck
835  /// CHECK: ArraySet
836
837  /// CHECK-START: void Main.pyramid3(int[]) BCE (after)
838  /// CHECK-NOT: BoundsCheck
839  /// CHECK: ArraySet
840  /// CHECK-NOT: BoundsCheck
841  /// CHECK: ArraySet
842
843  // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
844  static void pyramid3(int[] array) {
845    for (int i = 0; i < (array.length + 1) >>> 1; i++) {
846      array[i] = i;
847      array[array.length - 1 - i] = i;
848    }
849  }
850
851
852  /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
853  /// CHECK: BoundsCheck
854  /// CHECK: ArrayGet
855  /// CHECK: BoundsCheck
856  /// CHECK: ArrayGet
857
858  /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
859  /// CHECK-NOT: BoundsCheck
860  /// CHECK: ArrayGet
861  /// CHECK-NOT: BoundsCheck
862  /// CHECK: ArrayGet
863
864  static boolean isPyramid(int[] array) {
865    int i = 0;
866    int j = array.length - 1;
867    while (i <= j) {
868      if (array[i] != i) {
869        return false;
870      }
871      if (array[j] != i) {
872        return false;
873      }
874      i++; j--;
875    }
876    return true;
877  }
878
879
880  /// CHECK-START: void Main.bubbleSort(int[]) GVN (before)
881  /// CHECK: BoundsCheck
882  /// CHECK: ArrayGet
883  /// CHECK: BoundsCheck
884  /// CHECK: ArrayGet
885  /// CHECK: BoundsCheck
886  /// CHECK: ArrayGet
887  /// CHECK: BoundsCheck
888  /// CHECK: ArrayGet
889  /// CHECK: BoundsCheck
890  /// CHECK: ArraySet
891  /// CHECK: BoundsCheck
892  /// CHECK: ArraySet
893
894  /// CHECK-START: void Main.bubbleSort(int[]) GVN (after)
895  /// CHECK: BoundsCheck
896  /// CHECK: ArrayGet
897  /// CHECK: BoundsCheck
898  /// CHECK: ArrayGet
899  /// CHECK-NOT: ArrayGet
900  /// CHECK-NOT: ArrayGet
901  /// CHECK-NOT: BoundsCheck
902  /// CHECK: ArraySet
903  /// CHECK-NOT: BoundsCheck
904  /// CHECK: ArraySet
905
906  /// CHECK-START: void Main.bubbleSort(int[]) BCE (after)
907  /// CHECK-NOT: BoundsCheck
908  /// CHECK: ArrayGet
909  /// CHECK-NOT: BoundsCheck
910  /// CHECK: ArrayGet
911  /// CHECK-NOT: ArrayGet
912  /// CHECK-NOT: ArrayGet
913  /// CHECK-NOT: BoundsCheck
914  /// CHECK: ArraySet
915  /// CHECK-NOT: BoundsCheck
916  /// CHECK: ArraySet
917
918  static void bubbleSort(int[] array) {
919    for (int i = 0; i < array.length - 1; i++) {
920      for (int j = 0; j < array.length - i - 1; j++) {
921        if (array[j] > array[j + 1]) {
922          int temp = array[j + 1];
923          array[j + 1] = array[j];
924          array[j] = temp;
925        }
926      }
927    }
928  }
929
930  static int[][] mA;
931
932  /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before)
933  //  Array references mA[i] and ..[j] both in inner loop.
934  /// CHECK-DAG:  <<Get1:l\d+>>  ArrayGet [<<Array1:l\d+>>,<<Bounds1:i\d+>>] loop:<<InnerLoop:B\d+>>
935  /// CHECK-DAG:  <<Array1>>     NullCheck [<<Field1:l\d+>>]                 loop:<<InnerLoop>>
936  /// CHECK-DAG:  <<Len1:i\d+>>  ArrayLength [<<Array1>>]                    loop:<<InnerLoop>>
937  /// CHECK-DAG:  <<Bounds1>>    BoundsCheck [<<Index1:i\d+>>,<<Len1>>]      loop:<<InnerLoop>>
938  /// CHECK-DAG:  <<Get2:i\d+>>  ArrayGet [<<Array2:l\d+>>,<<Bounds2:i\d+>>] loop:<<InnerLoop>>
939  /// CHECK-DAG:  <<Array2>>     NullCheck [<<Get1>>]                        loop:<<InnerLoop>>
940  /// CHECK-DAG:  <<Len2:i\d+>>  ArrayLength [<<Array2>>]                    loop:<<InnerLoop>>
941  /// CHECK-DAG:  <<Bounds2>>    BoundsCheck [<<Index2:i\d+>>,<<Len2>>]      loop:<<InnerLoop>>
942  // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
943  /// CHECK-DAG:                 InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>>
944  /// CHECK-DAG:  <<Index2>>     Phi                                         loop:<<InnerLoop>>
945  /// CHECK-DAG:  <<Index1>>     Phi                                         loop:<<OuterLoop:B\d+>>
946  /// CHECK-DAG:  <<Field1>>     StaticFieldGet                              loop:none
947  /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
948  //
949  /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
950  //  Array reference mA[i] hoisted to same level as deopt.
951  /// CHECK-DAG:                 Deoptimize                                  loop:<<OuterLoop:B\d+>>
952  /// CHECK-DAG:                 ArrayLength                                 loop:<<OuterLoop>>
953  /// CHECK-DAG:  <<Get1:l\d+>>  ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>]  loop:<<OuterLoop>>
954  //  Array reference ..[j] still in inner loop, with a direct index.
955  /// CHECK-DAG:  <<Get2:i\d+>>  ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>]  loop:<<InnerLoop:B\d+>>
956  // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
957  /// CHECK-DAG:                 InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>>
958  /// CHECK-DAG:  <<Index2>>     Phi                                         loop:<<InnerLoop>>
959  /// CHECK-DAG:  <<Index1>>     Phi                                         loop:<<OuterLoop>>
960  //  Synthetic phi.
961  /// CHECK-DAG:  <<Array2>>     Phi                                         loop:<<OuterLoop>>
962  /// CHECK-DAG:  <<Array1>>     StaticFieldGet                              loop:none
963  /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
964  //
965  /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
966  /// CHECK-NOT: NullCheck
967  /// CHECK-NOT: BoundsCheck
968  static void dynamicBCEAndIntrinsic(int n) {
969    for (int i = 0; i < n; i++) {
970      for (int j = 0; j < n; j++) {
971        // Since intrinsic call cannot modify fields or arrays,
972        // dynamic BCE and hoisting can be applied to the inner loop.
973        mA[i][j] = Math.abs(mA[i][j]);
974      }
975    }
976  }
977
978  static int foo() {
979    try {
980      assertIsManaged();
981      // This will cause AIOOBE.
982      $opt$noinline$constantIndexing2(new int[3]);
983    } catch (ArrayIndexOutOfBoundsException e) {
984      assertIsManaged();  // This is to ensure that single-frame deoptimization works.
985                          // Will need to be updated if $opt$noinline$constantIndexing2 is inlined.
986      try {
987        // This will cause AIOOBE.
988        constantIndexingForward6(new int[3]);
989      } catch (ArrayIndexOutOfBoundsException e2) {
990        // Having deopted, we expect to be running interpreted at this point.
991        // Does not apply to debuggable, however, since we do not inline.
992        return 99;
993      }
994    }
995    return 0;
996  }
997
998
999  int sum;
1000
1001  /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before)
1002  /// CHECK: BoundsCheck
1003  /// CHECK: ArraySet
1004  /// CHECK-NOT: BoundsCheck
1005  /// CHECK: ArrayGet
1006
1007  /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after)
1008  /// CHECK: Phi
1009  /// CHECK-NOT: BoundsCheck
1010  /// CHECK: ArraySet
1011  /// CHECK-NOT: BoundsCheck
1012  /// CHECK: ArrayGet
1013  //  Added blocks at end for deoptimization.
1014  /// CHECK: Exit
1015  /// CHECK: If
1016  /// CHECK: Deoptimize
1017  /// CHECK: Deoptimize
1018  /// CHECK: Deoptimize
1019  /// CHECK-NOT: Deoptimize
1020  /// CHECK: Goto
1021  /// CHECK: Goto
1022  /// CHECK: Goto
1023
1024  void foo1(int[] array, int start, int end, boolean expectInterpreter) {
1025    // Three HDeoptimize will be added. Two for the index
1026    // and one for null check on array (to hoist null
1027    // check and array.length out of loop).
1028    for (int i = start ; i < end; i++) {
1029      if (expectInterpreter) {
1030        assertIsInterpreted();
1031      } else {
1032        assertIsManaged();
1033      }
1034      array[i] = 1;
1035      sum += array[i];
1036    }
1037  }
1038
1039
1040  /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before)
1041  /// CHECK: BoundsCheck
1042  /// CHECK: ArraySet
1043  /// CHECK-NOT: BoundsCheck
1044  /// CHECK: ArrayGet
1045  /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after)
1046  /// CHECK: Phi
1047  /// CHECK-NOT: BoundsCheck
1048  /// CHECK: ArraySet
1049  /// CHECK-NOT: BoundsCheck
1050  /// CHECK: ArrayGet
1051  //  Added blocks at end for deoptimization.
1052  /// CHECK: Exit
1053  /// CHECK: If
1054  /// CHECK: Deoptimize
1055  /// CHECK: Deoptimize
1056  /// CHECK: Deoptimize
1057  /// CHECK-NOT: Deoptimize
1058  /// CHECK: Goto
1059  /// CHECK: Goto
1060  /// CHECK: Goto
1061
1062  void foo2(int[] array, int start, int end, boolean expectInterpreter) {
1063    // Three HDeoptimize will be added. Two for the index
1064    // and one for null check on array (to hoist null
1065    // check and array.length out of loop).
1066    for (int i = start ; i <= end; i++) {
1067      if (expectInterpreter) {
1068        assertIsInterpreted();
1069      } else {
1070        assertIsManaged();
1071      }
1072      array[i] = 1;
1073      sum += array[i];
1074    }
1075  }
1076
1077
1078  /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before)
1079  /// CHECK: BoundsCheck
1080  /// CHECK: ArraySet
1081  /// CHECK-NOT: BoundsCheck
1082  /// CHECK: ArrayGet
1083  /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after)
1084  /// CHECK: Phi
1085  /// CHECK-NOT: BoundsCheck
1086  /// CHECK: ArraySet
1087  /// CHECK-NOT: BoundsCheck
1088  /// CHECK: ArrayGet
1089  //  Added blocks at end for deoptimization.
1090  /// CHECK: Exit
1091  /// CHECK: If
1092  /// CHECK: Deoptimize
1093  /// CHECK: Deoptimize
1094  /// CHECK: Deoptimize
1095  /// CHECK-NOT: Deoptimize
1096  /// CHECK: Goto
1097  /// CHECK: Goto
1098  /// CHECK: Goto
1099
1100  void foo3(int[] array, int end, boolean expectInterpreter) {
1101    // Three HDeoptimize will be added. Two for the index
1102    // and one for null check on array (to hoist null check
1103    // and array.length out of loop).
1104    for (int i = 3 ; i <= end; i++) {
1105      if (expectInterpreter) {
1106        assertIsInterpreted();
1107      } else {
1108        assertIsManaged();
1109      }
1110      array[i] = 1;
1111      sum += array[i];
1112    }
1113  }
1114
1115
1116  /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before)
1117  /// CHECK: BoundsCheck
1118  /// CHECK: ArraySet
1119  /// CHECK-NOT: BoundsCheck
1120  /// CHECK: ArrayGet
1121
1122  /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after)
1123  /// CHECK: Phi
1124  /// CHECK-NOT: BoundsCheck
1125  /// CHECK: ArraySet
1126  /// CHECK-NOT: BoundsCheck
1127  /// CHECK: ArrayGet
1128  //  Added blocks at end for deoptimization.
1129  /// CHECK: Exit
1130  /// CHECK: If
1131  /// CHECK: Deoptimize
1132  /// CHECK: Deoptimize
1133  /// CHECK: Deoptimize
1134  /// CHECK-NOT: Deoptimize
1135  /// CHECK: Goto
1136  /// CHECK: Goto
1137  /// CHECK: Goto
1138
1139  void foo4(int[] array, int end, boolean expectInterpreter) {
1140    // Three HDeoptimize will be added. Two for the index
1141    // and one for null check on array (to hoist null check
1142    // and array.length out of loop).
1143    for (int i = end ; i > 0; i--) {
1144      if (expectInterpreter) {
1145        assertIsInterpreted();
1146      } else {
1147        assertIsManaged();
1148      }
1149      array[i - 1] = 1;
1150      sum += array[i - 1];
1151    }
1152  }
1153
1154
1155  /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before)
1156  /// CHECK: BoundsCheck
1157  /// CHECK: ArraySet
1158  /// CHECK: BoundsCheck
1159  /// CHECK: ArrayGet
1160  /// CHECK: BoundsCheck
1161  /// CHECK: ArrayGet
1162  /// CHECK: BoundsCheck
1163  /// CHECK: ArrayGet
1164
1165  /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after)
1166  /// CHECK-NOT: BoundsCheck
1167  /// CHECK: ArraySet
1168  /// CHECK: Phi
1169  /// CHECK-NOT: BoundsCheck
1170  /// CHECK: ArrayGet
1171  /// CHECK-NOT: BoundsCheck
1172  /// CHECK: ArrayGet
1173  /// CHECK-NOT: BoundsCheck
1174  /// CHECK: ArrayGet
1175  //  Added blocks at end for deoptimization.
1176  /// CHECK: Exit
1177  /// CHECK: If
1178  /// CHECK: Deoptimize
1179  /// CHECK: Deoptimize
1180  /// CHECK: Deoptimize
1181  /// CHECK: Deoptimize
1182  /// CHECK: Deoptimize
1183  /// CHECK: Deoptimize
1184  /// CHECK-NOT: Deoptimize
1185  /// CHECK: Goto
1186  /// CHECK: Goto
1187  /// CHECK: Goto
1188
1189  void foo5(int[] array, int end, boolean expectInterpreter) {
1190    // Bounds check in this loop can be eliminated without deoptimization.
1191    for (int i = array.length - 1 ; i >= 0; i--) {
1192      array[i] = 1;
1193    }
1194    // Several HDeoptimize will be added. Two for each index.
1195    // The null check is not necessary.
1196    for (int i = end - 2 ; i > 0; i--) {
1197      if (expectInterpreter) {
1198        assertIsInterpreted();
1199      } else {
1200        assertIsManaged();
1201      }
1202      sum += array[i - 1];
1203      sum += array[i];
1204      sum += array[i + 1];
1205    }
1206  }
1207
1208
1209  /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before)
1210  /// CHECK: BoundsCheck
1211  /// CHECK: ArrayGet
1212  /// CHECK: BoundsCheck
1213  /// CHECK: ArrayGet
1214  /// CHECK: BoundsCheck
1215  /// CHECK: ArrayGet
1216  /// CHECK: BoundsCheck
1217  /// CHECK: ArrayGet
1218  /// CHECK: BoundsCheck
1219  /// CHECK: ArrayGet
1220  /// CHECK-NOT: BoundsCheck
1221  /// CHECK: ArraySet
1222  /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after)
1223  /// CHECK: Phi
1224  /// CHECK-NOT: BoundsCheck
1225  /// CHECK: ArrayGet
1226  /// CHECK-NOT: BoundsCheck
1227  /// CHECK: ArrayGet
1228  /// CHECK-NOT: BoundsCheck
1229  /// CHECK: ArrayGet
1230  /// CHECK-NOT: BoundsCheck
1231  /// CHECK: ArrayGet
1232  /// CHECK-NOT: BoundsCheck
1233  /// CHECK: ArrayGet
1234  /// CHECK-NOT: BoundsCheck
1235  /// CHECK: ArraySet
1236  //  Added blocks at end for deoptimization.
1237  /// CHECK: Exit
1238  /// CHECK: If
1239  /// CHECK: Deoptimize
1240  /// CHECK: Deoptimize
1241  /// CHECK: Deoptimize
1242  /// CHECK: Deoptimize
1243  /// CHECK: Deoptimize
1244  /// CHECK: Deoptimize
1245  /// CHECK: Deoptimize
1246  /// CHECK: Deoptimize
1247  /// CHECK: Deoptimize
1248  /// CHECK: Deoptimize
1249  /// CHECK: Deoptimize
1250  /// CHECK-NOT: Deoptimize
1251  /// CHECK: Goto
1252  /// CHECK: Goto
1253  /// CHECK: Goto
1254
1255  void foo6(int[] array, int start, int end, boolean expectInterpreter) {
1256    // Several HDeoptimize will be added.
1257    for (int i = end; i >= start; i--) {
1258      if (expectInterpreter) {
1259        assertIsInterpreted();
1260      } else {
1261        assertIsManaged();
1262      }
1263      array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5;
1264    }
1265  }
1266
1267
1268  /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
1269  /// CHECK: BoundsCheck
1270  /// CHECK: ArrayGet
1271  /// CHECK: BoundsCheck
1272  /// CHECK: ArrayGet
1273
1274  /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
1275  /// CHECK: Phi
1276  /// CHECK: BoundsCheck
1277  /// CHECK: ArrayGet
1278  /// CHECK-NOT: BoundsCheck
1279  /// CHECK: ArrayGet
1280  //  Added blocks at end for deoptimization.
1281  /// CHECK: Exit
1282  /// CHECK: If
1283  /// CHECK: Deoptimize
1284  /// CHECK: Deoptimize
1285  /// CHECK: Deoptimize
1286  /// CHECK-NOT: Deoptimize
1287  /// CHECK: Goto
1288  /// CHECK: Goto
1289  /// CHECK: Goto
1290
1291  void foo7(int[] array, int start, int end, boolean lowEnd) {
1292    // Three HDeoptimize will be added. One for the index
1293    // and one for null check on array (to hoist null
1294    // check and array.length out of loop).
1295    for (int i = start ; i < end; i++) {
1296      if (lowEnd) {
1297        // This array access isn't certain. So we don't
1298        // use +1000 offset in decision making for deoptimization
1299        // conditions.
1300        sum += array[i + 1000];
1301      }
1302      sum += array[i];
1303    }
1304  }
1305
1306
1307  /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before)
1308  /// CHECK: BoundsCheck
1309  /// CHECK: ArrayGet
1310  /// CHECK: BoundsCheck
1311  /// CHECK: ArraySet
1312
1313  /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after)
1314  /// CHECK: Phi
1315  /// CHECK-NOT: BoundsCheck
1316  /// CHECK: ArrayGet
1317  /// CHECK: Phi
1318  /// CHECK-NOT: BoundsCheck
1319  /// CHECK: ArraySet
1320  //  Added blocks at end for deoptimization.
1321  /// CHECK: Exit
1322  /// CHECK: If
1323  /// CHECK: Deoptimize
1324  /// CHECK: Deoptimize
1325  /// CHECK: Deoptimize
1326  /// CHECK: Goto
1327  /// CHECK: Goto
1328  /// CHECK: Goto
1329  /// CHECK: If
1330  /// CHECK: Deoptimize
1331  /// CHECK: Deoptimize
1332  /// CHECK: Deoptimize
1333  /// CHECK-NOT: Deoptimize
1334  /// CHECK: Goto
1335  /// CHECK: Goto
1336  /// CHECK: Goto
1337
1338  void foo8(int[][] matrix, int start, int end) {
1339    // Three HDeoptimize will be added for the outer loop,
1340    // two for the index, and null check on matrix. Same
1341    // for the inner loop.
1342    for (int i = start; i < end; i++) {
1343      int[] row = matrix[i];
1344      for (int j = start; j < end; j++) {
1345        row[j] = 1;
1346      }
1347    }
1348  }
1349
1350
1351  /// CHECK-START: void Main.foo9(int[], boolean) BCE (before)
1352  /// CHECK: NullCheck
1353  /// CHECK: BoundsCheck
1354  /// CHECK: ArrayGet
1355
1356  /// CHECK-START: void Main.foo9(int[], boolean) BCE (after)
1357  //  The loop is guaranteed to be entered. No need to transform the
1358  //  loop for loop body entry test.
1359  /// CHECK: Deoptimize
1360  /// CHECK: Deoptimize
1361  /// CHECK: Deoptimize
1362  /// CHECK-NOT: Deoptimize
1363  /// CHECK: Phi
1364  /// CHECK-NOT: NullCheck
1365  /// CHECK-NOT: BoundsCheck
1366  /// CHECK: ArrayGet
1367
1368  /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier_after_bce (after)
1369  //  Simplification removes the redundant check
1370  /// CHECK: Deoptimize
1371  /// CHECK: Deoptimize
1372  /// CHECK-NOT: Deoptimize
1373
1374  void foo9(int[] array, boolean expectInterpreter) {
1375    // Two HDeoptimize will be added. Two for the index
1376    // and one for null check on array.
1377    for (int i = 0 ; i < 10; i++) {
1378      if (expectInterpreter) {
1379        assertIsInterpreted();
1380      } else {
1381        assertIsManaged();
1382      }
1383      sum += array[i];
1384    }
1385  }
1386
1387
1388  /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
1389  /// CHECK: BoundsCheck
1390  /// CHECK: ArraySet
1391
1392  /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
1393  /// CHECK-NOT: Deoptimize
1394  /// CHECK: BoundsCheck
1395  /// CHECK: ArraySet
1396
1397  void partialLooping(int[] array, int start, int end) {
1398    // This loop doesn't cover the full range of [start, end) so
1399    // adding deoptimization is too aggressive, since end can be
1400    // greater than array.length but the loop is never going to work on
1401    // more than 2 elements.
1402    for (int i = start; i < end; i++) {
1403      if (i == 2) {
1404        return;
1405      }
1406      array[i] = 1;
1407    }
1408  }
1409
1410
1411  static void testUnknownBounds() {
1412    boolean caught = false;
1413
1414    runAllConstantIndices();
1415
1416    Main main = new Main();
1417    main.foo1(new int[10], 0, 10, false);
1418    if (main.sum != 10) {
1419      System.out.println("foo1 failed!");
1420    }
1421
1422    caught = false;
1423    main = new Main();
1424    try {
1425      main.foo1(new int[10], 0, 11, true);
1426    } catch (ArrayIndexOutOfBoundsException e) {
1427      caught = true;
1428    }
1429    if (!caught || main.sum != 10) {
1430      System.out.println("foo1 exception failed!");
1431    }
1432
1433    main = new Main();
1434    main.foo2(new int[10], 0, 9, false);
1435    if (main.sum != 10) {
1436      System.out.println("foo2 failed!");
1437    }
1438
1439    caught = false;
1440    main = new Main();
1441    try {
1442      main.foo2(new int[10], 0, 10, true);
1443    } catch (ArrayIndexOutOfBoundsException e) {
1444      caught = true;
1445    }
1446    if (!caught || main.sum != 10) {
1447      System.out.println("foo2 exception failed!");
1448    }
1449
1450    main = new Main();
1451    main.foo3(new int[10], 9, false);
1452    if (main.sum != 7) {
1453      System.out.println("foo3 failed!");
1454    }
1455
1456    caught = false;
1457    main = new Main();
1458    try {
1459      main.foo3(new int[10], 10, true);
1460    } catch (ArrayIndexOutOfBoundsException e) {
1461      caught = true;
1462    }
1463    if (!caught || main.sum != 7) {
1464      System.out.println("foo3 exception failed!");
1465    }
1466
1467    main = new Main();
1468    main.foo4(new int[10], 10, false);
1469    if (main.sum != 10) {
1470      System.out.println("foo4 failed!");
1471    }
1472
1473    caught = false;
1474    main = new Main();
1475    try {
1476      main.foo4(new int[10], 11, true);
1477    } catch (ArrayIndexOutOfBoundsException e) {
1478      caught = true;
1479    }
1480    if (!caught || main.sum != 0) {
1481      System.out.println("foo4 exception failed!");
1482    }
1483
1484    main = new Main();
1485    main.foo5(new int[10], 10, false);
1486    if (main.sum != 24) {
1487      System.out.println("foo5 failed!");
1488    }
1489
1490    caught = false;
1491    main = new Main();
1492    try {
1493      main.foo5(new int[10], 11, true);
1494    } catch (ArrayIndexOutOfBoundsException e) {
1495      caught = true;
1496    }
1497    if (!caught || main.sum != 2) {
1498      System.out.println("foo5 exception failed!");
1499    }
1500
1501    main = new Main();
1502    main.foo6(new int[10], 2, 7, false);
1503
1504    main = new Main();
1505    int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1506    main.foo9(array9, false);
1507    if (main.sum != 45) {
1508      System.out.println("foo9 failed!");
1509    }
1510
1511    main = new Main();
1512    int[] array = new int[4];
1513    main.partialLooping(new int[3], 0, 4);
1514    if ((array[0] != 1) && (array[1] != 1) &&
1515        (array[2] != 0) && (array[3] != 0)) {
1516      System.out.println("partialLooping failed!");
1517    }
1518
1519    caught = false;
1520    main = new Main();
1521    try {
1522      main.foo6(new int[10], 2, 8, true);
1523    } catch (ArrayIndexOutOfBoundsException e) {
1524      caught = true;
1525    }
1526    if (!caught) {
1527      System.out.println("foo6 exception failed!");
1528    }
1529
1530    caught = false;
1531    main = new Main();
1532    try {
1533      main.foo6(new int[10], 1, 7, true);
1534    } catch (ArrayIndexOutOfBoundsException e) {
1535      caught = true;
1536    }
1537    if (!caught) {
1538      System.out.println("foo6 exception failed!");
1539    }
1540
1541  }
1542
1543  public void testExceptionMessage() {
1544    short[] B1 = new short[5];
1545    int[] B2 = new int[5];
1546    Exception err = null;
1547    try {
1548      testExceptionMessage1(B1, B2, null, -1, 6);
1549    } catch (Exception e) {
1550      err = e;
1551    }
1552    System.out.println(err);
1553  }
1554
1555  void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) {
1556    int j = finish + 77;
1557    // Bug: 22665511
1558    // A deoptimization will be triggered here right before the loop. Need to make
1559    // sure the value of j is preserved for the interpreter.
1560    for (int i = start; i <= finish; i++) {
1561      a2[j - 1] = a1[i + 1];
1562    }
1563  }
1564
1565  // Make sure this method is compiled with optimizing.
1566  /// CHECK-START: void Main.main(java.lang.String[]) register (after)
1567  /// CHECK: ParallelMove
1568
1569  public static void main(String[] args) {
1570    System.loadLibrary(args[0]);
1571
1572    if (!compiledWithOptimizing() ||
1573        !hasOatFile() ||
1574        runtimeIsSoftFail() ||
1575        isInterpreted()) {
1576      disableStackFrameAsserts();
1577    }
1578
1579    sieve(20);
1580
1581    int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
1582    bubbleSort(array);
1583    for (int i = 0; i < 8; i++) {
1584      if (array[i] != i) {
1585        System.out.println("bubble sort failed!");
1586      }
1587    }
1588
1589    mA = new int[4][4];
1590    for (int i = 0; i < 4; i++) {
1591      for (int j = 0; j < 4; j++) {
1592        mA[i][j] = -1;
1593      }
1594    }
1595    dynamicBCEAndIntrinsic(4);
1596    for (int i = 0; i < 4; i++) {
1597      for (int j = 0; j < 4; j++) {
1598        if (mA[i][i] != 1) {
1599          System.out.println("dynamic bce failed!");
1600        }
1601      }
1602    }
1603
1604    array = new int[7];
1605    pyramid1(array);
1606    if (!isPyramid(array)) {
1607      System.out.println("pyramid1 failed!");
1608    }
1609
1610    array = new int[8];
1611    pyramid2(array);
1612    if (!isPyramid(array)) {
1613      System.out.println("pyramid2 failed!");
1614    }
1615
1616    java.util.Arrays.fill(array, -1);
1617    pyramid3(array);
1618    if (!isPyramid(array)) {
1619      System.out.println("pyramid3 failed!");
1620    }
1621
1622    // Make sure this value is kept after deoptimization.
1623    int i = 1;
1624    if (foo() + i != 100) {
1625      System.out.println("foo failed!");
1626    };
1627
1628    testUnknownBounds();
1629    new Main().testExceptionMessage();
1630  }
1631
1632  public static native boolean compiledWithOptimizing();
1633  public static native void disableStackFrameAsserts();
1634  public static native void assertIsManaged();
1635  public static native void assertIsInterpreted();
1636  public static native boolean hasOatFile();
1637  public static native boolean runtimeIsSoftFail();
1638  public static native boolean isInterpreted();
1639}
1640