Main.java revision 0b5849be045c5683d4a6b6b6c306abadba5f0fcc
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    array[5] = 1;
126    array[4] = 1;
127  }
128
129
130  /// CHECK-START: void Main.constantIndexing2(int[]) BCE (before)
131  /// CHECK: BoundsCheck
132  /// CHECK: ArraySet
133  /// CHECK: BoundsCheck
134  /// CHECK: ArraySet
135  /// CHECK: BoundsCheck
136  /// CHECK: ArraySet
137  /// CHECK: BoundsCheck
138  /// CHECK: ArraySet
139
140  /// 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
153
154  static void constantIndexing2(int[] array) {
155    array[1] = 1;
156    array[2] = 1;
157    array[3] = 1;
158    array[4] = 1;
159    array[-1] = 1;
160  }
161
162
163  /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (before)
164  /// CHECK: BoundsCheck
165  /// CHECK: ArrayGet
166  /// CHECK: BoundsCheck
167  /// CHECK: ArraySet
168  /// CHECK: BoundsCheck
169  /// CHECK: ArrayGet
170  /// CHECK: BoundsCheck
171  /// CHECK: ArraySet
172  /// CHECK: BoundsCheck
173  /// CHECK: ArrayGet
174  /// CHECK: BoundsCheck
175  /// CHECK: ArraySet
176  /// CHECK: BoundsCheck
177  /// CHECK: ArrayGet
178  /// CHECK: BoundsCheck
179  /// CHECK: ArraySet
180
181  /// CHECK-START: int[] Main.constantIndexing3(int[], int[], boolean) BCE (after)
182  /// CHECK: LessThanOrEqual
183  /// CHECK: Deoptimize
184  /// CHECK-NOT: BoundsCheck
185  /// CHECK: ArrayGet
186  /// CHECK: LessThanOrEqual
187  /// CHECK: Deoptimize
188  /// CHECK-NOT: BoundsCheck
189  /// CHECK: ArraySet
190  /// CHECK-NOT: BoundsCheck
191  /// CHECK: ArrayGet
192  /// CHECK-NOT: BoundsCheck
193  /// CHECK: ArraySet
194  /// CHECK-NOT: BoundsCheck
195  /// CHECK: ArrayGet
196  /// CHECK-NOT: BoundsCheck
197  /// CHECK: ArraySet
198  /// CHECK-NOT: BoundsCheck
199  /// CHECK: ArrayGet
200  /// CHECK-NOT: BoundsCheck
201  /// CHECK: ArraySet
202
203  static int[] constantIndexing3(int[] array1, int[] array2, boolean copy) {
204    if (!copy) {
205      return array1;
206    }
207    array2[0] = array1[0];
208    array2[1] = array1[1];
209    array2[2] = array1[2];
210    array2[3] = array1[3];
211    return array2;
212  }
213
214
215  /// CHECK-START: void Main.constantIndexing4(int[]) BCE (before)
216  /// CHECK: BoundsCheck
217  /// CHECK: ArraySet
218
219  /// CHECK-START: void Main.constantIndexing4(int[]) BCE (after)
220  /// CHECK-NOT: LessThanOrEqual
221  /// CHECK: BoundsCheck
222  /// CHECK: ArraySet
223
224  // There is only one array access. It's not beneficial
225  // to create a compare with deoptimization instruction.
226  static void constantIndexing4(int[] array) {
227    array[0] = 1;
228  }
229
230
231  /// CHECK-START: void Main.constantIndexing5(int[]) BCE (before)
232  /// CHECK: BoundsCheck
233  /// CHECK: ArraySet
234  /// CHECK: BoundsCheck
235  /// CHECK: ArraySet
236
237  /// CHECK-START: void Main.constantIndexing5(int[]) BCE (after)
238  /// CHECK-NOT: Deoptimize
239  /// CHECK: BoundsCheck
240  /// CHECK: ArraySet
241  /// CHECK: BoundsCheck
242  /// CHECK: ArraySet
243
244  static void constantIndexing5(int[] array) {
245    // We don't apply the deoptimization for very large constant index
246    // since it's likely to be an anomaly and will throw AIOOBE.
247    array[Integer.MAX_VALUE - 1000] = 1;
248    array[Integer.MAX_VALUE - 999] = 1;
249    array[Integer.MAX_VALUE - 998] = 1;
250  }
251
252  /// 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) {
268    assertIsManaged();
269    constantIndexing6(array);
270  }
271
272  /// 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
287
288  /// 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
303
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
339  /// 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
352
353  /// 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
366
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
395  /// CHECK-START: void Main.loopPattern3(int[]) BCE (before)
396  /// CHECK: BoundsCheck
397  /// CHECK: ArraySet
398
399  /// CHECK-START: void Main.loopPattern3(int[]) BCE (after)
400  /// CHECK: BoundsCheck
401  /// CHECK: ArraySet
402
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
416  /// 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
427
428  /// 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
439
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
455
456  static byte readData() {
457    return 1;
458  }
459
460  /// CHECK-START: void Main.circularBufferProducer() BCE (before)
461  /// CHECK: BoundsCheck
462  /// CHECK: ArraySet
463
464  /// CHECK-START: void Main.circularBufferProducer() BCE (after)
465  /// CHECK-NOT: BoundsCheck
466  /// CHECK: ArraySet
467
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
478  /// CHECK-START: void Main.pyramid1(int[]) BCE (before)
479  /// CHECK: BoundsCheck
480  /// CHECK: ArraySet
481  /// CHECK: BoundsCheck
482  /// CHECK: ArraySet
483
484  /// CHECK-START: void Main.pyramid1(int[]) BCE (after)
485  /// CHECK-NOT: BoundsCheck
486  /// CHECK: ArraySet
487  /// CHECK-NOT: BoundsCheck
488  /// CHECK: ArraySet
489
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
499  /// CHECK-START: void Main.pyramid2(int[]) BCE (before)
500  /// CHECK: BoundsCheck
501  /// CHECK: ArraySet
502  /// CHECK: BoundsCheck
503  /// CHECK: ArraySet
504
505  /// CHECK-START: void Main.pyramid2(int[]) BCE (after)
506  /// CHECK-NOT: BoundsCheck
507  /// CHECK: ArraySet
508  /// CHECK-NOT: BoundsCheck
509  /// CHECK: ArraySet
510
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
520  /// CHECK-START: void Main.pyramid3(int[]) BCE (before)
521  /// CHECK: BoundsCheck
522  /// CHECK: ArraySet
523  /// CHECK: BoundsCheck
524  /// CHECK: ArraySet
525
526  /// CHECK-START: void Main.pyramid3(int[]) BCE (after)
527  /// CHECK-NOT: BoundsCheck
528  /// CHECK: ArraySet
529  /// CHECK-NOT: BoundsCheck
530  /// CHECK: ArraySet
531
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
541  /// CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
542  /// CHECK: BoundsCheck
543  /// CHECK: ArrayGet
544  /// CHECK: BoundsCheck
545  /// CHECK: ArrayGet
546
547  /// CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
548  /// CHECK-NOT: BoundsCheck
549  /// CHECK: ArrayGet
550  /// CHECK-NOT: BoundsCheck
551  /// CHECK: ArrayGet
552
553  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
569  /// 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
582
583  /// 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
594
595  /// 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
606
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
619
620  static int foo() {
621    try {
622      assertIsManaged();
623      // This will cause AIOOBE.
624      constantIndexing2(new int[3]);
625    } catch (ArrayIndexOutOfBoundsException e) {
626      assertIsManaged();  // This is to ensure that single-frame deoptimization works.
627                          // Will need to be updated if constantIndexing2 is inlined.
628      try {
629        // This will cause AIOOBE.
630        constantIndexingForward6(new int[3]);
631      } catch (ArrayIndexOutOfBoundsException e2) {
632        // Having deopted, we expect to be running interpreted at this point.
633        // Does not apply to debuggable, however, since we do not inline.
634        return 99;
635      }
636    }
637    return 0;
638  }
639
640
641  int sum;
642
643  /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before)
644  /// CHECK: BoundsCheck
645  /// CHECK: ArraySet
646  /// CHECK-NOT: BoundsCheck
647  /// CHECK: ArrayGet
648
649  /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after)
650  /// CHECK: Phi
651  /// CHECK-NOT: BoundsCheck
652  /// CHECK: ArraySet
653  /// CHECK-NOT: BoundsCheck
654  /// CHECK: ArrayGet
655  //  Added blocks at end for deoptimization.
656  /// CHECK: Exit
657  /// CHECK: If
658  /// CHECK: Deoptimize
659  /// CHECK: Deoptimize
660  /// CHECK: Deoptimize
661  /// CHECK-NOT: Deoptimize
662  /// CHECK: Goto
663  /// CHECK: Goto
664  /// CHECK: Goto
665
666  void foo1(int[] array, int start, int end, boolean expectInterpreter) {
667    // Three HDeoptimize will be added. Two for the index
668    // and one for null check on array (to hoist null
669    // check and array.length out of loop).
670    for (int i = start ; i < end; i++) {
671      if (expectInterpreter) {
672        assertIsInterpreted();
673      } else {
674        assertIsManaged();
675      }
676      array[i] = 1;
677      sum += array[i];
678    }
679  }
680
681
682  /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before)
683  /// CHECK: BoundsCheck
684  /// CHECK: ArraySet
685  /// CHECK-NOT: BoundsCheck
686  /// CHECK: ArrayGet
687  /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after)
688  /// CHECK: Phi
689  /// CHECK-NOT: BoundsCheck
690  /// CHECK: ArraySet
691  /// CHECK-NOT: BoundsCheck
692  /// CHECK: ArrayGet
693  //  Added blocks at end for deoptimization.
694  /// CHECK: Exit
695  /// CHECK: If
696  /// CHECK: Deoptimize
697  /// CHECK: Deoptimize
698  /// CHECK: Deoptimize
699  /// CHECK-NOT: Deoptimize
700  /// CHECK: Goto
701  /// CHECK: Goto
702  /// CHECK: Goto
703
704  void foo2(int[] array, int start, int end, boolean expectInterpreter) {
705    // Three HDeoptimize will be added. Two for the index
706    // and one for null check on array (to hoist null
707    // check and array.length out of loop).
708    for (int i = start ; i <= end; i++) {
709      if (expectInterpreter) {
710        assertIsInterpreted();
711      } else {
712        assertIsManaged();
713      }
714      array[i] = 1;
715      sum += array[i];
716    }
717  }
718
719
720  /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before)
721  /// CHECK: BoundsCheck
722  /// CHECK: ArraySet
723  /// CHECK-NOT: BoundsCheck
724  /// CHECK: ArrayGet
725  /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after)
726  /// CHECK: Phi
727  /// CHECK-NOT: BoundsCheck
728  /// CHECK: ArraySet
729  /// CHECK-NOT: BoundsCheck
730  /// CHECK: ArrayGet
731  //  Added blocks at end for deoptimization.
732  /// CHECK: Exit
733  /// CHECK: If
734  /// CHECK: Deoptimize
735  /// CHECK: Deoptimize
736  /// CHECK: Deoptimize
737  /// CHECK-NOT: Deoptimize
738  /// CHECK: Goto
739  /// CHECK: Goto
740  /// CHECK: Goto
741
742  void foo3(int[] array, int end, boolean expectInterpreter) {
743    // Three HDeoptimize will be added. Two for the index
744    // and one for null check on array (to hoist null check
745    // and array.length out of loop).
746    for (int i = 3 ; i <= end; i++) {
747      if (expectInterpreter) {
748        assertIsInterpreted();
749      } else {
750        assertIsManaged();
751      }
752      array[i] = 1;
753      sum += array[i];
754    }
755  }
756
757
758  /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before)
759  /// CHECK: BoundsCheck
760  /// CHECK: ArraySet
761  /// CHECK-NOT: BoundsCheck
762  /// CHECK: ArrayGet
763
764  /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after)
765  /// CHECK: Phi
766  /// CHECK-NOT: BoundsCheck
767  /// CHECK: ArraySet
768  /// CHECK-NOT: BoundsCheck
769  /// CHECK: ArrayGet
770  //  Added blocks at end for deoptimization.
771  /// CHECK: Exit
772  /// CHECK: If
773  /// CHECK: Deoptimize
774  /// CHECK: Deoptimize
775  /// CHECK: Deoptimize
776  /// CHECK-NOT: Deoptimize
777  /// CHECK: Goto
778  /// CHECK: Goto
779  /// CHECK: Goto
780
781  void foo4(int[] array, int end, boolean expectInterpreter) {
782    // Three HDeoptimize will be added. Two for the index
783    // and one for null check on array (to hoist null check
784    // and array.length out of loop).
785    for (int i = end ; i > 0; i--) {
786      if (expectInterpreter) {
787        assertIsInterpreted();
788      } else {
789        assertIsManaged();
790      }
791      array[i - 1] = 1;
792      sum += array[i - 1];
793    }
794  }
795
796
797  /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before)
798  /// CHECK: BoundsCheck
799  /// CHECK: ArraySet
800  /// CHECK: BoundsCheck
801  /// CHECK: ArrayGet
802  /// CHECK: BoundsCheck
803  /// CHECK: ArrayGet
804  /// CHECK: BoundsCheck
805  /// CHECK: ArrayGet
806
807  /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after)
808  /// CHECK-NOT: BoundsCheck
809  /// CHECK: ArraySet
810  /// CHECK: Phi
811  /// CHECK-NOT: BoundsCheck
812  /// CHECK: ArrayGet
813  /// CHECK-NOT: BoundsCheck
814  /// CHECK: ArrayGet
815  /// CHECK-NOT: BoundsCheck
816  /// CHECK: ArrayGet
817  //  Added blocks at end for deoptimization.
818  /// CHECK: Exit
819  /// CHECK: If
820  /// CHECK: Deoptimize
821  /// CHECK: Deoptimize
822  /// CHECK: Deoptimize
823  /// CHECK: Deoptimize
824  /// CHECK: Deoptimize
825  /// CHECK: Deoptimize
826  /// CHECK-NOT: Deoptimize
827  /// CHECK: Goto
828  /// CHECK: Goto
829  /// CHECK: Goto
830
831  void foo5(int[] array, int end, boolean expectInterpreter) {
832    // Bounds check in this loop can be eliminated without deoptimization.
833    for (int i = array.length - 1 ; i >= 0; i--) {
834      array[i] = 1;
835    }
836    // Several HDeoptimize will be added. Two for each index.
837    // The null check is not necessary.
838    for (int i = end - 2 ; i > 0; i--) {
839      if (expectInterpreter) {
840        assertIsInterpreted();
841      } else {
842        assertIsManaged();
843      }
844      sum += array[i - 1];
845      sum += array[i];
846      sum += array[i + 1];
847    }
848  }
849
850
851  /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before)
852  /// CHECK: BoundsCheck
853  /// CHECK: ArrayGet
854  /// CHECK: BoundsCheck
855  /// CHECK: ArrayGet
856  /// CHECK: BoundsCheck
857  /// CHECK: ArrayGet
858  /// CHECK: BoundsCheck
859  /// CHECK: ArrayGet
860  /// CHECK: BoundsCheck
861  /// CHECK: ArrayGet
862  /// CHECK-NOT: BoundsCheck
863  /// CHECK: ArraySet
864  /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after)
865  /// CHECK: Phi
866  /// CHECK-NOT: BoundsCheck
867  /// CHECK: ArrayGet
868  /// CHECK-NOT: BoundsCheck
869  /// CHECK: ArrayGet
870  /// CHECK-NOT: BoundsCheck
871  /// CHECK: ArrayGet
872  /// CHECK-NOT: BoundsCheck
873  /// CHECK: ArrayGet
874  /// CHECK-NOT: BoundsCheck
875  /// CHECK: ArrayGet
876  /// CHECK-NOT: BoundsCheck
877  /// CHECK: ArraySet
878  //  Added blocks at end for deoptimization.
879  /// CHECK: Exit
880  /// CHECK: If
881  /// CHECK: Deoptimize
882  /// CHECK: Deoptimize
883  /// CHECK: Deoptimize
884  /// CHECK: Deoptimize
885  /// CHECK: Deoptimize
886  /// CHECK: Deoptimize
887  /// CHECK: Deoptimize
888  /// CHECK: Deoptimize
889  /// CHECK: Deoptimize
890  /// CHECK: Deoptimize
891  /// CHECK: Deoptimize
892  /// CHECK-NOT: Deoptimize
893  /// CHECK: Goto
894  /// CHECK: Goto
895  /// CHECK: Goto
896
897  void foo6(int[] array, int start, int end, boolean expectInterpreter) {
898    // Several HDeoptimize will be added.
899    for (int i = end; i >= start; i--) {
900      if (expectInterpreter) {
901        assertIsInterpreted();
902      } else {
903        assertIsManaged();
904      }
905      array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5;
906    }
907  }
908
909
910  /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
911  /// CHECK: BoundsCheck
912  /// CHECK: ArrayGet
913  /// CHECK: BoundsCheck
914  /// CHECK: ArrayGet
915
916  /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
917  /// CHECK: Phi
918  /// CHECK: BoundsCheck
919  /// CHECK: ArrayGet
920  /// CHECK-NOT: BoundsCheck
921  /// CHECK: ArrayGet
922  //  Added blocks at end for deoptimization.
923  /// CHECK: Exit
924  /// CHECK: If
925  /// CHECK: Deoptimize
926  /// CHECK: Deoptimize
927  /// CHECK: Deoptimize
928  /// CHECK-NOT: Deoptimize
929  /// CHECK: Goto
930  /// CHECK: Goto
931  /// CHECK: Goto
932
933  void foo7(int[] array, int start, int end, boolean lowEnd) {
934    // Three HDeoptimize will be added. One for the index
935    // and one for null check on array (to hoist null
936    // check and array.length out of loop).
937    for (int i = start ; i < end; i++) {
938      if (lowEnd) {
939        // This array access isn't certain. So we don't
940        // use +1000 offset in decision making for deoptimization
941        // conditions.
942        sum += array[i + 1000];
943      }
944      sum += array[i];
945    }
946  }
947
948
949  /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before)
950  /// CHECK: BoundsCheck
951  /// CHECK: ArrayGet
952  /// CHECK: BoundsCheck
953  /// CHECK: ArraySet
954
955  /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after)
956  /// CHECK: Phi
957  /// CHECK-NOT: BoundsCheck
958  /// CHECK: ArrayGet
959  /// CHECK: Phi
960  /// CHECK-NOT: BoundsCheck
961  /// CHECK: ArraySet
962  //  Added blocks at end for deoptimization.
963  /// CHECK: Exit
964  /// CHECK: If
965  /// CHECK: Deoptimize
966  /// CHECK: Deoptimize
967  /// CHECK: Deoptimize
968  /// CHECK: Goto
969  /// CHECK: Goto
970  /// CHECK: Goto
971  /// CHECK: If
972  /// CHECK: Deoptimize
973  /// CHECK: Deoptimize
974  /// CHECK: Deoptimize
975  /// CHECK-NOT: Deoptimize
976  /// CHECK: Goto
977  /// CHECK: Goto
978  /// CHECK: Goto
979
980  void foo8(int[][] matrix, int start, int end) {
981    // Three HDeoptimize will be added for the outer loop,
982    // two for the index, and null check on matrix. Same
983    // for the inner loop.
984    for (int i = start; i < end; i++) {
985      int[] row = matrix[i];
986      for (int j = start; j < end; j++) {
987        row[j] = 1;
988      }
989    }
990  }
991
992
993  /// CHECK-START: void Main.foo9(int[], boolean) BCE (before)
994  /// CHECK: NullCheck
995  /// CHECK: BoundsCheck
996  /// CHECK: ArrayGet
997
998  /// CHECK-START: void Main.foo9(int[], boolean) BCE (after)
999  //  The loop is guaranteed to be entered. No need to transform the
1000  //  loop for loop body entry test.
1001  /// CHECK: Deoptimize
1002  /// CHECK: Deoptimize
1003  /// CHECK: Deoptimize
1004  /// CHECK-NOT: Deoptimize
1005  /// CHECK: Phi
1006  /// CHECK-NOT: NullCheck
1007  /// CHECK-NOT: BoundsCheck
1008  /// CHECK: ArrayGet
1009
1010  /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier_after_bce (after)
1011  //  Simplification removes the redundant check
1012  /// CHECK: Deoptimize
1013  /// CHECK: Deoptimize
1014  /// CHECK-NOT: Deoptimize
1015
1016  void foo9(int[] array, boolean expectInterpreter) {
1017    // Two HDeoptimize will be added. Two for the index
1018    // and one for null check on array.
1019    for (int i = 0 ; i < 10; i++) {
1020      if (expectInterpreter) {
1021        assertIsInterpreted();
1022      } else {
1023        assertIsManaged();
1024      }
1025      sum += array[i];
1026    }
1027  }
1028
1029
1030  /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
1031  /// CHECK: BoundsCheck
1032  /// CHECK: ArraySet
1033
1034  /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
1035  /// CHECK-NOT: Deoptimize
1036  /// CHECK: BoundsCheck
1037  /// CHECK: ArraySet
1038
1039  void partialLooping(int[] array, int start, int end) {
1040    // This loop doesn't cover the full range of [start, end) so
1041    // adding deoptimization is too aggressive, since end can be
1042    // greater than array.length but the loop is never going to work on
1043    // more than 2 elements.
1044    for (int i = start; i < end; i++) {
1045      if (i == 2) {
1046        return;
1047      }
1048      array[i] = 1;
1049    }
1050  }
1051
1052
1053  static void testUnknownBounds() {
1054    boolean caught = false;
1055    Main main = new Main();
1056    main.foo1(new int[10], 0, 10, false);
1057    if (main.sum != 10) {
1058      System.out.println("foo1 failed!");
1059    }
1060
1061    caught = false;
1062    main = new Main();
1063    try {
1064      main.foo1(new int[10], 0, 11, true);
1065    } catch (ArrayIndexOutOfBoundsException e) {
1066      caught = true;
1067    }
1068    if (!caught || main.sum != 10) {
1069      System.out.println("foo1 exception failed!");
1070    }
1071
1072    main = new Main();
1073    main.foo2(new int[10], 0, 9, false);
1074    if (main.sum != 10) {
1075      System.out.println("foo2 failed!");
1076    }
1077
1078    caught = false;
1079    main = new Main();
1080    try {
1081      main.foo2(new int[10], 0, 10, true);
1082    } catch (ArrayIndexOutOfBoundsException e) {
1083      caught = true;
1084    }
1085    if (!caught || main.sum != 10) {
1086      System.out.println("foo2 exception failed!");
1087    }
1088
1089    main = new Main();
1090    main.foo3(new int[10], 9, false);
1091    if (main.sum != 7) {
1092      System.out.println("foo3 failed!");
1093    }
1094
1095    caught = false;
1096    main = new Main();
1097    try {
1098      main.foo3(new int[10], 10, true);
1099    } catch (ArrayIndexOutOfBoundsException e) {
1100      caught = true;
1101    }
1102    if (!caught || main.sum != 7) {
1103      System.out.println("foo3 exception failed!");
1104    }
1105
1106    main = new Main();
1107    main.foo4(new int[10], 10, false);
1108    if (main.sum != 10) {
1109      System.out.println("foo4 failed!");
1110    }
1111
1112    caught = false;
1113    main = new Main();
1114    try {
1115      main.foo4(new int[10], 11, true);
1116    } catch (ArrayIndexOutOfBoundsException e) {
1117      caught = true;
1118    }
1119    if (!caught || main.sum != 0) {
1120      System.out.println("foo4 exception failed!");
1121    }
1122
1123    main = new Main();
1124    main.foo5(new int[10], 10, false);
1125    if (main.sum != 24) {
1126      System.out.println("foo5 failed!");
1127    }
1128
1129    caught = false;
1130    main = new Main();
1131    try {
1132      main.foo5(new int[10], 11, true);
1133    } catch (ArrayIndexOutOfBoundsException e) {
1134      caught = true;
1135    }
1136    if (!caught || main.sum != 2) {
1137      System.out.println("foo5 exception failed!");
1138    }
1139
1140    main = new Main();
1141    main.foo6(new int[10], 2, 7, false);
1142
1143    main = new Main();
1144    int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
1145    main.foo9(array9, false);
1146    if (main.sum != 45) {
1147      System.out.println("foo9 failed!");
1148    }
1149
1150    main = new Main();
1151    int[] array = new int[4];
1152    main.partialLooping(new int[3], 0, 4);
1153    if ((array[0] != 1) && (array[1] != 1) &&
1154        (array[2] != 0) && (array[3] != 0)) {
1155      System.out.println("partialLooping failed!");
1156    }
1157
1158    caught = false;
1159    main = new Main();
1160    try {
1161      main.foo6(new int[10], 2, 8, true);
1162    } catch (ArrayIndexOutOfBoundsException e) {
1163      caught = true;
1164    }
1165    if (!caught) {
1166      System.out.println("foo6 exception failed!");
1167    }
1168
1169    caught = false;
1170    main = new Main();
1171    try {
1172      main.foo6(new int[10], 1, 7, true);
1173    } catch (ArrayIndexOutOfBoundsException e) {
1174      caught = true;
1175    }
1176    if (!caught) {
1177      System.out.println("foo6 exception failed!");
1178    }
1179
1180  }
1181
1182  public void testExceptionMessage() {
1183    short[] B1 = new short[5];
1184    int[] B2 = new int[5];
1185    Exception err = null;
1186    try {
1187      testExceptionMessage1(B1, B2, null, -1, 6);
1188    } catch (Exception e) {
1189      err = e;
1190    }
1191    System.out.println(err);
1192  }
1193
1194  void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) {
1195    int j = finish + 77;
1196    // Bug: 22665511
1197    // A deoptimization will be triggered here right before the loop. Need to make
1198    // sure the value of j is preserved for the interpreter.
1199    for (int i = start; i <= finish; i++) {
1200      a2[j - 1] = a1[i + 1];
1201    }
1202  }
1203
1204  // Make sure this method is compiled with optimizing.
1205  /// CHECK-START: void Main.main(java.lang.String[]) register (after)
1206  /// CHECK: ParallelMove
1207
1208  public static void main(String[] args) {
1209    System.loadLibrary(args[0]);
1210
1211    if (!compiledWithOptimizing() ||
1212        !hasOatFile() ||
1213        runtimeIsSoftFail() ||
1214        isInterpreted()) {
1215      disableStackFrameAsserts();
1216    }
1217
1218    sieve(20);
1219
1220    int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
1221    bubbleSort(array);
1222    for (int i = 0; i < 8; i++) {
1223      if (array[i] != i) {
1224        System.out.println("bubble sort failed!");
1225      }
1226    }
1227
1228    array = new int[7];
1229    pyramid1(array);
1230    if (!isPyramid(array)) {
1231      System.out.println("pyramid1 failed!");
1232    }
1233
1234    array = new int[8];
1235    pyramid2(array);
1236    if (!isPyramid(array)) {
1237      System.out.println("pyramid2 failed!");
1238    }
1239
1240    java.util.Arrays.fill(array, -1);
1241    pyramid3(array);
1242    if (!isPyramid(array)) {
1243      System.out.println("pyramid3 failed!");
1244    }
1245
1246    // Make sure this value is kept after deoptimization.
1247    int i = 1;
1248    if (foo() + i != 100) {
1249      System.out.println("foo failed!");
1250    };
1251
1252    testUnknownBounds();
1253    new Main().testExceptionMessage();
1254  }
1255
1256  public static native boolean compiledWithOptimizing();
1257  public static native void disableStackFrameAsserts();
1258  public static native void assertIsManaged();
1259  public static native void assertIsInterpreted();
1260  public static native boolean hasOatFile();
1261  public static native boolean runtimeIsSoftFail();
1262  public static native boolean isInterpreted();
1263}
1264