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     // 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