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 //
     18 // Test on loop optimizations, in particular around less common induction.
     19 //
     20 public class Main {
     21 
     22   static int sResult;
     23 
     24   //
     25   // Various sequence variables used in bound checks.
     26   //
     27 
     28   /// CHECK-START: void Main.bubble(int[]) BCE (before)
     29   /// CHECK-DAG: BoundsCheck
     30   /// CHECK-DAG: BoundsCheck
     31   //
     32   /// CHECK-START: void Main.bubble(int[]) BCE (after)
     33   /// CHECK-NOT: BoundsCheck
     34   /// CHECK-NOT: Deoptimize
     35   private static void bubble(int[] a) {
     36     for (int i = a.length; --i >= 0;) {
     37       for (int j = 0; j < i; j++) {
     38         if (a[j] > a[j+1]) {
     39           int tmp = a[j];
     40           a[j]  = a[j+1];
     41           a[j+1] = tmp;
     42         }
     43       }
     44     }
     45   }
     46 
     47   /// CHECK-START: int Main.periodicIdiom(int) BCE (before)
     48   /// CHECK-DAG: BoundsCheck
     49   //
     50   /// CHECK-START: int Main.periodicIdiom(int) BCE (after)
     51   /// CHECK-NOT: BoundsCheck
     52   /// CHECK-NOT: Deoptimize
     53   private static int periodicIdiom(int tc) {
     54     int[] x = { 1, 3 };
     55     // Loop with periodic sequence (0, 1).
     56     int k = 0;
     57     int result = 0;
     58     for (int i = 0; i < tc; i++) {
     59       result += x[k];
     60       k = 1 - k;
     61     }
     62     return result;
     63   }
     64 
     65   /// CHECK-START: int Main.periodicSequence2(int) BCE (before)
     66   /// CHECK-DAG: BoundsCheck
     67   //
     68   /// CHECK-START: int Main.periodicSequence2(int) BCE (after)
     69   /// CHECK-NOT: BoundsCheck
     70   /// CHECK-NOT: Deoptimize
     71   private static int periodicSequence2(int tc) {
     72     int[] x = { 1, 3 };
     73     // Loop with periodic sequence (0, 1).
     74     int k = 0;
     75     int l = 1;
     76     int result = 0;
     77     for (int i = 0; i < tc; i++) {
     78       result += x[k];
     79       int t = l;
     80       l = k;
     81       k = t;
     82     }
     83     return result;
     84   }
     85 
     86   /// CHECK-START: int Main.periodicSequence4(int) BCE (before)
     87   /// CHECK-DAG: BoundsCheck
     88   /// CHECK-DAG: BoundsCheck
     89   /// CHECK-DAG: BoundsCheck
     90   /// CHECK-DAG: BoundsCheck
     91   //
     92   /// CHECK-START: int Main.periodicSequence4(int) BCE (after)
     93   /// CHECK-NOT: BoundsCheck
     94   /// CHECK-NOT: Deoptimize
     95   private static int periodicSequence4(int tc) {
     96     int[] x = { 1, 3, 5, 7 };
     97     // Loop with periodic sequence (0, 1, 2, 3).
     98     int k = 0;
     99     int l = 1;
    100     int m = 2;
    101     int n = 3;
    102     int result = 0;
    103     for (int i = 0; i < tc; i++) {
    104       result += x[k] + x[l] + x[m] + x[n];  // all used at once
    105       int t = n;
    106       n = k;
    107       k = l;
    108       l = m;
    109       m = t;
    110     }
    111     return result;
    112   }
    113 
    114   /// CHECK-START: int Main.periodicXorSequence(int) BCE (before)
    115   /// CHECK-DAG: BoundsCheck
    116   //
    117   /// CHECK-START: int Main.periodicXorSequence(int) BCE (after)
    118   /// CHECK-NOT: BoundsCheck
    119   /// CHECK-NOT: Deoptimize
    120   private static int periodicXorSequence(int tc) {
    121     int[] x = { 1, 3 };
    122     // Loop with periodic sequence (0, 1).
    123     int k = 0;
    124     int result = 0;
    125     for (int i = 0; i < tc; i++) {
    126       result += x[k];
    127       k ^= 1;
    128     }
    129     return result;
    130   }
    131 
    132   /// CHECK-START: int Main.justRightUp1() BCE (before)
    133   /// CHECK-DAG: BoundsCheck
    134   //
    135   /// CHECK-START: int Main.justRightUp1() BCE (after)
    136   /// CHECK-NOT: BoundsCheck
    137   /// CHECK-NOT: Deoptimize
    138   private static int justRightUp1() {
    139     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    140     int result = 0;
    141     for (int i = Integer.MAX_VALUE - 10, k = 0; i < Integer.MAX_VALUE; i++) {
    142       result += x[k++];
    143     }
    144     return result;
    145   }
    146 
    147   /// CHECK-START: int Main.justRightUp2() BCE (before)
    148   /// CHECK-DAG: BoundsCheck
    149   //
    150   /// CHECK-START: int Main.justRightUp2() BCE (after)
    151   /// CHECK-NOT: BoundsCheck
    152   /// CHECK-NOT: Deoptimize
    153   private static int justRightUp2() {
    154     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    155     int result = 0;
    156     for (int i = Integer.MAX_VALUE - 10; i < Integer.MAX_VALUE; i++) {
    157       result += x[i - Integer.MAX_VALUE + 10];
    158     }
    159     return result;
    160   }
    161 
    162   /// CHECK-START: int Main.justRightUp3() BCE (before)
    163   /// CHECK-DAG: BoundsCheck
    164   //
    165   /// CHECK-START: int Main.justRightUp3() BCE (after)
    166   /// CHECK-NOT: BoundsCheck
    167   /// CHECK-NOT: Deoptimize
    168   private static int justRightUp3() {
    169     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    170     int result = 0;
    171     for (int i = Integer.MAX_VALUE - 10, k = 0; i <= Integer.MAX_VALUE - 1; i++) {
    172       result += x[k++];
    173     }
    174     return result;
    175   }
    176 
    177   /// CHECK-START: int Main.justOOBUp() BCE (before)
    178   /// CHECK-DAG: BoundsCheck
    179   //
    180   /// CHECK-START: int Main.justOOBUp() BCE (after)
    181   /// CHECK-DAG: BoundsCheck
    182   //
    183   /// CHECK-START: int Main.justOOBUp() BCE (after)
    184   /// CHECK-NOT: Deoptimize
    185   private static int justOOBUp() {
    186     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    187     int result = 0;
    188     // Infinite loop!
    189     for (int i = Integer.MAX_VALUE - 9, k = 0; i <= Integer.MAX_VALUE; i++) {
    190       result += x[k++];
    191     }
    192     return result;
    193   }
    194 
    195   /// CHECK-START: int Main.justRightDown1() BCE (before)
    196   /// CHECK-DAG: BoundsCheck
    197   //
    198   /// CHECK-START: int Main.justRightDown1() BCE (after)
    199   /// CHECK-NOT: BoundsCheck
    200   /// CHECK-NOT: Deoptimize
    201   private static int justRightDown1() {
    202     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    203     int result = 0;
    204     for (int i = Integer.MIN_VALUE + 10, k = 0; i > Integer.MIN_VALUE; i--) {
    205       result += x[k++];
    206     }
    207     return result;
    208   }
    209 
    210   /// CHECK-START: int Main.justRightDown2() BCE (before)
    211   /// CHECK-DAG: BoundsCheck
    212   //
    213   /// CHECK-START: int Main.justRightDown2() BCE (after)
    214   /// CHECK-NOT: BoundsCheck
    215   /// CHECK-NOT: Deoptimize
    216   private static int justRightDown2() {
    217     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    218     int result = 0;
    219     for (int i = Integer.MIN_VALUE + 10; i > Integer.MIN_VALUE; i--) {
    220       result += x[Integer.MAX_VALUE + i];
    221     }
    222     return result;
    223   }
    224 
    225   /// CHECK-START: int Main.justRightDown3() BCE (before)
    226   /// CHECK-DAG: BoundsCheck
    227   //
    228   /// CHECK-START: int Main.justRightDown3() BCE (after)
    229   /// CHECK-NOT: BoundsCheck
    230   /// CHECK-NOT: Deoptimize
    231   private static int justRightDown3() {
    232     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    233     int result = 0;
    234     for (int i = Integer.MIN_VALUE + 10, k = 0; i >= Integer.MIN_VALUE + 1; i--) {
    235       result += x[k++];
    236     }
    237     return result;
    238   }
    239 
    240   /// CHECK-START: int Main.justOOBDown() BCE (before)
    241   /// CHECK-DAG: BoundsCheck
    242   //
    243   /// CHECK-START: int Main.justOOBDown() BCE (after)
    244   /// CHECK-DAG: BoundsCheck
    245   //
    246   /// CHECK-START: int Main.justOOBDown() BCE (after)
    247   /// CHECK-NOT: Deoptimize
    248   private static int justOOBDown() {
    249     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    250     int result = 0;
    251     // Infinite loop!
    252     for (int i = Integer.MIN_VALUE + 9, k = 0; i >= Integer.MIN_VALUE; i--) {
    253       result += x[k++];
    254     }
    255     return result;
    256   }
    257 
    258   /// CHECK-START: void Main.lowerOOB(int[]) BCE (before)
    259   /// CHECK-DAG: BoundsCheck
    260   //
    261   /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
    262   /// CHECK-DAG: BoundsCheck
    263   //
    264   /// CHECK-START: void Main.lowerOOB(int[]) BCE (after)
    265   /// CHECK-NOT: Deoptimize
    266   private static void lowerOOB(int[] x) {
    267     // OOB!
    268     for (int i = -1; i < x.length; i++) {
    269       sResult += x[i];
    270     }
    271   }
    272 
    273   /// CHECK-START: void Main.upperOOB(int[]) BCE (before)
    274   /// CHECK-DAG: BoundsCheck
    275   //
    276   /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
    277   /// CHECK-DAG: BoundsCheck
    278   //
    279   /// CHECK-START: void Main.upperOOB(int[]) BCE (after)
    280   /// CHECK-NOT: Deoptimize
    281   private static void upperOOB(int[] x) {
    282     // OOB!
    283     for (int i = 0; i <= x.length; i++) {
    284       sResult += x[i];
    285     }
    286   }
    287 
    288   /// CHECK-START: void Main.doWhileUpOOB() BCE (before)
    289   /// CHECK-DAG: BoundsCheck
    290   //
    291   /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
    292   /// CHECK-DAG: BoundsCheck
    293   //
    294   /// CHECK-START: void Main.doWhileUpOOB() BCE (after)
    295   /// CHECK-NOT: Deoptimize
    296   private static void doWhileUpOOB() {
    297     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    298     int i = 0;
    299     // OOB!
    300     do {
    301       sResult += x[i++];
    302     } while (i <= x.length);
    303   }
    304 
    305   /// CHECK-START: void Main.doWhileDownOOB() BCE (before)
    306   /// CHECK-DAG: BoundsCheck
    307   //
    308   /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
    309   /// CHECK-DAG: BoundsCheck
    310   //
    311   /// CHECK-START: void Main.doWhileDownOOB() BCE (after)
    312   /// CHECK-NOT: Deoptimize
    313   private static void doWhileDownOOB() {
    314     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    315     int i = x.length - 1;
    316     // OOB!
    317     do {
    318       sResult += x[i--];
    319     } while (-1 <= i);
    320   }
    321 
    322   /// CHECK-START: void Main.justRightTriangular1() BCE (before)
    323   /// CHECK-DAG: BoundsCheck
    324   //
    325   /// CHECK-START: void Main.justRightTriangular1() BCE (after)
    326   /// CHECK-NOT: BoundsCheck
    327   /// CHECK-NOT: Deoptimize
    328   private static void justRightTriangular1() {
    329     int[] a = { 1 } ;
    330     for (int i = Integer.MIN_VALUE + 5; i <= Integer.MIN_VALUE + 10; i++) {
    331       for (int j = Integer.MIN_VALUE + 4; j < i - 5; j++) {
    332         sResult += a[j - (Integer.MIN_VALUE + 4)];
    333       }
    334     }
    335   }
    336 
    337   /// CHECK-START: void Main.justRightTriangular2() BCE (before)
    338   /// CHECK-DAG: BoundsCheck
    339   //
    340   /// CHECK-START: void Main.justRightTriangular2() BCE (after)
    341   /// CHECK-NOT: BoundsCheck
    342   /// CHECK-NOT: Deoptimize
    343   private static void justRightTriangular2() {
    344     int[] a = { 1 } ;
    345     for (int i = Integer.MIN_VALUE + 5; i <= 10; i++) {
    346       for (int j = 4; j < i - 5; j++) {
    347         sResult += a[j - 4];
    348       }
    349     }
    350   }
    351 
    352   /// CHECK-START: void Main.justOOBTriangular() BCE (before)
    353   /// CHECK-DAG: BoundsCheck
    354   //
    355   /// CHECK-START: void Main.justOOBTriangular() BCE (after)
    356   /// CHECK-DAG: Deoptimize
    357   //
    358   /// CHECK-START: void Main.justOOBTriangular() BCE (after)
    359   /// CHECK-NOT: BoundsCheck
    360   private static void justOOBTriangular() {
    361     int[] a = { 1 } ;
    362     for (int i = Integer.MIN_VALUE + 4; i <= 10; i++) {
    363       for (int j = 4; j < i - 5; j++) {
    364         sResult += a[j - 4];
    365       }
    366     }
    367   }
    368 
    369   /// CHECK-START: void Main.hiddenOOB1(int) BCE (before)
    370   /// CHECK-DAG: BoundsCheck
    371   //
    372   /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
    373   /// CHECK-DAG: Deoptimize
    374   //
    375   /// CHECK-START: void Main.hiddenOOB1(int) BCE (after)
    376   /// CHECK-NOT: BoundsCheck
    377   private static void hiddenOOB1(int lo) {
    378     int[] a = { 1 } ;
    379     for (int i = lo; i <= 10; i++) {
    380       // Dangerous loop where careless static range analysis would yield strict upper bound
    381       // on index j of 5. When, for instance, lo and thus i = -2147483648, the upper bound
    382       // becomes really positive due to arithmetic wrap-around, causing OOB.
    383       for (int j = 4; j < i - 5; j++) {
    384         sResult += a[j - 4];
    385       }
    386     }
    387   }
    388 
    389   /// CHECK-START: void Main.hiddenOOB2(int) BCE (before)
    390   /// CHECK-DAG: BoundsCheck
    391   //
    392   /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
    393   /// CHECK-DAG: Deoptimize
    394   //
    395   /// CHECK-START: void Main.hiddenOOB2(int) BCE (after)
    396   /// CHECK-NOT: BoundsCheck
    397   private static void hiddenOOB2(int hi) {
    398     int[] a = { 1 } ;
    399     for (int i = 0; i < hi; i++) {
    400       // Dangerous loop where careless static range analysis would yield strict lower bound
    401       // on index j of 5. When, for instance, hi and thus i = 2147483647, the upper bound
    402       // becomes really negative due to arithmetic wrap-around, causing OOB.
    403       for (int j = 6; j > i + 5; j--) {
    404         sResult += a[j - 6];
    405       }
    406     }
    407   }
    408 
    409   /// CHECK-START: void Main.hiddenOOB3(int) BCE (before)
    410   /// CHECK-DAG: BoundsCheck
    411   //
    412   /// CHECK-START: void Main.hiddenOOB3(int) BCE (after)
    413   /// CHECK-DAG: Deoptimize
    414   //
    415   /// CHECK-START: void Main.hiddenOOB3(int) BCE (after)
    416   /// CHECK-NOT: BoundsCheck
    417   private static void hiddenOOB3(int hi) {
    418     int[] a = { 11 } ;
    419     for (int i = -1; i <= hi; i++) {
    420       // Dangerous loop where careless static range analysis would yield strict lower bound
    421       // on index j of 0. For large i, the initial value of j becomes really negative due
    422       // to arithmetic wrap-around, causing OOB.
    423       for (int j = i + 1; j < 1; j++) {
    424         sResult += a[j];
    425       }
    426     }
    427   }
    428 
    429   /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (before)
    430   /// CHECK-DAG: BoundsCheck
    431   //
    432   /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
    433   /// CHECK-DAG: BoundsCheck
    434   //
    435   /// CHECK-START: void Main.hiddenInfiniteOOB() BCE (after)
    436   /// CHECK-NOT: Deoptimize
    437   private static void hiddenInfiniteOOB() {
    438     int[] a = { 11 } ;
    439     for (int i = -1; i <= 0; i++) {
    440       // Dangerous loop where careless static range analysis would yield a safe upper bound
    441       // of -3. In reality, due to arithmetic wrap-around (when i = -1, j <= 2147483647;
    442       // whereas when i = 0, j <= -3), this is an infinite loop that goes OOB.
    443       for (int j = -3; j <= 2147483646 * i - 3; j++) {
    444         sResult += a[j + 3];
    445       }
    446     }
    447   }
    448 
    449   /// CHECK-START: void Main.hiddenFiniteOOB() BCE (before)
    450   /// CHECK-DAG: BoundsCheck
    451   //
    452   /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
    453   /// CHECK-DAG: Deoptimize
    454   //
    455   /// CHECK-START: void Main.hiddenFiniteOOB() BCE (after)
    456   /// CHECK-NOT: BoundsCheck
    457   private static void hiddenFiniteOOB() {
    458     int[] a = { 111 } ;
    459     for (int i = -1; i <= 0; i++) {
    460       // Dangerous loop similar as above where the loop is now finite, but the
    461       // loop still goes out of bounds for i = -1 due to the large upper bound.
    462       for (int j = -4; j < 2147483646 * i - 3; j++) {
    463         sResult += a[j + 4];
    464       }
    465     }
    466   }
    467 
    468   /// CHECK-START: void Main.inductionOOB(int[]) BCE (before)
    469   /// CHECK-DAG: BoundsCheck
    470   //
    471   /// CHECK-START: void Main.inductionOOB(int[]) BCE (after)
    472   /// CHECK-DAG: BoundsCheck
    473   //
    474   /// CHECK-START: void Main.inductionOOB(int[]) BCE (after)
    475   /// CHECK-NOT: Deoptimize
    476   private static void inductionOOB(int[] a) {
    477     // Careless range analysis would remove the bounds check.
    478     // However, the narrower induction b wraps around arithmetically
    479     // before it reaches the end of arrays longer than 127.
    480     byte b = 0;
    481     for (int i = 0; i < a.length; i++) {
    482       a[b++] = i;
    483     }
    484   }
    485 
    486   /// CHECK-START: void Main.controlOOB(int[]) BCE (before)
    487   /// CHECK-DAG: BoundsCheck
    488   //
    489   /// CHECK-START: void Main.controlOOB(int[]) BCE (after)
    490   /// CHECK-DAG: BoundsCheck
    491   //
    492   /// CHECK-START: void Main.controlOOB(int[]) BCE (after)
    493   /// CHECK-NOT: Deoptimize
    494   private static void controlOOB(int[] a) {
    495     // As above, but now the loop control also wraps around.
    496     for (byte i = 0; i < a.length; i++) {
    497       a[i] = -i;
    498     }
    499   }
    500 
    501   /// CHECK-START: void Main.conversionOOB(int[]) BCE (before)
    502   /// CHECK-DAG: BoundsCheck
    503   //
    504   /// CHECK-START: void Main.conversionOOB(int[]) BCE (after)
    505   /// CHECK-DAG: BoundsCheck
    506   //
    507   /// CHECK-START: void Main.conversionOOB(int[]) BCE (after)
    508   /// CHECK-NOT: Deoptimize
    509   private static void conversionOOB(int[] a) {
    510     // As above, but with wrap around caused by an explicit conversion.
    511     for (int i = 0; i < a.length; ) {
    512       a[i] = i;
    513       i = (byte) (i + 1);
    514     }
    515   }
    516 
    517   /// CHECK-START: int Main.doNotHoist(int[]) BCE (before)
    518   /// CHECK-DAG: BoundsCheck
    519   //
    520   /// CHECK-START: int Main.doNotHoist(int[]) BCE (after)
    521   /// CHECK-NOT: BoundsCheck
    522   public static int doNotHoist(int[] a) {
    523      int n = a.length;
    524      int x = 0;
    525      // BCE applies, but hoisting would crash the loop.
    526      for (int i = -10000; i < 10000; i++) {
    527        for (int j = 0; j <= 1; j++) {
    528          if (0 <= i && i < n)
    529            x += a[i];
    530        }
    531     }
    532     return x;
    533   }
    534 
    535 
    536   /// CHECK-START: int[] Main.add() BCE (before)
    537   /// CHECK-DAG: BoundsCheck
    538   //
    539   /// CHECK-START: int[] Main.add() BCE (after)
    540   /// CHECK-NOT: BoundsCheck
    541   /// CHECK-NOT: Deoptimize
    542   private static int[] add() {
    543     int[] a = new int[10];
    544     for (int i = 0; i <= 3; i++) {
    545       for (int j = 0; j <= 6; j++) {
    546         a[i + j] += 1;
    547       }
    548     }
    549     return a;
    550   }
    551 
    552   /// CHECK-START: int[] Main.multiply1() BCE (before)
    553   /// CHECK-DAG: BoundsCheck
    554   //
    555   /// CHECK-START: int[] Main.multiply1() BCE (after)
    556   /// CHECK-NOT: BoundsCheck
    557   /// CHECK-NOT: Deoptimize
    558   private static int[] multiply1() {
    559     int[] a = new int[10];
    560     try {
    561       for (int i = 0; i <= 3; i++) {
    562         for (int j = 0; j <= 3; j++) {
    563           // Range [0,9]: safe.
    564           a[i * j] += 1;
    565         }
    566       }
    567     } catch (Exception e) {
    568       a[0] += 1000;
    569     }
    570     return a;
    571   }
    572 
    573   /// CHECK-START: int[] Main.multiply2() BCE (before)
    574   /// CHECK-DAG: BoundsCheck
    575   //
    576   /// CHECK-START: int[] Main.multiply2() BCE (after)
    577   /// CHECK-DAG: BoundsCheck
    578   //
    579   /// CHECK-START: int[] Main.multiply2() BCE (after)
    580   /// CHECK-NOT: Deoptimize
    581   static int[] multiply2() {
    582     int[] a = new int[10];
    583     try {
    584       for (int i = -3; i <= 3; i++) {
    585         for (int j = -3; j <= 3; j++) {
    586           // Range [-9,9]: unsafe.
    587           a[i * j] += 1;
    588         }
    589       }
    590     } catch (Exception e) {
    591       a[0] += 1000;
    592     }
    593     return a;
    594   }
    595 
    596   /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (before)
    597   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    598   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    599   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    600   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    601   //
    602   /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
    603   /// CHECK-DAG: ArrayGet    loop:{{B\d+}}
    604   /// CHECK-DAG: Deoptimize  loop:none
    605   //
    606   /// CHECK-START: int Main.linearDynamicBCE1(int[], int, int) BCE (after)
    607   /// CHECK-NOT: NullCheck   loop:{{B\d+}}
    608   /// CHECK-NOT: ArrayLength loop:{{B\d+}}
    609   /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
    610   private static int linearDynamicBCE1(int[] x, int lo, int hi) {
    611     int result = 0;
    612     for (int i = lo; i < hi; i++) {
    613       sResult += x[i];
    614     }
    615     return result;
    616   }
    617 
    618   /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (before)
    619   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    620   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    621   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    622   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    623   //
    624   /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
    625   /// CHECK-DAG: ArrayGet    loop:{{B\d+}}
    626   /// CHECK-DAG: Deoptimize  loop:none
    627   //
    628   /// CHECK-START: int Main.linearDynamicBCE2(int[], int, int, int) BCE (after)
    629   /// CHECK-NOT: NullCheck   loop:{{B\d+}}
    630   /// CHECK-NOT: ArrayLength loop:{{B\d+}}
    631   /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
    632   private static int linearDynamicBCE2(int[] x, int lo, int hi, int offset) {
    633     int result = 0;
    634     for (int i = lo; i < hi; i++) {
    635       sResult += x[offset + i];
    636     }
    637     return result;
    638   }
    639 
    640   /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (before)
    641   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    642   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    643   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    644   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    645   //
    646   /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
    647   /// CHECK-DAG: ArrayGet    loop:{{B\d+}}
    648   /// CHECK-DAG: Deoptimize  loop:none
    649   //
    650   /// CHECK-START: int Main.wrapAroundDynamicBCE(int[]) BCE (after)
    651   /// CHECK-NOT: NullCheck   loop:{{B\d+}}
    652   /// CHECK-NOT: ArrayLength loop:{{B\d+}}
    653   /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
    654   private static int wrapAroundDynamicBCE(int[] x) {
    655     int w = 9;
    656     int result = 0;
    657     for (int i = 0; i < 10; i++) {
    658       result += x[w];
    659       w = i;
    660     }
    661     return result;
    662   }
    663 
    664   /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (before)
    665   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    666   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    667   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    668   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    669   //
    670   /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
    671   /// CHECK-DAG: ArrayGet    loop:{{B\d+}}
    672   /// CHECK-DAG: Deoptimize  loop:none
    673   //
    674   /// CHECK-START: int Main.periodicDynamicBCE(int[]) BCE (after)
    675   /// CHECK-NOT: NullCheck   loop:{{B\d+}}
    676   /// CHECK-NOT: ArrayLength loop:{{B\d+}}
    677   /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
    678   private static int periodicDynamicBCE(int[] x) {
    679     int k = 0;
    680     int result = 0;
    681     for (int i = 0; i < 10; i++) {
    682       result += x[k];
    683       k = 1 - k;
    684     }
    685     return result;
    686   }
    687 
    688   /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
    689   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    690   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    691   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    692   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    693   //
    694   /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
    695   /// CHECK-DAG: ArrayGet    loop:{{B\d+}}
    696   /// CHECK-DAG: Deoptimize  loop:none
    697   //
    698   /// CHECK-START: int Main.dynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
    699   /// CHECK-NOT: NullCheck   loop:{{B\d+}}
    700   /// CHECK-NOT: ArrayLength loop:{{B\d+}}
    701   /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
    702   static int dynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
    703     // This loop could be infinite for hi = max int. Since i is also used
    704     // as subscript, however, dynamic bce can proceed.
    705     int result = 0;
    706     for (int i = lo; i <= hi; i++) {
    707       result += x[i];
    708     }
    709     return result;
    710   }
    711 
    712   /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (before)
    713   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    714   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    715   //
    716   /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
    717   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    718   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    719   //
    720   /// CHECK-START: int Main.noDynamicBCEPossiblyInfiniteLoop(int[], int, int) BCE (after)
    721   /// CHECK-NOT: Deoptimize
    722   static int noDynamicBCEPossiblyInfiniteLoop(int[] x, int lo, int hi) {
    723     // As above, but now the index is not used as subscript,
    724     // and dynamic bce is not applied.
    725     int result = 0;
    726     for (int k = 0, i = lo; i <= hi; i++) {
    727       result += x[k++];
    728     }
    729     return result;
    730   }
    731 
    732   /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (before)
    733   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    734   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    735   //
    736   /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
    737   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    738   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    739   //
    740   /// CHECK-START: int Main.noDynamicBCEMixedInductionTypes(int[], long, long) BCE (after)
    741   /// CHECK-NOT: Deoptimize
    742   static int noDynamicBCEMixedInductionTypes(int[] x, long lo, long hi) {
    743     int result = 0;
    744     // Mix of int and long induction.
    745     int k = 0;
    746     for (long i = lo; i < hi; i++) {
    747       result += x[k++];
    748     }
    749     return result;
    750   }
    751 
    752   /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (before)
    753   /// CHECK-DAG: BoundsCheck loop:<<InnerLoop:B\d+>>
    754   /// CHECK-DAG: ArrayGet    loop:<<InnerLoop>>
    755   /// CHECK-DAG: If          loop:<<InnerLoop>>
    756   /// CHECK-DAG: If          loop:<<OuterLoop:B\d+>>
    757   /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
    758   //
    759   /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
    760   /// CHECK-DAG: ArrayGet   loop:<<InnerLoop:B\d+>>
    761   /// CHECK-DAG: Deoptimize loop:<<OuterLoop:B\d+>>
    762   /// CHECK-EVAL: "<<InnerLoop>>" != "<<OuterLoop>>"
    763   //
    764   /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
    765   /// CHECK-NOT: BoundsCheck
    766   //
    767   //  No additional top tests were introduced.
    768   /// CHECK-START: int Main.dynamicBCEConstantRange(int[]) BCE (after)
    769   /// CHECK-DAG: If
    770   /// CHECK-DAG: If
    771   /// CHECK-NOT: If
    772   static int dynamicBCEConstantRange(int[] x) {
    773     int result = 0;
    774     for (int i = 2; i <= 6; i++) {
    775       // Range analysis sees that innermost loop is finite and always taken.
    776       for (int j = i - 2; j <= i + 2; j++) {
    777         result += x[j];
    778       }
    779     }
    780     return result;
    781   }
    782 
    783   /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (before)
    784   /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop:B\d+>>
    785   /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
    786   /// CHECK-DAG: {{l\d+}} ArrayGet loop:<<Loop>>
    787   //
    788   /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
    789   //  Order matters:
    790   /// CHECK:              Deoptimize loop:<<Loop:B\d+>>
    791   /// CHECK-NOT:          Goto       loop:<<Loop>>
    792   /// CHECK-DAG: {{l\d+}} ArrayGet   loop:<<Loop>>
    793   /// CHECK-DAG: {{l\d+}} ArrayGet   loop:<<Loop>>
    794   /// CHECK-DAG: {{l\d+}} ArrayGet   loop:<<Loop>>
    795   /// CHECK:              Goto       loop:<<Loop>>
    796   //
    797   /// CHECK-START: int Main.dynamicBCEAndConstantIndices(int[], int[][], int, int) BCE (after)
    798   /// CHECK-DAG: Deoptimize loop:none
    799   static int dynamicBCEAndConstantIndices(int[] x, int[][] a, int lo, int hi) {
    800     // Deliberately test array length on a before the loop so that only bounds checks
    801     // on constant subscripts remain, making them a viable candidate for hoisting.
    802     if (a.length == 0) {
    803       return -1;
    804     }
    805     // Loop that allows BCE on x[i].
    806     int result = 0;
    807     for (int i = lo; i < hi; i++) {
    808       result += x[i];
    809       if ((i % 10) != 0) {
    810         // None of the subscripts inside a conditional are removed by dynamic bce,
    811         // making them a candidate for deoptimization based on constant indices.
    812         // Compiler should ensure the array loads are not subsequently hoisted
    813         // "above" the deoptimization "barrier" on the bounds.
    814         a[1][i] = 1;
    815         a[2][i] = 2;
    816         a[99][i] = 3;
    817       }
    818     }
    819     return result;
    820   }
    821 
    822   /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (before)
    823   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    824   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    825   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    826   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    827   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    828   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    829   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    830   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    831   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    832   //  For brevity, just test occurrence of at least one of each in the loop:
    833   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    834   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    835   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    836   //
    837   /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
    838   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    839   /// CHECK-NOT: ArrayGet    loop:<<Loop>>
    840   //
    841   /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
    842   /// CHECK-NOT: NullCheck   loop:{{B\d+}}
    843   /// CHECK-NOT: ArrayLength loop:{{B\d+}}
    844   /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
    845   //
    846   /// CHECK-START: int Main.dynamicBCEAndConstantIndicesAllPrimTypes(int[], boolean[], byte[], char[], short[], int[], long[], float[], double[], int, int) BCE (after)
    847   /// CHECK-DAG: Deoptimize  loop:none
    848   static int dynamicBCEAndConstantIndicesAllPrimTypes(int[] q,
    849                                                       boolean[] r,
    850                                                       byte[] s,
    851                                                       char[] t,
    852                                                       short[] u,
    853                                                       int[] v,
    854                                                       long[] w,
    855                                                       float[] x,
    856                                                       double[] y, int lo, int hi) {
    857     int result = 0;
    858     for (int i = lo; i < hi; i++) {
    859       // All constant index array references can be hoisted out of the loop during BCE on q[i].
    860       result += q[i] + (r[0] ? 1 : 0) + (int) s[0] + (int) t[0] + (int) u[0] + (int) v[0] +
    861                                         (int) w[0] + (int) x[0] + (int) y[0];
    862     }
    863     return result;
    864   }
    865 
    866   /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (before)
    867   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    868   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    869   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    870   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    871   /// CHECK-DAG: ArrayGet    loop:<<Loop>>
    872   /// CHECK-DAG: NullCheck   loop:<<Loop>>
    873   /// CHECK-DAG: ArrayLength loop:<<Loop>>
    874   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    875   //
    876   /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
    877   /// CHECK-DAG: ArrayGet    loop:<<Loop:B\d+>>
    878   /// CHECK-DAG: Deoptimize  loop:none
    879   //
    880   /// CHECK-START: int Main.dynamicBCEAndConstantIndexRefType(int[], java.lang.Integer[], int, int) BCE (after)
    881   /// CHECK-NOT: ArrayLength loop:{{B\d+}}
    882   /// CHECK-NOT: BoundsCheck loop:{{B\d+}}
    883   static int dynamicBCEAndConstantIndexRefType(int[] q, Integer[] z, int lo, int hi) {
    884     int result = 0;
    885     for (int i = lo; i < hi; i++) {
    886       // Similar to above, but now implicit call to intValue() may prevent hoisting
    887       // z[0] itself during BCE on q[i]. Therefore, we just check BCE on q[i].
    888       result += q[i] + z[0];
    889     }
    890     return result;
    891   }
    892 
    893   /// CHECK-START: int Main.shortIndex(int[]) BCE (before)
    894   /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>>
    895   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    896   //
    897   /// CHECK-START: int Main.shortIndex(int[]) BCE (after)
    898   /// CHECK-DAG: BoundsCheck loop:<<Loop:B\d+>>
    899   /// CHECK-DAG: BoundsCheck loop:<<Loop>>
    900   //
    901   /// CHECK-START: int Main.shortIndex(int[]) BCE (after)
    902   /// CHECK-NOT: Deoptimize
    903   static int shortIndex(int[] a) {
    904     int r = 0;
    905     // Make sure short/int conversions compiles well (b/32193474).
    906     for (short i = 1; i < 10; i++) {
    907       int ki = i - 1;
    908       r += a[ki] + a[i];
    909     }
    910     return r;
    911   }
    912 
    913   //
    914   // Verifier.
    915   //
    916 
    917   public static void main(String[] args) {
    918     // Set to run expensive tests for correctness too.
    919     boolean HEAVY = false;
    920 
    921     int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    922 
    923     int[] a200 = new int[200];
    924 
    925     // Sorting.
    926     int[] sort = { 5, 4, 1, 9, 10, 2, 7, 6, 3, 8 };
    927     bubble(sort);
    928     for (int i = 0; i < 10; i++) {
    929       expectEquals(sort[i], x[i]);
    930     }
    931 
    932     // Periodic adds (1, 3), one at the time.
    933     expectEquals(0, periodicIdiom(-1));
    934     for (int tc = 0; tc < 32; tc++) {
    935       int expected = (tc >> 1) << 2;
    936       if ((tc & 1) != 0) {
    937         expected += 1;
    938       }
    939       expectEquals(expected, periodicIdiom(tc));
    940     }
    941 
    942     // Periodic adds (1, 3), one at the time.
    943     expectEquals(0, periodicSequence2(-1));
    944     for (int tc = 0; tc < 32; tc++) {
    945       int expected = (tc >> 1) << 2;
    946       if ((tc & 1) != 0) {
    947         expected += 1;
    948       }
    949       expectEquals(expected, periodicSequence2(tc));
    950     }
    951 
    952     // Periodic adds (1, 3, 5, 7), all at once.
    953     expectEquals(0, periodicSequence4(-1));
    954     for (int tc = 0; tc < 32; tc++) {
    955       expectEquals(tc * 16, periodicSequence4(tc));
    956     }
    957 
    958     // Periodic adds (1, 3), one at the time.
    959     expectEquals(0, periodicXorSequence(-1));
    960     for (int tc = 0; tc < 32; tc++) {
    961       int expected = (tc >> 1) << 2;
    962       if ((tc & 1) != 0) {
    963         expected += 1;
    964       }
    965       expectEquals(expected, periodicXorSequence(tc));
    966     }
    967 
    968     // Large bounds.
    969     expectEquals(55, justRightUp1());
    970     expectEquals(55, justRightUp2());
    971     expectEquals(55, justRightUp3());
    972     expectEquals(55, justRightDown1());
    973     expectEquals(55, justRightDown2());
    974     expectEquals(55, justRightDown3());
    975 
    976     // Large bounds OOB.
    977     sResult = 0;
    978     try {
    979       justOOBUp();
    980     } catch (ArrayIndexOutOfBoundsException e) {
    981       sResult = 1;
    982     }
    983     expectEquals(1, sResult);
    984     sResult = 0;
    985     try {
    986       justOOBDown();
    987     } catch (ArrayIndexOutOfBoundsException e) {
    988       sResult = 1;
    989     }
    990     expectEquals(1, sResult);
    991 
    992     // Lower bound goes OOB.
    993     sResult = 0;
    994     try {
    995       lowerOOB(x);
    996     } catch (ArrayIndexOutOfBoundsException e) {
    997       sResult += 1000;
    998     }
    999     expectEquals(1000, sResult);
   1000 
   1001     // Upper bound goes OOB.
   1002     sResult = 0;
   1003     try {
   1004       upperOOB(x);
   1005     } catch (ArrayIndexOutOfBoundsException e) {
   1006       sResult += 1000;
   1007     }
   1008     expectEquals(1055, sResult);
   1009 
   1010     // Do while up goes OOB.
   1011     sResult = 0;
   1012     try {
   1013       doWhileUpOOB();
   1014     } catch (ArrayIndexOutOfBoundsException e) {
   1015       sResult += 1000;
   1016     }
   1017     expectEquals(1055, sResult);
   1018 
   1019     // Do while down goes OOB.
   1020     sResult = 0;
   1021     try {
   1022       doWhileDownOOB();
   1023     } catch (ArrayIndexOutOfBoundsException e) {
   1024       sResult += 1000;
   1025     }
   1026     expectEquals(1055, sResult);
   1027 
   1028     // Triangular.
   1029     sResult = 0;
   1030     justRightTriangular1();
   1031     expectEquals(1, sResult);
   1032     if (HEAVY) {
   1033       sResult = 0;
   1034       justRightTriangular2();
   1035       expectEquals(1, sResult);
   1036     }
   1037     sResult = 0;
   1038     try {
   1039       justOOBTriangular();
   1040     } catch (ArrayIndexOutOfBoundsException e) {
   1041       sResult += 1000;
   1042     }
   1043     expectEquals(1001, sResult);
   1044 
   1045     // Hidden OOB.
   1046     sResult = 0;
   1047     try {
   1048       hiddenOOB1(10);  // no OOB
   1049     } catch (ArrayIndexOutOfBoundsException e) {
   1050       sResult += 1000;
   1051     }
   1052     expectEquals(1, sResult);
   1053     sResult = 0;
   1054     try {
   1055       hiddenOOB1(-2147483648);  // OOB
   1056     } catch (ArrayIndexOutOfBoundsException e) {
   1057       sResult += 1000;
   1058     }
   1059     expectEquals(1001, sResult);
   1060     sResult = 0;
   1061     try {
   1062       hiddenOOB2(1);  // no OOB
   1063     } catch (ArrayIndexOutOfBoundsException e) {
   1064       sResult += 1000;
   1065     }
   1066     expectEquals(1, sResult);
   1067     sResult = 0;
   1068     try {
   1069       hiddenOOB3(-1);  // no OOB
   1070     } catch (ArrayIndexOutOfBoundsException e) {
   1071       sResult += 1000;
   1072     }
   1073     expectEquals(11, sResult);
   1074 
   1075     // Expensive hidden OOB test.
   1076     if (HEAVY) {
   1077       sResult = 0;
   1078       try {
   1079         hiddenOOB2(2147483647);  // OOB
   1080       } catch (ArrayIndexOutOfBoundsException e) {
   1081         sResult += 1000;
   1082       }
   1083       expectEquals(1002, sResult);
   1084       sResult = 0;
   1085       try {
   1086         hiddenOOB3(2147483647);  // OOB
   1087       } catch (ArrayIndexOutOfBoundsException e) {
   1088         sResult += 1000;
   1089       }
   1090       expectEquals(1011, sResult);
   1091     }
   1092 
   1093     // More hidden OOB.
   1094     sResult = 0;
   1095     try {
   1096       hiddenInfiniteOOB();
   1097     } catch (ArrayIndexOutOfBoundsException e) {
   1098       sResult += 1000;
   1099     }
   1100     expectEquals(1011, sResult);
   1101     sResult = 0;
   1102     try {
   1103       hiddenFiniteOOB();
   1104     } catch (ArrayIndexOutOfBoundsException e) {
   1105       sResult += 1000;
   1106     }
   1107     expectEquals(1111, sResult);
   1108     sResult = 0;
   1109     try {
   1110       inductionOOB(a200);
   1111     } catch (ArrayIndexOutOfBoundsException e) {
   1112       sResult += 1000;
   1113     }
   1114     expectEquals(1000, sResult);
   1115     for (int i = 0; i < 200; i++) {
   1116       expectEquals(i < 128 ? i : 0, a200[i]);
   1117     }
   1118     sResult = 0;
   1119     try {
   1120       controlOOB(a200);
   1121     } catch (ArrayIndexOutOfBoundsException e) {
   1122       sResult += 1000;
   1123     }
   1124     expectEquals(1000, sResult);
   1125     for (int i = 0; i < 200; i++) {
   1126       expectEquals(i < 128 ? -i : 0, a200[i]);
   1127     }
   1128     sResult = 0;
   1129     try {
   1130       conversionOOB(a200);
   1131     } catch (ArrayIndexOutOfBoundsException e) {
   1132       sResult += 1000;
   1133     }
   1134     expectEquals(1000, sResult);
   1135     for (int i = 0; i < 200; i++) {
   1136       expectEquals(i < 128 ? i : 0, a200[i]);
   1137     }
   1138 
   1139     // No hoisting after BCE.
   1140     expectEquals(110, doNotHoist(x));
   1141 
   1142     // Addition.
   1143     {
   1144       int[] e1 ={ 1, 2, 3, 4, 4, 4, 4, 3, 2, 1 };
   1145       int[] a1 = add();
   1146       for (int i = 0; i < 10; i++) {
   1147         expectEquals(a1[i], e1[i]);
   1148       }
   1149     }
   1150 
   1151     // Multiplication.
   1152     {
   1153       int[] e1 = { 7, 1, 2, 2, 1, 0, 2, 0, 0, 1 };
   1154       int[] a1 = multiply1();
   1155       for (int i = 0; i < 10; i++) {
   1156         expectEquals(a1[i], e1[i]);
   1157       }
   1158       int[] e2 = { 1001, 0, 0, 1, 0, 0, 1, 0, 0, 1 };
   1159       int[] a2 = multiply2();
   1160       for (int i = 0; i < 10; i++) {
   1161         expectEquals(a2[i], e2[i]);
   1162       }
   1163     }
   1164 
   1165     // Dynamic BCE.
   1166     sResult = 0;
   1167     try {
   1168       linearDynamicBCE1(x, -1, x.length);
   1169     } catch (ArrayIndexOutOfBoundsException e) {
   1170       sResult += 1000;
   1171     }
   1172     expectEquals(1000, sResult);
   1173     sResult = 0;
   1174     linearDynamicBCE1(x, 0, x.length);
   1175     expectEquals(55, sResult);
   1176     sResult = 0;
   1177     try {
   1178       linearDynamicBCE1(x, 0, x.length + 1);
   1179     } catch (ArrayIndexOutOfBoundsException e) {
   1180       sResult += 1000;
   1181     }
   1182     expectEquals(1055, sResult);
   1183 
   1184     // Dynamic BCE with offset.
   1185     sResult = 0;
   1186     try {
   1187       linearDynamicBCE2(x, 0, x.length, -1);
   1188     } catch (ArrayIndexOutOfBoundsException e) {
   1189       sResult += 1000;
   1190     }
   1191     expectEquals(1000, sResult);
   1192     sResult = 0;
   1193     linearDynamicBCE2(x, 0, x.length, 0);
   1194     expectEquals(55, sResult);
   1195     sResult = 0;
   1196     try {
   1197       linearDynamicBCE2(x, 0, x.length, 1);
   1198     } catch (ArrayIndexOutOfBoundsException e) {
   1199       sResult += 1000;
   1200     }
   1201     expectEquals(1054, sResult);
   1202 
   1203     // Dynamic BCE candidates.
   1204     expectEquals(55, wrapAroundDynamicBCE(x));
   1205     expectEquals(15, periodicDynamicBCE(x));
   1206     expectEquals(55, dynamicBCEPossiblyInfiniteLoop(x, 0, 9));
   1207     expectEquals(55, noDynamicBCEPossiblyInfiniteLoop(x, 0, 9));
   1208     expectEquals(55, noDynamicBCEMixedInductionTypes(x, 0, 10));
   1209     expectEquals(125, dynamicBCEConstantRange(x));
   1210 
   1211     // Dynamic BCE combined with constant indices.
   1212     int[][] a;
   1213     a = new int[0][0];
   1214     expectEquals(-1, dynamicBCEAndConstantIndices(x, a, 0, 10));
   1215     a = new int[100][10];
   1216     expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
   1217     for (int i = 0; i < 10; i++) {
   1218       expectEquals((i % 10) != 0 ? 1 : 0, a[1][i]);
   1219       expectEquals((i % 10) != 0 ? 2 : 0, a[2][i]);
   1220       expectEquals((i % 10) != 0 ? 3 : 0, a[99][i]);
   1221     }
   1222     a = new int[3][10];
   1223     sResult = 0;
   1224     try {
   1225       expectEquals(55, dynamicBCEAndConstantIndices(x, a, 0, 10));
   1226     } catch (ArrayIndexOutOfBoundsException e) {
   1227       sResult = 1;
   1228     }
   1229     expectEquals(1, sResult);
   1230     expectEquals(a[1][1], 1);
   1231     expectEquals(a[2][1], 2);
   1232 
   1233     // Dynamic BCE combined with constant indices of all types.
   1234     boolean[] x1 = { true };
   1235     byte[] x2 = { 2 };
   1236     char[] x3 = { 3 };
   1237     short[] x4 = { 4 };
   1238     int[] x5 = { 5 };
   1239     long[] x6 = { 6 };
   1240     float[] x7 = { 7 };
   1241     double[] x8 = { 8 };
   1242     expectEquals(415,
   1243         dynamicBCEAndConstantIndicesAllPrimTypes(x, x1, x2, x3, x4, x5, x6, x7, x8, 0, 10));
   1244     Integer[] x9 = { 9 };
   1245     expectEquals(145, dynamicBCEAndConstantIndexRefType(x, x9, 0, 10));
   1246 
   1247     expectEquals(99, shortIndex(x));
   1248 
   1249     System.out.println("passed");
   1250   }
   1251 
   1252   private static void expectEquals(int expected, int result) {
   1253     if (expected != result) {
   1254       throw new Error("Expected: " + expected + ", found: " + result);
   1255     }
   1256   }
   1257 }
   1258