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   /// CHECK-START: void Main.nonzeroLength(int[]) BCE (before)
    931   /// CHECK-DAG: BoundsCheck
    932   //
    933   /// CHECK-START: void Main.nonzeroLength(int[]) BCE (after)
    934   /// CHECK-NOT: BoundsCheck
    935   /// CHECK-NOT: Deoptimize
    936   public static void nonzeroLength(int[] a) {
    937     if (a.length != 0) {
    938       a[0] = 112;
    939     }
    940   }
    941 
    942   /// CHECK-START: void Main.knownLength(int[]) BCE (before)
    943   /// CHECK-DAG: BoundsCheck
    944   /// CHECK-DAG: BoundsCheck
    945   //
    946   /// CHECK-START: void Main.knownLength(int[]) BCE (after)
    947   /// CHECK-NOT: BoundsCheck
    948   /// CHECK-NOT: Deoptimize
    949   public static void knownLength(int[] a) {
    950     if (a.length == 2) {
    951       a[0] = -1;
    952       a[1] = -2;
    953     }
    954   }
    955 
    956   static int[][] mA;
    957 
    958   /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (before)
    959   //  Array references mA[i] and ..[j] both in inner loop.
    960   /// CHECK-DAG:  <<Get1:l\d+>>  ArrayGet [<<Array1:l\d+>>,<<Bounds1:i\d+>>] loop:<<InnerLoop:B\d+>>
    961   /// CHECK-DAG:  <<Array1>>     NullCheck [<<Field1:l\d+>>]                 loop:<<InnerLoop>>
    962   /// CHECK-DAG:  <<Len1:i\d+>>  ArrayLength [<<Array1>>]                    loop:<<InnerLoop>>
    963   /// CHECK-DAG:  <<Bounds1>>    BoundsCheck [<<Index1:i\d+>>,<<Len1>>]      loop:<<InnerLoop>>
    964   /// CHECK-DAG:  <<Get2:i\d+>>  ArrayGet [<<Array2:l\d+>>,<<Bounds2:i\d+>>] loop:<<InnerLoop>>
    965   /// CHECK-DAG:  <<Array2>>     NullCheck [<<Get1>>]                        loop:<<InnerLoop>>
    966   /// CHECK-DAG:  <<Len2:i\d+>>  ArrayLength [<<Array2>>]                    loop:<<InnerLoop>>
    967   /// CHECK-DAG:  <<Bounds2>>    BoundsCheck [<<Index2:i\d+>>,<<Len2>>]      loop:<<InnerLoop>>
    968   // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
    969   /// CHECK-DAG:                 InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>>
    970   /// CHECK-DAG:  <<Index2>>     Phi                                         loop:<<InnerLoop>>
    971   /// CHECK-DAG:  <<Index1>>     Phi                                         loop:<<OuterLoop:B\d+>>
    972   /// CHECK-DAG:  <<Field1>>     StaticFieldGet                              loop:none
    973   /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
    974   //
    975   /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
    976   //  Array reference mA[i] hoisted to same level as deopt.
    977   /// CHECK-DAG:                 Deoptimize                                  loop:<<OuterLoop:B\d+>>
    978   /// CHECK-DAG:                 ArrayLength                                 loop:<<OuterLoop>>
    979   /// CHECK-DAG:  <<Get1:l\d+>>  ArrayGet [<<Array1:l\d+>>,<<Index1:i\d+>>]  loop:<<OuterLoop>>
    980   //  Array reference ..[j] still in inner loop, with a direct index.
    981   /// CHECK-DAG:  <<Get2:i\d+>>  ArrayGet [<<Array2:l\d+>>,<<Index2:i\d+>>]  loop:<<InnerLoop:B\d+>>
    982   // Note: The ArtMethod* (typed as int or long) is optional after sharpening.
    983   /// CHECK-DAG:                 InvokeStaticOrDirect [<<Get2>>{{(,[ij]\d+)?}}] loop:<<InnerLoop>>
    984   /// CHECK-DAG:  <<Index2>>     Phi                                         loop:<<InnerLoop>>
    985   /// CHECK-DAG:  <<Index1>>     Phi                                         loop:<<OuterLoop>>
    986   //  Synthetic phi.
    987   /// CHECK-DAG:  <<Array2>>     Phi                                         loop:<<OuterLoop>>
    988   /// CHECK-DAG:  <<Array1>>     StaticFieldGet                              loop:none
    989   /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
    990   //
    991   /// CHECK-START: void Main.dynamicBCEAndIntrinsic(int) BCE (after)
    992   /// CHECK-NOT: NullCheck
    993   /// CHECK-NOT: BoundsCheck
    994   static void dynamicBCEAndIntrinsic(int n) {
    995     for (int i = 0; i < n; i++) {
    996       for (int j = 0; j < n; j++) {
    997         // Since intrinsic call cannot modify fields or arrays,
    998         // dynamic BCE and hoisting can be applied to the inner loop.
    999         mA[i][j] = Math.abs(mA[i][j]);
   1000       }
   1001     }
   1002   }
   1003 
   1004   static int foo() {
   1005     try {
   1006       assertIsManaged();
   1007       // This will cause AIOOBE.
   1008       $opt$noinline$constantIndexing2(new int[3]);
   1009     } catch (ArrayIndexOutOfBoundsException e) {
   1010       assertIsManaged();  // This is to ensure that single-frame deoptimization works.
   1011                           // Will need to be updated if $opt$noinline$constantIndexing2 is inlined.
   1012       try {
   1013         // This will cause AIOOBE.
   1014         constantIndexingForward6(new int[3]);
   1015       } catch (ArrayIndexOutOfBoundsException e2) {
   1016         // Having deopted, we expect to be running interpreted at this point.
   1017         // Does not apply to debuggable, however, since we do not inline.
   1018         return 99;
   1019       }
   1020     }
   1021     return 0;
   1022   }
   1023 
   1024 
   1025   int sum;
   1026 
   1027   /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (before)
   1028   /// CHECK: BoundsCheck
   1029   /// CHECK: ArraySet
   1030   /// CHECK-NOT: BoundsCheck
   1031   /// CHECK: ArrayGet
   1032 
   1033   /// CHECK-START: void Main.foo1(int[], int, int, boolean) BCE (after)
   1034   /// CHECK: Phi
   1035   /// CHECK-NOT: BoundsCheck
   1036   /// CHECK: ArraySet
   1037   /// CHECK-NOT: BoundsCheck
   1038   /// CHECK: ArrayGet
   1039   //  Added blocks at end for deoptimization.
   1040   /// CHECK: Exit
   1041   /// CHECK: If
   1042   /// CHECK: Deoptimize
   1043   /// CHECK: Deoptimize
   1044   /// CHECK: Deoptimize
   1045   /// CHECK-NOT: Deoptimize
   1046   /// CHECK: Goto
   1047   /// CHECK: Goto
   1048   /// CHECK: Goto
   1049 
   1050   void foo1(int[] array, int start, int end, boolean expectInterpreter) {
   1051     if (end < 0)
   1052       throw new Error("");
   1053     // Three HDeoptimize will be added. Two for the index
   1054     // and one for null check on array (to hoist null
   1055     // check and array.length out of loop).
   1056     for (int i = start ; i < end; i++) {
   1057       if (expectInterpreter) {
   1058         assertIsInterpreted();
   1059       } else {
   1060         assertIsManaged();
   1061       }
   1062       array[i] = 1;
   1063       sum += array[i];
   1064     }
   1065   }
   1066 
   1067 
   1068   /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (before)
   1069   /// CHECK: BoundsCheck
   1070   /// CHECK: ArraySet
   1071   /// CHECK-NOT: BoundsCheck
   1072   /// CHECK: ArrayGet
   1073   /// CHECK-START: void Main.foo2(int[], int, int, boolean) BCE (after)
   1074   /// CHECK: Phi
   1075   /// CHECK-NOT: BoundsCheck
   1076   /// CHECK: ArraySet
   1077   /// CHECK-NOT: BoundsCheck
   1078   /// CHECK: ArrayGet
   1079   //  Added blocks at end for deoptimization.
   1080   /// CHECK: Exit
   1081   /// CHECK: If
   1082   /// CHECK: Deoptimize
   1083   /// CHECK: Deoptimize
   1084   /// CHECK: Deoptimize
   1085   /// CHECK-NOT: Deoptimize
   1086   /// CHECK: Goto
   1087   /// CHECK: Goto
   1088   /// CHECK: Goto
   1089 
   1090   void foo2(int[] array, int start, int end, boolean expectInterpreter) {
   1091     if (end < 0)
   1092       throw new Error("");
   1093     // Three HDeoptimize will be added. Two for the index
   1094     // and one for null check on array (to hoist null
   1095     // check and array.length out of loop).
   1096     for (int i = start ; i <= end; i++) {
   1097       if (expectInterpreter) {
   1098         assertIsInterpreted();
   1099       } else {
   1100         assertIsManaged();
   1101       }
   1102       array[i] = 1;
   1103       sum += array[i];
   1104     }
   1105   }
   1106 
   1107 
   1108   /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (before)
   1109   /// CHECK: BoundsCheck
   1110   /// CHECK: ArraySet
   1111   /// CHECK-NOT: BoundsCheck
   1112   /// CHECK: ArrayGet
   1113   /// CHECK-START: void Main.foo3(int[], int, boolean) BCE (after)
   1114   /// CHECK: Phi
   1115   /// CHECK-NOT: BoundsCheck
   1116   /// CHECK: ArraySet
   1117   /// CHECK-NOT: BoundsCheck
   1118   /// CHECK: ArrayGet
   1119   //  Added blocks at end for deoptimization.
   1120   /// CHECK: Exit
   1121   /// CHECK: If
   1122   /// CHECK: Deoptimize
   1123   /// CHECK: Deoptimize
   1124   /// CHECK: Deoptimize
   1125   /// CHECK-NOT: Deoptimize
   1126   /// CHECK: Goto
   1127   /// CHECK: Goto
   1128   /// CHECK: Goto
   1129 
   1130   void foo3(int[] array, int end, boolean expectInterpreter) {
   1131     if (end < 0)
   1132       throw new Error("");
   1133     // Three HDeoptimize will be added. Two for the index
   1134     // and one for null check on array (to hoist null check
   1135     // and array.length out of loop).
   1136     for (int i = 3 ; i <= end; i++) {
   1137       if (expectInterpreter) {
   1138         assertIsInterpreted();
   1139       } else {
   1140         assertIsManaged();
   1141       }
   1142       array[i] = 1;
   1143       sum += array[i];
   1144     }
   1145   }
   1146 
   1147 
   1148   /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (before)
   1149   /// CHECK: BoundsCheck
   1150   /// CHECK: ArraySet
   1151   /// CHECK-NOT: BoundsCheck
   1152   /// CHECK: ArrayGet
   1153 
   1154   /// CHECK-START: void Main.foo4(int[], int, boolean) BCE (after)
   1155   /// CHECK: Phi
   1156   /// CHECK-NOT: BoundsCheck
   1157   /// CHECK: ArraySet
   1158   /// CHECK-NOT: BoundsCheck
   1159   /// CHECK: ArrayGet
   1160   //  Added blocks at end for deoptimization.
   1161   /// CHECK: Exit
   1162   /// CHECK: If
   1163   /// CHECK: Deoptimize
   1164   /// CHECK: Deoptimize
   1165   /// CHECK: Deoptimize
   1166   /// CHECK-NOT: Deoptimize
   1167   /// CHECK: Goto
   1168   /// CHECK: Goto
   1169   /// CHECK: Goto
   1170 
   1171   void foo4(int[] array, int end, boolean expectInterpreter) {
   1172     if (end < 0)
   1173       throw new Error("");
   1174     // Three HDeoptimize will be added. Two for the index
   1175     // and one for null check on array (to hoist null check
   1176     // and array.length out of loop).
   1177     for (int i = end ; i > 0; i--) {
   1178       if (expectInterpreter) {
   1179         assertIsInterpreted();
   1180       } else {
   1181         assertIsManaged();
   1182       }
   1183       array[i - 1] = 1;
   1184       sum += array[i - 1];
   1185     }
   1186   }
   1187 
   1188 
   1189   /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (before)
   1190   /// CHECK: BoundsCheck
   1191   /// CHECK: ArraySet
   1192   /// CHECK: BoundsCheck
   1193   /// CHECK: ArrayGet
   1194   /// CHECK: BoundsCheck
   1195   /// CHECK: ArrayGet
   1196   /// CHECK: BoundsCheck
   1197   /// CHECK: ArrayGet
   1198 
   1199   /// CHECK-START: void Main.foo5(int[], int, boolean) BCE (after)
   1200   /// CHECK-NOT: BoundsCheck
   1201   /// CHECK: ArraySet
   1202   /// CHECK: Phi
   1203   /// CHECK-NOT: BoundsCheck
   1204   /// CHECK: ArrayGet
   1205   /// CHECK-NOT: BoundsCheck
   1206   /// CHECK: ArrayGet
   1207   /// CHECK-NOT: BoundsCheck
   1208   /// CHECK: ArrayGet
   1209   //  Added blocks at end for deoptimization.
   1210   /// CHECK: Exit
   1211   /// CHECK: If
   1212   /// CHECK: Deoptimize
   1213   /// CHECK: Deoptimize
   1214   /// CHECK: Deoptimize
   1215   /// CHECK-NOT: Deoptimize
   1216   /// CHECK: Goto
   1217   /// CHECK: Goto
   1218   /// CHECK: Goto
   1219 
   1220   void foo5(int[] array, int end, boolean expectInterpreter) {
   1221     if (end < 0)
   1222       throw new Error("");
   1223     // Bounds check in this loop can be eliminated without deoptimization.
   1224     for (int i = array.length - 1 ; i >= 0; i--) {
   1225       array[i] = 1;
   1226     }
   1227     // Three HDeoptimize will be added for the bounds.
   1228     // The null check is not necessary.
   1229     for (int i = end - 2 ; i > 0; i--) {
   1230       if (expectInterpreter) {
   1231         assertIsInterpreted();
   1232       } else {
   1233         assertIsManaged();
   1234       }
   1235       sum += array[i - 1];
   1236       sum += array[i];
   1237       sum += array[i + 1];
   1238     }
   1239   }
   1240 
   1241 
   1242   /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (before)
   1243   /// CHECK: BoundsCheck
   1244   /// CHECK: ArrayGet
   1245   /// CHECK: BoundsCheck
   1246   /// CHECK: ArrayGet
   1247   /// CHECK: BoundsCheck
   1248   /// CHECK: ArrayGet
   1249   /// CHECK: BoundsCheck
   1250   /// CHECK: ArrayGet
   1251   /// CHECK: BoundsCheck
   1252   /// CHECK: ArrayGet
   1253   /// CHECK-NOT: BoundsCheck
   1254   /// CHECK: ArraySet
   1255   /// CHECK-START: void Main.foo6(int[], int, int, boolean) BCE (after)
   1256   /// CHECK: Phi
   1257   /// CHECK-NOT: BoundsCheck
   1258   /// CHECK: ArrayGet
   1259   /// CHECK-NOT: BoundsCheck
   1260   /// CHECK: ArrayGet
   1261   /// CHECK-NOT: BoundsCheck
   1262   /// CHECK: ArrayGet
   1263   /// CHECK-NOT: BoundsCheck
   1264   /// CHECK: ArrayGet
   1265   /// CHECK-NOT: BoundsCheck
   1266   /// CHECK: ArrayGet
   1267   /// CHECK-NOT: BoundsCheck
   1268   /// CHECK: ArraySet
   1269   //  Added blocks at end for deoptimization.
   1270   /// CHECK: Exit
   1271   /// CHECK: If
   1272   /// CHECK: Deoptimize
   1273   /// CHECK: Deoptimize
   1274   /// CHECK: Deoptimize
   1275   /// CHECK: Deoptimize
   1276   /// CHECK-NOT: Deoptimize
   1277   /// CHECK: Goto
   1278   /// CHECK: Goto
   1279   /// CHECK: Goto
   1280 
   1281   void foo6(int[] array, int start, int end, boolean expectInterpreter) {
   1282     if (end < 0)
   1283       throw new Error("");
   1284     for (int i = end; i >= start; i--) {
   1285       if (expectInterpreter) {
   1286         assertIsInterpreted();
   1287       } else {
   1288         assertIsManaged();
   1289       }
   1290       array[i] = (array[i-2] + array[i-1] + array[i] + array[i+1] + array[i+2]) / 5;
   1291     }
   1292   }
   1293 
   1294 
   1295   /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (before)
   1296   /// CHECK: BoundsCheck
   1297   /// CHECK: ArrayGet
   1298   /// CHECK: BoundsCheck
   1299   /// CHECK: ArrayGet
   1300 
   1301   /// CHECK-START: void Main.foo7(int[], int, int, boolean) BCE (after)
   1302   /// CHECK: Phi
   1303   /// CHECK: BoundsCheck
   1304   /// CHECK: ArrayGet
   1305   /// CHECK-NOT: BoundsCheck
   1306   /// CHECK: ArrayGet
   1307   //  Added blocks at end for deoptimization.
   1308   /// CHECK: Exit
   1309   /// CHECK: If
   1310   /// CHECK: Deoptimize
   1311   /// CHECK: Deoptimize
   1312   /// CHECK: Deoptimize
   1313   /// CHECK-NOT: Deoptimize
   1314   /// CHECK: Goto
   1315   /// CHECK: Goto
   1316   /// CHECK: Goto
   1317 
   1318   void foo7(int[] array, int start, int end, boolean lowEnd) {
   1319     // Three HDeoptimize will be added. One for the index
   1320     // and one for null check on array (to hoist null
   1321     // check and array.length out of loop).
   1322     for (int i = start ; i < end; i++) {
   1323       if (lowEnd) {
   1324         // This array access isn't certain. So we don't
   1325         // use +1000 offset in decision making for deoptimization
   1326         // conditions.
   1327         sum += array[i + 1000];
   1328       }
   1329       sum += array[i];
   1330     }
   1331   }
   1332 
   1333 
   1334   /// CHECK-START: void Main.foo8(int[][], int, int) BCE (before)
   1335   /// CHECK: BoundsCheck
   1336   /// CHECK: ArrayGet
   1337   /// CHECK: BoundsCheck
   1338   /// CHECK: ArraySet
   1339 
   1340   /// CHECK-START: void Main.foo8(int[][], int, int) BCE (after)
   1341   /// CHECK: Phi
   1342   /// CHECK-NOT: BoundsCheck
   1343   /// CHECK: ArrayGet
   1344   /// CHECK: Phi
   1345   /// CHECK-NOT: BoundsCheck
   1346   /// CHECK: ArraySet
   1347   //  Added blocks at end for deoptimization.
   1348   /// CHECK: Exit
   1349   /// CHECK: If
   1350   /// CHECK: Deoptimize
   1351   /// CHECK: Deoptimize
   1352   /// CHECK: Deoptimize
   1353   /// CHECK: Goto
   1354   /// CHECK: Goto
   1355   /// CHECK: Goto
   1356   /// CHECK: If
   1357   /// CHECK: Deoptimize
   1358   /// CHECK: Deoptimize
   1359   /// CHECK: Deoptimize
   1360   /// CHECK-NOT: Deoptimize
   1361   /// CHECK: Goto
   1362   /// CHECK: Goto
   1363   /// CHECK: Goto
   1364 
   1365   void foo8(int[][] matrix, int start, int end) {
   1366     // Three HDeoptimize will be added for the outer loop,
   1367     // two for the index, and null check on matrix. Same
   1368     // for the inner loop.
   1369     for (int i = start; i < end; i++) {
   1370       int[] row = matrix[i];
   1371       for (int j = start; j < end; j++) {
   1372         row[j] = 1;
   1373       }
   1374     }
   1375   }
   1376 
   1377 
   1378   /// CHECK-START: void Main.foo9(int[], boolean) BCE (before)
   1379   /// CHECK: NullCheck
   1380   /// CHECK: BoundsCheck
   1381   /// CHECK: ArrayGet
   1382 
   1383   /// CHECK-START: void Main.foo9(int[], boolean) BCE (after)
   1384   //  The loop is guaranteed to be entered. No need to transform the
   1385   //  loop for loop body entry test.
   1386   /// CHECK: Deoptimize
   1387   /// CHECK: Deoptimize
   1388   /// CHECK: Deoptimize
   1389   /// CHECK-NOT: Deoptimize
   1390   /// CHECK: Phi
   1391   /// CHECK-NOT: NullCheck
   1392   /// CHECK-NOT: BoundsCheck
   1393   /// CHECK: ArrayGet
   1394 
   1395   /// CHECK-START: void Main.foo9(int[], boolean) instruction_simplifier$after_bce (after)
   1396   //  Simplification removes the redundant check
   1397   /// CHECK: Deoptimize
   1398   /// CHECK: Deoptimize
   1399   /// CHECK-NOT: Deoptimize
   1400 
   1401   void foo9(int[] array, boolean expectInterpreter) {
   1402     // Three HDeoptimize will be added. Two for the index and one for null check on array. Then
   1403     // simplification removes one redundant HDeoptimize.
   1404     for (int i = 0 ; i < 10; i++) {
   1405       if (expectInterpreter) {
   1406         assertIsInterpreted();
   1407       } else {
   1408         assertIsManaged();
   1409       }
   1410       sum += array[i];
   1411     }
   1412   }
   1413 
   1414 
   1415   /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (before)
   1416   /// CHECK: BoundsCheck
   1417   /// CHECK: ArraySet
   1418 
   1419   /// CHECK-START: void Main.partialLooping(int[], int, int) BCE (after)
   1420   /// CHECK-NOT: Deoptimize
   1421   /// CHECK: BoundsCheck
   1422   /// CHECK: ArraySet
   1423 
   1424   void partialLooping(int[] array, int start, int end) {
   1425     // This loop doesn't cover the full range of [start, end) so
   1426     // adding deoptimization is too aggressive, since end can be
   1427     // greater than array.length but the loop is never going to work on
   1428     // more than 2 elements.
   1429     for (int i = start; i < end; i++) {
   1430       if (i == 2) {
   1431         return;
   1432       }
   1433       array[i] = 1;
   1434     }
   1435   }
   1436 
   1437 
   1438   static void testUnknownBounds() {
   1439     boolean caught = false;
   1440 
   1441     runAllConstantIndices();
   1442 
   1443     Main main = new Main();
   1444     main.foo1(new int[10], 0, 10, false);
   1445     if (main.sum != 10) {
   1446       System.out.println("foo1 failed!");
   1447     }
   1448 
   1449     caught = false;
   1450     main = new Main();
   1451     try {
   1452       main.foo1(new int[10], 0, 11, true);
   1453     } catch (ArrayIndexOutOfBoundsException e) {
   1454       caught = true;
   1455     }
   1456     if (!caught || main.sum != 10) {
   1457       System.out.println("foo1 exception failed!");
   1458     }
   1459 
   1460     main = new Main();
   1461     main.foo2(new int[10], 0, 9, false);
   1462     if (main.sum != 10) {
   1463       System.out.println("foo2 failed!");
   1464     }
   1465 
   1466     caught = false;
   1467     main = new Main();
   1468     try {
   1469       main.foo2(new int[10], 0, 10, true);
   1470     } catch (ArrayIndexOutOfBoundsException e) {
   1471       caught = true;
   1472     }
   1473     if (!caught || main.sum != 10) {
   1474       System.out.println("foo2 exception failed!");
   1475     }
   1476 
   1477     main = new Main();
   1478     main.foo3(new int[10], 9, false);
   1479     if (main.sum != 7) {
   1480       System.out.println("foo3 failed!");
   1481     }
   1482 
   1483     caught = false;
   1484     main = new Main();
   1485     try {
   1486       main.foo3(new int[10], 10, true);
   1487     } catch (ArrayIndexOutOfBoundsException e) {
   1488       caught = true;
   1489     }
   1490     if (!caught || main.sum != 7) {
   1491       System.out.println("foo3 exception failed!");
   1492     }
   1493 
   1494     main = new Main();
   1495     main.foo4(new int[10], 10, false);
   1496     if (main.sum != 10) {
   1497       System.out.println("foo4 failed!");
   1498     }
   1499 
   1500     caught = false;
   1501     main = new Main();
   1502     try {
   1503       main.foo4(new int[10], 11, true);
   1504     } catch (ArrayIndexOutOfBoundsException e) {
   1505       caught = true;
   1506     }
   1507     if (!caught || main.sum != 0) {
   1508       System.out.println("foo4 exception failed!");
   1509     }
   1510 
   1511     main = new Main();
   1512     main.foo5(new int[10], 10, false);
   1513     if (main.sum != 24) {
   1514       System.out.println("foo5 failed!");
   1515     }
   1516 
   1517     caught = false;
   1518     main = new Main();
   1519     try {
   1520       main.foo5(new int[10], 11, true);
   1521     } catch (ArrayIndexOutOfBoundsException e) {
   1522       caught = true;
   1523     }
   1524     if (!caught || main.sum != 2) {
   1525       System.out.println("foo5 exception failed!");
   1526     }
   1527 
   1528     main = new Main();
   1529     main.foo6(new int[10], 2, 7, false);
   1530 
   1531     main = new Main();
   1532     int[] array9 = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
   1533     main.foo9(array9, false);
   1534     if (main.sum != 45) {
   1535       System.out.println("foo9 failed!");
   1536     }
   1537 
   1538     main = new Main();
   1539     int[] array = new int[4];
   1540     main.partialLooping(new int[3], 0, 4);
   1541     if ((array[0] != 1) && (array[1] != 1) &&
   1542         (array[2] != 0) && (array[3] != 0)) {
   1543       System.out.println("partialLooping failed!");
   1544     }
   1545 
   1546     caught = false;
   1547     main = new Main();
   1548     try {
   1549       main.foo6(new int[10], 2, 8, true);
   1550     } catch (ArrayIndexOutOfBoundsException e) {
   1551       caught = true;
   1552     }
   1553     if (!caught) {
   1554       System.out.println("foo6 exception failed!");
   1555     }
   1556 
   1557     caught = false;
   1558     main = new Main();
   1559     try {
   1560       main.foo6(new int[10], 1, 7, true);
   1561     } catch (ArrayIndexOutOfBoundsException e) {
   1562       caught = true;
   1563     }
   1564     if (!caught) {
   1565       System.out.println("foo6 exception failed!");
   1566     }
   1567 
   1568   }
   1569 
   1570   public void testExceptionMessage() {
   1571     short[] B1 = new short[5];
   1572     int[] B2 = new int[5];
   1573     Exception err = null;
   1574     try {
   1575       testExceptionMessage1(B1, B2, null, -1, 6);
   1576     } catch (Exception e) {
   1577       err = e;
   1578     }
   1579     System.out.println(err);
   1580   }
   1581 
   1582   void testExceptionMessage1(short[] a1, int[] a2, long a3[], int start, int finish) {
   1583     int j = finish + 77;
   1584     // Bug: 22665511
   1585     // A deoptimization will be triggered here right before the loop. Need to make
   1586     // sure the value of j is preserved for the interpreter.
   1587     for (int i = start; i <= finish; i++) {
   1588       a2[j - 1] = a1[i + 1];
   1589     }
   1590   }
   1591 
   1592   // Make sure this method is compiled with optimizing.
   1593   /// CHECK-START: void Main.main(java.lang.String[]) register (after)
   1594   /// CHECK: ParallelMove
   1595 
   1596   public static void main(String[] args) {
   1597     System.loadLibrary(args[0]);
   1598 
   1599     if (!compiledWithOptimizing() ||
   1600         !hasOatFile() ||
   1601         runtimeIsSoftFail() ||
   1602         isInterpreted()) {
   1603       disableStackFrameAsserts();
   1604     }
   1605 
   1606     sieve(20);
   1607 
   1608     int[] array = {5, 2, 3, 7, 0, 1, 6, 4};
   1609     bubbleSort(array);
   1610     for (int i = 0; i < 8; i++) {
   1611       if (array[i] != i) {
   1612         System.out.println("bubble sort failed!");
   1613       }
   1614     }
   1615 
   1616     nonzeroLength(array);
   1617     if (array[0] != 112) {
   1618       System.out.println("nonzero length failed!");
   1619     }
   1620 
   1621     knownLength(array);
   1622     if (array[0] != 112 || array[1] != 1) {
   1623       System.out.println("nonzero length failed!");
   1624     }
   1625     array = new int[2];
   1626     knownLength(array);
   1627     if (array[0] != -1 || array[1] != -2) {
   1628       System.out.println("nonzero length failed!");
   1629     }
   1630 
   1631     // Zero length array does not break.
   1632     array = new int[0];
   1633     nonzeroLength(array);
   1634     knownLength(array);
   1635 
   1636     mA = new int[4][4];
   1637     for (int i = 0; i < 4; i++) {
   1638       for (int j = 0; j < 4; j++) {
   1639         mA[i][j] = -1;
   1640       }
   1641     }
   1642     dynamicBCEAndIntrinsic(4);
   1643     for (int i = 0; i < 4; i++) {
   1644       for (int j = 0; j < 4; j++) {
   1645         if (mA[i][i] != 1) {
   1646           System.out.println("dynamic bce failed!");
   1647         }
   1648       }
   1649     }
   1650 
   1651     array = new int[7];
   1652     pyramid1(array);
   1653     if (!isPyramid(array)) {
   1654       System.out.println("pyramid1 failed!");
   1655     }
   1656 
   1657     array = new int[8];
   1658     pyramid2(array);
   1659     if (!isPyramid(array)) {
   1660       System.out.println("pyramid2 failed!");
   1661     }
   1662 
   1663     java.util.Arrays.fill(array, -1);
   1664     pyramid3(array);
   1665     if (!isPyramid(array)) {
   1666       System.out.println("pyramid3 failed!");
   1667     }
   1668 
   1669     // Make sure this value is kept after deoptimization.
   1670     int i = 1;
   1671     if (foo() + i != 100) {
   1672       System.out.println("foo failed!");
   1673     };
   1674 
   1675     testUnknownBounds();
   1676     new Main().testExceptionMessage();
   1677   }
   1678 
   1679   public static native boolean compiledWithOptimizing();
   1680   public static native void disableStackFrameAsserts();
   1681   public static native void assertIsManaged();
   1682   public static native void assertIsInterpreted();
   1683   public static native boolean hasOatFile();
   1684   public static native boolean runtimeIsSoftFail();
   1685   public static native boolean isInterpreted();
   1686 }
   1687