Home | History | Annotate | Download | only in src
      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 
     17 public 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.loopPattern1(int[]) BCE (before)
    253   // CHECK: BoundsCheck
    254   // CHECK: ArraySet
    255   // CHECK: BoundsCheck
    256   // CHECK: ArraySet
    257   // CHECK: BoundsCheck
    258   // CHECK: ArraySet
    259   // CHECK: BoundsCheck
    260   // CHECK: ArraySet
    261   // CHECK: BoundsCheck
    262   // CHECK: ArraySet
    263   // CHECK: BoundsCheck
    264   // CHECK: ArraySet
    265   // CHECK: BoundsCheck
    266   // CHECK: ArraySet
    267 
    268   // CHECK-START: void Main.loopPattern1(int[]) BCE (after)
    269   // CHECK-NOT: BoundsCheck
    270   // CHECK: ArraySet
    271   // CHECK-NOT: BoundsCheck
    272   // CHECK: ArraySet
    273   // CHECK-NOT: BoundsCheck
    274   // CHECK: ArraySet
    275   // CHECK: BoundsCheck
    276   // CHECK: ArraySet
    277   // CHECK: BoundsCheck
    278   // CHECK: ArraySet
    279   // CHECK: BoundsCheck
    280   // CHECK: ArraySet
    281   // CHECK-NOT: BoundsCheck
    282   // CHECK: ArraySet
    283 
    284   static void loopPattern1(int[] array) {
    285     for (int i = 0; i < array.length; i++) {
    286       array[i] = 1;  // Bounds check can be eliminated.
    287     }
    288 
    289     for (int i = 1; i < array.length; i++) {
    290       array[i] = 1;  // Bounds check can be eliminated.
    291     }
    292 
    293     for (int i = 1; i < array.length - 1; i++) {
    294       array[i] = 1;  // Bounds check can be eliminated.
    295     }
    296 
    297     for (int i = -1; i < array.length; i++) {
    298       array[i] = 1;  // Bounds check can't be eliminated.
    299     }
    300 
    301     for (int i = 0; i <= array.length; i++) {
    302       array[i] = 1;  // Bounds check can't be eliminated.
    303     }
    304 
    305     for (int i = 0; i < array.length; i += 2) {
    306       // We don't have any assumption on max array length yet.
    307       // Bounds check can't be eliminated due to overflow concern.
    308       array[i] = 1;
    309     }
    310 
    311     for (int i = 1; i < array.length; i += 2) {
    312       // Bounds check can be eliminated since i is odd so the last
    313       // i that's less than array.length is at most (Integer.MAX_VALUE - 2).
    314       array[i] = 1;
    315     }
    316   }
    317 
    318 
    319   // CHECK-START: void Main.loopPattern2(int[]) BCE (before)
    320   // CHECK: BoundsCheck
    321   // CHECK: ArraySet
    322   // CHECK: BoundsCheck
    323   // CHECK: ArraySet
    324   // CHECK: BoundsCheck
    325   // CHECK: ArraySet
    326   // CHECK: BoundsCheck
    327   // CHECK: ArraySet
    328   // CHECK: BoundsCheck
    329   // CHECK: ArraySet
    330   // CHECK: BoundsCheck
    331   // CHECK: ArraySet
    332 
    333   // CHECK-START: void Main.loopPattern2(int[]) BCE (after)
    334   // CHECK-NOT: BoundsCheck
    335   // CHECK: ArraySet
    336   // CHECK-NOT: BoundsCheck
    337   // CHECK: ArraySet
    338   // CHECK-NOT: BoundsCheck
    339   // CHECK: ArraySet
    340   // CHECK: BoundsCheck
    341   // CHECK: ArraySet
    342   // CHECK: BoundsCheck
    343   // CHECK: ArraySet
    344   // CHECK-NOT: BoundsCheck
    345   // CHECK: ArraySet
    346 
    347   static void loopPattern2(int[] array) {
    348     for (int i = array.length - 1; i >= 0; i--) {
    349       array[i] = 1;  // Bounds check can be eliminated.
    350     }
    351 
    352     for (int i = array.length; i > 0; i--) {
    353       array[i - 1] = 1;  // Bounds check can be eliminated.
    354     }
    355 
    356     for (int i = array.length - 1; i > 0; i--) {
    357       array[i] = 1;  // Bounds check can be eliminated.
    358     }
    359 
    360     for (int i = array.length; i >= 0; i--) {
    361       array[i] = 1;  // Bounds check can't be eliminated.
    362     }
    363 
    364     for (int i = array.length; i >= 0; i--) {
    365       array[i - 1] = 1;  // Bounds check can't be eliminated.
    366     }
    367 
    368     for (int i = array.length; i > 0; i -= 20) {
    369       // For i >= 0, (i - 20 - 1) is guaranteed not to underflow.
    370       array[i - 1] = 1;  // Bounds check can be eliminated.
    371     }
    372   }
    373 
    374 
    375   // CHECK-START: void Main.loopPattern3(int[]) BCE (before)
    376   // CHECK: BoundsCheck
    377   // CHECK: ArraySet
    378 
    379   // CHECK-START: void Main.loopPattern3(int[]) BCE (after)
    380   // CHECK: BoundsCheck
    381   // CHECK: ArraySet
    382 
    383   static void loopPattern3(int[] array) {
    384     java.util.Random random = new java.util.Random();
    385     for (int i = 0; ; i++) {
    386       if (random.nextInt() % 1000 == 0 && i < array.length) {
    387         // Can't eliminate the bound check since not every i++ is
    388         // matched with a array length check, so there is some chance that i
    389         // overflows and is negative.
    390         array[i] = 1;
    391       }
    392     }
    393   }
    394 
    395 
    396   // CHECK-START: void Main.constantNewArray() BCE (before)
    397   // CHECK: BoundsCheck
    398   // CHECK: ArraySet
    399   // CHECK: BoundsCheck
    400   // CHECK: ArraySet
    401   // CHECK: BoundsCheck
    402   // CHECK: ArraySet
    403   // CHECK: BoundsCheck
    404   // CHECK: ArraySet
    405   // CHECK: BoundsCheck
    406   // CHECK: ArraySet
    407 
    408   // CHECK-START: void Main.constantNewArray() BCE (after)
    409   // CHECK-NOT: BoundsCheck
    410   // CHECK: ArraySet
    411   // CHECK: BoundsCheck
    412   // CHECK: ArraySet
    413   // CHECK-NOT: BoundsCheck
    414   // CHECK: ArraySet
    415   // CHECK-NOT: BoundsCheck
    416   // CHECK: ArraySet
    417   // CHECK: BoundsCheck
    418   // CHECK: ArraySet
    419 
    420   static void constantNewArray() {
    421     int[] array = new int[10];
    422     for (int i = 0; i < 10; i++) {
    423       array[i] = 1;  // Bounds check can be eliminated.
    424     }
    425 
    426     for (int i = 0; i <= 10; i++) {
    427       array[i] = 1;  // Bounds check can't be eliminated.
    428     }
    429 
    430     array[0] = 1;  // Bounds check can be eliminated.
    431     array[9] = 1;  // Bounds check can be eliminated.
    432     array[10] = 1; // Bounds check can't be eliminated.
    433   }
    434 
    435 
    436   static byte readData() {
    437     return 1;
    438   }
    439 
    440   // CHECK-START: void Main.circularBufferProducer() BCE (before)
    441   // CHECK: BoundsCheck
    442   // CHECK: ArraySet
    443 
    444   // CHECK-START: void Main.circularBufferProducer() BCE (after)
    445   // CHECK-NOT: BoundsCheck
    446   // CHECK: ArraySet
    447 
    448   static void circularBufferProducer() {
    449     byte[] array = new byte[4096];
    450     int i = 0;
    451     while (true) {
    452       array[i & (array.length - 1)] = readData();
    453       i++;
    454     }
    455   }
    456 
    457 
    458   // CHECK-START: void Main.pyramid1(int[]) BCE (before)
    459   // CHECK: BoundsCheck
    460   // CHECK: ArraySet
    461   // CHECK: BoundsCheck
    462   // CHECK: ArraySet
    463 
    464   // CHECK-START: void Main.pyramid1(int[]) BCE (after)
    465   // CHECK-NOT: BoundsCheck
    466   // CHECK: ArraySet
    467   // CHECK-NOT: BoundsCheck
    468   // CHECK: ArraySet
    469 
    470   // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
    471   static void pyramid1(int[] array) {
    472     for (int i = 0; i < (array.length + 1) / 2; i++) {
    473       array[i] = i;
    474       array[array.length - 1 - i] = i;
    475     }
    476   }
    477 
    478 
    479   // CHECK-START: void Main.pyramid2(int[]) BCE (before)
    480   // CHECK: BoundsCheck
    481   // CHECK: ArraySet
    482   // CHECK: BoundsCheck
    483   // CHECK: ArraySet
    484 
    485   // CHECK-START: void Main.pyramid2(int[]) BCE (after)
    486   // CHECK-NOT: BoundsCheck
    487   // CHECK: ArraySet
    488   // CHECK-NOT: BoundsCheck
    489   // CHECK: ArraySet
    490 
    491   // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
    492   static void pyramid2(int[] array) {
    493     for (int i = 0; i < (array.length + 1) >> 1; i++) {
    494       array[i] = i;
    495       array[array.length - 1 - i] = i;
    496     }
    497   }
    498 
    499 
    500   // CHECK-START: void Main.pyramid3(int[]) BCE (before)
    501   // CHECK: BoundsCheck
    502   // CHECK: ArraySet
    503   // CHECK: BoundsCheck
    504   // CHECK: ArraySet
    505 
    506   // CHECK-START: void Main.pyramid3(int[]) BCE (after)
    507   // CHECK-NOT: BoundsCheck
    508   // CHECK: ArraySet
    509   // CHECK-NOT: BoundsCheck
    510   // CHECK: ArraySet
    511 
    512   // Set array to something like {0, 1, 2, 3, 2, 1, 0}.
    513   static void pyramid3(int[] array) {
    514     for (int i = 0; i < (array.length + 1) >>> 1; i++) {
    515       array[i] = i;
    516       array[array.length - 1 - i] = i;
    517     }
    518   }
    519 
    520 
    521   // CHECK-START: boolean Main.isPyramid(int[]) BCE (before)
    522   // CHECK: BoundsCheck
    523   // CHECK: ArrayGet
    524   // CHECK: BoundsCheck
    525   // CHECK: ArrayGet
    526 
    527   // CHECK-START: boolean Main.isPyramid(int[]) BCE (after)
    528   // CHECK-NOT: BoundsCheck
    529   // CHECK: ArrayGet
    530   // CHECK-NOT: BoundsCheck
    531   // CHECK: ArrayGet
    532 
    533   static boolean isPyramid(int[] array) {
    534     int i = 0;
    535     int j = array.length - 1;
    536     while (i <= j) {
    537       if (array[i] != i) {
    538         return false;
    539       }
    540       if (array[j] != i) {
    541         return false;
    542       }
    543       i++; j--;
    544     }
    545     return true;
    546   }
    547 
    548 
    549   // CHECK-START: void Main.bubbleSort(int[]) GVN (before)
    550   // CHECK: BoundsCheck
    551   // CHECK: ArrayGet
    552   // CHECK: BoundsCheck
    553   // CHECK: ArrayGet
    554   // CHECK: BoundsCheck
    555   // CHECK: ArrayGet
    556   // CHECK: BoundsCheck
    557   // CHECK: ArrayGet
    558   // CHECK: BoundsCheck
    559   // CHECK: ArraySet
    560   // CHECK: BoundsCheck
    561   // CHECK: ArraySet
    562 
    563   // CHECK-START: void Main.bubbleSort(int[]) GVN (after)
    564   // CHECK: BoundsCheck
    565   // CHECK: ArrayGet
    566   // CHECK: BoundsCheck
    567   // CHECK: ArrayGet
    568   // CHECK-NOT: ArrayGet
    569   // CHECK-NOT: ArrayGet
    570   // CHECK-NOT: BoundsCheck
    571   // CHECK: ArraySet
    572   // CHECK-NOT: BoundsCheck
    573   // CHECK: ArraySet
    574 
    575   // CHECK-START: void Main.bubbleSort(int[]) BCE (after)
    576   // CHECK-NOT: BoundsCheck
    577   // CHECK: ArrayGet
    578   // CHECK-NOT: BoundsCheck
    579   // CHECK: ArrayGet
    580   // CHECK-NOT: ArrayGet
    581   // CHECK-NOT: ArrayGet
    582   // CHECK-NOT: BoundsCheck
    583   // CHECK: ArraySet
    584   // CHECK-NOT: BoundsCheck
    585   // CHECK: ArraySet
    586 
    587   static void bubbleSort(int[] array) {
    588     for (int i = 0; i < array.length - 1; i++) {
    589       for (int j = 0; j < array.length - i - 1; j++) {
    590         if (array[j] > array[j + 1]) {
    591           int temp = array[j + 1];
    592           array[j + 1] = array[j];
    593           array[j] = temp;
    594         }
    595       }
    596     }
    597   }
    598 
    599 
    600   static int foo() {
    601     try {
    602       // This will cause AIOOBE.
    603       constantIndexing2(new int[3]);
    604     } catch (ArrayIndexOutOfBoundsException e) {
    605       return 99;
    606     }
    607     return 0;
    608   }
    609 
    610 
    611   int sum;
    612 
    613   // CHECK-START: void Main.foo1(int[], int, int) BCE (before)
    614   // CHECK: BoundsCheck
    615   // CHECK: ArraySet
    616   // CHECK-NOT: BoundsCheck
    617   // CHECK: ArrayGet
    618 
    619   // CHECK-START: void Main.foo1(int[], int, int) BCE (after)
    620   // CHECK: Phi
    621   // CHECK-NOT: BoundsCheck
    622   // CHECK: ArraySet
    623   // CHECK-NOT: BoundsCheck
    624   // CHECK: ArrayGet
    625   //  Added blocks for deoptimization.
    626   // CHECK: If
    627   // CHECK: Goto
    628   // CHECK: Deoptimize
    629   // CHECK: Deoptimize
    630   // CHECK: Deoptimize
    631   // CHECK-NOT: Deoptimize
    632   // CHECK: Goto
    633   // CHECK: Phi
    634   // CHECK: Goto
    635 
    636   void foo1(int[] array, int start, int end) {
    637     // Three HDeoptimize will be added. One for
    638     // start >= 0, one for end <= array.length,
    639     // and one for null check on array (to hoist null
    640     // check and array.length out of loop).
    641     for (int i = start ; i < end; i++) {
    642       array[i] = 1;
    643       sum += array[i];
    644     }
    645   }
    646 
    647 
    648   // CHECK-START: void Main.foo2(int[], int, int) BCE (before)
    649   // CHECK: BoundsCheck
    650   // CHECK: ArraySet
    651   // CHECK-NOT: BoundsCheck
    652   // CHECK: ArrayGet
    653 
    654   // CHECK-START: void Main.foo2(int[], int, int) BCE (after)
    655   // CHECK: Phi
    656   // CHECK-NOT: BoundsCheck
    657   // CHECK: ArraySet
    658   // CHECK-NOT: BoundsCheck
    659   // CHECK: ArrayGet
    660   //  Added blocks for deoptimization.
    661   // CHECK: If
    662   // CHECK: Goto
    663   // CHECK: Deoptimize
    664   // CHECK: Deoptimize
    665   // CHECK: Deoptimize
    666   // CHECK-NOT: Deoptimize
    667   // CHECK: Goto
    668   // CHECK: Phi
    669   // CHECK: Goto
    670 
    671   void foo2(int[] array, int start, int end) {
    672     // Three HDeoptimize will be added. One for
    673     // start >= 0, one for end <= array.length,
    674     // and one for null check on array (to hoist null
    675     // check and array.length out of loop).
    676     for (int i = start ; i <= end; i++) {
    677       array[i] = 1;
    678       sum += array[i];
    679     }
    680   }
    681 
    682 
    683   // CHECK-START: void Main.foo3(int[], int) BCE (before)
    684   // CHECK: BoundsCheck
    685   // CHECK: ArraySet
    686   // CHECK-NOT: BoundsCheck
    687   // CHECK: ArrayGet
    688 
    689   // CHECK-START: void Main.foo3(int[], int) BCE (after)
    690   // CHECK: Phi
    691   // CHECK-NOT: BoundsCheck
    692   // CHECK: ArraySet
    693   // CHECK-NOT: BoundsCheck
    694   // CHECK: ArrayGet
    695   //  Added blocks for deoptimization.
    696   // CHECK: If
    697   // CHECK: Goto
    698   // CHECK: Deoptimize
    699   // CHECK: Deoptimize
    700   // CHECK-NOT: Deoptimize
    701   // CHECK: Goto
    702   // CHECK: Phi
    703   // CHECK: Goto
    704 
    705   void foo3(int[] array, int end) {
    706     // Two HDeoptimize will be added. One for end < array.length,
    707     // and one for null check on array (to hoist null check
    708     // and array.length out of loop).
    709     for (int i = 3 ; i <= end; i++) {
    710       array[i] = 1;
    711       sum += array[i];
    712     }
    713   }
    714 
    715 
    716   // CHECK-START: void Main.foo4(int[], int) BCE (before)
    717   // CHECK: BoundsCheck
    718   // CHECK: ArraySet
    719   // CHECK-NOT: BoundsCheck
    720   // CHECK: ArrayGet
    721 
    722   // CHECK-START: void Main.foo4(int[], int) BCE (after)
    723   // CHECK: Phi
    724   // CHECK-NOT: BoundsCheck
    725   // CHECK: ArraySet
    726   // CHECK-NOT: BoundsCheck
    727   // CHECK: ArrayGet
    728   //  Added blocks for deoptimization.
    729   // CHECK: If
    730   // CHECK: Goto
    731   // CHECK: Deoptimize
    732   // CHECK: Deoptimize
    733   // CHECK-NOT: Deoptimize
    734   // CHECK: Goto
    735   // CHECK: Phi
    736   // CHECK: Goto
    737 
    738   void foo4(int[] array, int end) {
    739     // Two HDeoptimize will be added. One for end <= array.length,
    740     // and one for null check on array (to hoist null check
    741     // and array.length out of loop).
    742     for (int i = end ; i > 0; i--) {
    743       array[i - 1] = 1;
    744       sum += array[i - 1];
    745     }
    746   }
    747 
    748 
    749   // CHECK-START: void Main.foo5(int[], int) BCE (before)
    750   // CHECK: BoundsCheck
    751   // CHECK: ArraySet
    752   // CHECK: BoundsCheck
    753   // CHECK: ArrayGet
    754   // CHECK: BoundsCheck
    755   // CHECK: ArrayGet
    756   // CHECK: BoundsCheck
    757   // CHECK: ArrayGet
    758 
    759   // CHECK-START: void Main.foo5(int[], int) BCE (after)
    760   // CHECK-NOT: BoundsCheck
    761   // CHECK: ArraySet
    762   // CHECK: Phi
    763   // CHECK-NOT: BoundsCheck
    764   // CHECK: ArrayGet
    765   // CHECK-NOT: BoundsCheck
    766   // CHECK: ArrayGet
    767   // CHECK-NOT: BoundsCheck
    768   // CHECK: ArrayGet
    769   //  Added blocks for deoptimization.
    770   // CHECK: If
    771   // CHECK: Goto
    772   // CHECK: Deoptimize
    773   // CHECK-NOT: Deoptimize
    774   // CHECK: Goto
    775   //  array.length is defined before the loop header so no phi is needed.
    776   // CHECK-NOT: Phi
    777   // CHECK: Goto
    778 
    779   void foo5(int[] array, int end) {
    780     // Bounds check in this loop can be eliminated without deoptimization.
    781     for (int i = array.length - 1 ; i >= 0; i--) {
    782       array[i] = 1;
    783     }
    784     // One HDeoptimize will be added.
    785     // It's for (end - 2 <= array.length - 2).
    786     for (int i = end - 2 ; i > 0; i--) {
    787       sum += array[i - 1];
    788       sum += array[i];
    789       sum += array[i + 1];
    790     }
    791   }
    792 
    793 
    794   // CHECK-START: void Main.foo6(int[], int, int) BCE (before)
    795   // CHECK: BoundsCheck
    796   // CHECK: ArrayGet
    797   // CHECK: BoundsCheck
    798   // CHECK: ArrayGet
    799   // CHECK: BoundsCheck
    800   // CHECK: ArrayGet
    801   // CHECK: BoundsCheck
    802   // CHECK: ArrayGet
    803   // CHECK: BoundsCheck
    804   // CHECK: ArrayGet
    805   // CHECK-NOT: BoundsCheck
    806   // CHECK: ArraySet
    807 
    808   // CHECK-START: void Main.foo6(int[], int, int) BCE (after)
    809   // CHECK: Phi
    810   // CHECK-NOT: BoundsCheck
    811   // CHECK: ArrayGet
    812   // CHECK-NOT: BoundsCheck
    813   // CHECK: ArrayGet
    814   // CHECK-NOT: BoundsCheck
    815   // CHECK: ArrayGet
    816   // CHECK-NOT: BoundsCheck
    817   // CHECK: ArrayGet
    818   // CHECK-NOT: BoundsCheck
    819   // CHECK: ArrayGet
    820   // CHECK-NOT: BoundsCheck
    821   // CHECK: ArraySet
    822   //  Added blocks for deoptimization.
    823   // CHECK: If
    824   // CHECK: Goto
    825   // CHECK: Deoptimize
    826   // CHECK: Deoptimize
    827   // CHECK: Deoptimize
    828   // CHECK-NOT: Deoptimize
    829   // CHECK: Goto
    830   // CHECK: Phi
    831   // CHECK: Goto
    832   // CHECK-NOT: Deoptimize
    833 
    834   void foo6(int[] array, int start, int end) {
    835     // Three HDeoptimize will be added. One for
    836     // start >= 2, one for end <= array.length - 3,
    837     // and one for null check on array (to hoist null
    838     // check and array.length out of loop).
    839     for (int i = end; i >= start; i--) {
    840       array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5;
    841     }
    842   }
    843 
    844 
    845   // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
    846   // CHECK: BoundsCheck
    847   // CHECK: ArrayGet
    848   // CHECK: BoundsCheck
    849   // CHECK: ArrayGet
    850 
    851   // CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
    852   // CHECK: Phi
    853   // CHECK: BoundsCheck
    854   // CHECK: ArrayGet
    855   // CHECK-NOT: BoundsCheck
    856   // CHECK: ArrayGet
    857   //  Added blocks for deoptimization.
    858   // CHECK: If
    859   // CHECK: Goto
    860   // CHECK: Deoptimize
    861   // CHECK: Deoptimize
    862   // CHECK: Deoptimize
    863   // CHECK-NOT: Deoptimize
    864   // CHECK: Goto
    865   // CHECK: Phi
    866   // CHECK: Goto
    867 
    868   void foo7(int[] array, int start, int end, boolean lowEnd) {
    869     // Three HDeoptimize will be added. One for
    870     // start >= 0, one for end <= array.length,
    871     // and one for null check on array (to hoist null
    872     // check and array.length out of loop).
    873     for (int i = start ; i < end; i++) {
    874       if (lowEnd) {
    875         // This array access isn't certain. So we don't
    876         // use +1000 offset in decision making for deoptimization
    877         // conditions.
    878         sum += array[i + 1000];
    879       }
    880       sum += array[i];
    881     }
    882   }
    883 
    884 
    885   // CHECK-START: void Main.foo8(int[][], int, int) BCE (before)
    886   // CHECK: BoundsCheck
    887   // CHECK: ArrayGet
    888   // CHECK: BoundsCheck
    889   // CHECK: ArraySet
    890 
    891   // CHECK-START: void Main.foo8(int[][], int, int) BCE (after)
    892   // CHECK: Phi
    893   // CHECK-NOT: BoundsCheck
    894   // CHECK: ArrayGet
    895   // CHECK: Phi
    896   // CHECK-NOT: BoundsCheck
    897   // CHECK: ArraySet
    898   //  Added blocks for deoptimization.
    899   // CHECK: If
    900   // CHECK: Goto
    901   // CHECK: Deoptimize
    902   // CHECK: Deoptimize
    903   // CHECK: Deoptimize
    904   // CHECK: Deoptimize
    905   // CHECK: Deoptimize
    906   // CHECK: Deoptimize
    907   // CHECK-NOT: Deoptimize
    908   // CHECK: Goto
    909   // CHECK: Phi
    910   // CHECK: Goto
    911 
    912   void foo8(int[][] matrix, int start, int end) {
    913     // Three HDeoptimize will be added for the outer loop.
    914     // start >= 0, end <= matrix.length, and null check on matrix.
    915     // Three HDeoptimize will be added for the inner loop
    916     // start >= 0 (TODO: this may be optimized away),
    917     // end <= row.length, and null check on row.
    918     for (int i = start; i < end; i++) {
    919       int[] row = matrix[i];
    920       for (int j = start; j < end; j++) {
    921         row[j] = 1;
    922       }
    923     }
    924   }
    925 
    926 
    927   // CHECK-START: void Main.foo9(int[]) BCE (before)
    928   // CHECK: NullCheck
    929   // CHECK: BoundsCheck
    930   // CHECK: ArrayGet
    931 
    932   // CHECK-START: void Main.foo9(int[]) BCE (after)
    933   //  The loop is guaranteed to be entered. No need to transform the
    934   //  loop for loop body entry test.
    935   // CHECK: Deoptimize
    936   // CHECK: Deoptimize
    937   // CHECK-NOT: Deoptimize
    938   // CHECK: Phi
    939   // CHECK-NOT: NullCheck
    940   // CHECK-NOT: BoundsCheck
    941   // CHECK: ArrayGet
    942 
    943   void foo9(int[] array) {
    944     // Two HDeoptimize will be added. One for
    945     // 10 <= array.length, and one for null check on array.
    946     for (int i = 0 ; i < 10; i++) {
    947       sum += array[i];
    948     }
    949   }
    950 
    951 
    952   // CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
    953   // CHECK: BoundsCheck
    954   // CHECK: ArraySet
    955 
    956   // CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
    957   // CHECK-NOT: Deoptimize
    958   // CHECK: BoundsCheck
    959   // CHECK: ArraySet
    960 
    961   void partialLooping(int[] array, int start, int end) {
    962     // This loop doesn't cover the full range of [start, end) so
    963     // adding deoptimization is too aggressive, since end can be
    964     // greater than array.length but the loop is never going to work on
    965     // more than 2 elements.
    966     for (int i = start; i < end; i++) {
    967       if (i == 2) {
    968         return;
    969       }
    970       array[i] = 1;
    971     }
    972   }
    973 
    974 
    975   static void testUnknownBounds() {
    976     boolean caught = false;
    977     Main main = new Main();
    978     main.foo1(new int[10], 0, 10);
    979     if (main.sum != 10) {
    980       System.out.println("foo1 failed!");
    981     }
    982 
    983     caught = false;
    984     main = new Main();
    985     try {
    986       main.foo1(new int[10], 0, 11);
    987     } catch (ArrayIndexOutOfBoundsException e) {
    988       caught = true;
    989     }
    990     if (!caught || main.sum != 10) {
    991       System.out.println("foo1 exception failed!");
    992     }
    993 
    994     main = new Main();
    995     main.foo2(new int[10], 0, 9);
    996     if (main.sum != 10) {
    997       System.out.println("foo2 failed!");
    998     }
    999 
   1000     caught = false;
   1001     main = new Main();
   1002     try {
   1003       main.foo2(new int[10], 0, 10);
   1004     } catch (ArrayIndexOutOfBoundsException e) {
   1005       caught = true;
   1006     }
   1007     if (!caught || main.sum != 10) {
   1008       System.out.println("foo2 exception failed!");
   1009     }
   1010 
   1011     main = new Main();
   1012     main.foo3(new int[10], 9);
   1013     if (main.sum != 7) {
   1014       System.out.println("foo3 failed!");
   1015     }
   1016 
   1017     caught = false;
   1018     main = new Main();
   1019     try {
   1020       main.foo3(new int[10], 10);
   1021     } catch (ArrayIndexOutOfBoundsException e) {
   1022       caught = true;
   1023     }
   1024     if (!caught || main.sum != 7) {
   1025       System.out.println("foo3 exception failed!");
   1026     }
   1027 
   1028     main = new Main();
   1029     main.foo4(new int[10], 10);
   1030     if (main.sum != 10) {
   1031       System.out.println("foo4 failed!");
   1032     }
   1033 
   1034     caught = false;
   1035     main = new Main();
   1036     try {
   1037       main.foo4(new int[10], 11);
   1038     } catch (ArrayIndexOutOfBoundsException e) {
   1039       caught = true;
   1040     }
   1041     if (!caught || main.sum != 0) {
   1042       System.out.println("foo4 exception failed!");
   1043     }
   1044 
   1045     main = new Main();
   1046     main.foo5(new int[10], 10);
   1047     if (main.sum != 24) {
   1048       System.out.println("foo5 failed!");
   1049     }
   1050 
   1051     caught = false;
   1052     main = new Main();
   1053     try {
   1054       main.foo5(new int[10], 11);
   1055     } catch (ArrayIndexOutOfBoundsException e) {
   1056       caught = true;
   1057     }
   1058     if (!caught || main.sum != 2) {
   1059       System.out.println("foo5 exception failed!");
   1060     }
   1061 
   1062     main = new Main();
   1063     main.foo6(new int[10], 2, 7);
   1064 
   1065     main = new Main();
   1066     int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
   1067     main.foo9(array9);
   1068     if (main.sum != 45) {
   1069       System.out.println("foo9 failed!");
   1070     }
   1071 
   1072     main = new Main();
   1073     int[] array = new int[4];
   1074     main.partialLooping(new int[3], 0, 4);
   1075     if ((array[0] != 1) && (array[1] != 1) &&
   1076         (array[2] != 0) && (array[3] != 0)) {
   1077       System.out.println("partialLooping failed!");
   1078     }
   1079 
   1080     caught = false;
   1081     main = new Main();
   1082     try {
   1083       main.foo6(new int[10], 2, 8);
   1084     } catch (ArrayIndexOutOfBoundsException e) {
   1085       caught = true;
   1086     }
   1087     if (!caught) {
   1088       System.out.println("foo6 exception failed!");
   1089     }
   1090 
   1091     caught = false;
   1092     main = new Main();
   1093     try {
   1094       main.foo6(new int[10], 1, 7);
   1095     } catch (ArrayIndexOutOfBoundsException e) {
   1096       caught = true;
   1097     }
   1098     if (!caught) {
   1099       System.out.println("foo6 exception failed!");
   1100     }
   1101 
   1102   }
   1103 
   1104   public void testExceptionMessage() {
   1105     short[] B1 = new short[5];
   1106     int[] B2 = new int[5];
   1107     Exception err = null;
   1108     try {
   1109       testExceptionMessage1(B1, B2, null, -1, 6);
   1110     } catch (Exception e) {
   1111       err = e;
   1112     }
   1113     System.out.println(err);
   1114   }
   1115 
   1116   void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) {
   1117     int j = finish + 77;
   1118     // Bug: 22665511
   1119     // A deoptimization will be triggered here right before the loop. Need to make
   1120     // sure the value of j is preserved for the interpreter.
   1121     for (int i = start; i <= finish; i++) {
   1122       a2[j - 1] = a1[i + 1];
   1123     }
   1124   }
   1125 
   1126   // Make sure this method is compiled with optimizing.
   1127   // CHECK-START: void Main.main(java.lang.String[]) register (after)
   1128   // CHECK: ParallelMove
   1129 
   1130   public static void main(String[] args) {
   1131     sieve(20);
   1132 
   1133     int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
   1134     bubbleSort(array);
   1135     for (int i = 0; i < 8; i++) {
   1136       if (array[i] != i) {
   1137         System.out.println("bubble sort failed!");
   1138       }
   1139     }
   1140 
   1141     array = new int[7];
   1142     pyramid1(array);
   1143     if (!isPyramid(array)) {
   1144       System.out.println("pyramid1 failed!");
   1145     }
   1146 
   1147     array = new int[8];
   1148     pyramid2(array);
   1149     if (!isPyramid(array)) {
   1150       System.out.println("pyramid2 failed!");
   1151     }
   1152 
   1153     java.util.Arrays.fill(array, -1);
   1154     pyramid3(array);
   1155     if (!isPyramid(array)) {
   1156       System.out.println("pyramid3 failed!");
   1157     }
   1158 
   1159     // Make sure this value is kept after deoptimization.
   1160     int i = 1;
   1161     if (foo() + i != 100) {
   1162       System.out.println("foo failed!");
   1163     };
   1164 
   1165     testUnknownBounds();
   1166     new Main().testExceptionMessage();
   1167   }
   1168 
   1169 }
   1170