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   public static void assertIntEquals(int expected, int result) {
     20     if (expected != result) {
     21       throw new Error("Expected: " + expected + ", found: " + result);
     22     }
     23   }
     24 
     25   /**
     26    * Test that HArrayGet with a constant index is not split.
     27    */
     28 
     29   /// CHECK-START-ARM64: int Main.constantIndexGet(int[]) instruction_simplifier_arm64 (before)
     30   /// CHECK:             <<Array:l\d+>>         NullCheck
     31   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     32   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
     33 
     34   /// CHECK-START-ARM64: int Main.constantIndexGet(int[]) instruction_simplifier_arm64 (after)
     35   /// CHECK:             <<Array:l\d+>>         NullCheck
     36   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     37   /// CHECK-NOT:                                IntermediateAddress
     38   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
     39 
     40 
     41   /// CHECK-START-ARM: int Main.constantIndexGet(int[]) instruction_simplifier_arm (before)
     42   /// CHECK:             <<Array:l\d+>>         NullCheck
     43   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     44   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
     45 
     46   /// CHECK-START-ARM: int Main.constantIndexGet(int[]) instruction_simplifier_arm (after)
     47   /// CHECK:           <<Array:l\d+>>         NullCheck
     48   /// CHECK:           <<Index:i\d+>>         BoundsCheck
     49   /// CHECK-NOT:                              IntermediateAddress
     50   /// CHECK:                                  ArrayGet [<<Array>>,<<Index>>]
     51 
     52   public static int constantIndexGet(int array[]) {
     53     return array[1];
     54   }
     55 
     56   /**
     57    * Test that HArraySet with a constant index is not split.
     58    */
     59 
     60   /// CHECK-START-ARM64: void Main.constantIndexSet(int[]) instruction_simplifier_arm64 (before)
     61   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
     62   /// CHECK:             <<Array:l\d+>>         NullCheck
     63   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     64   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
     65 
     66   /// CHECK-START-ARM64: void Main.constantIndexSet(int[]) instruction_simplifier_arm64 (after)
     67   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
     68   /// CHECK:             <<Array:l\d+>>         NullCheck
     69   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     70   /// CHECK-NOT:                                IntermediateAddress
     71   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
     72 
     73 
     74   /// CHECK-START-ARM:   void Main.constantIndexSet(int[]) instruction_simplifier_arm (before)
     75   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
     76   /// CHECK:             <<Array:l\d+>>         NullCheck
     77   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     78   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
     79 
     80   /// CHECK-START-ARM:   void Main.constantIndexSet(int[]) instruction_simplifier_arm (after)
     81   /// CHECK:             <<Const2:i\d+>>        IntConstant 2
     82   /// CHECK:             <<Array:l\d+>>         NullCheck
     83   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     84   /// CHECK-NOT:                                IntermediateAddress
     85   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Const2>>]
     86 
     87   public static void constantIndexSet(int array[]) {
     88     array[1] = 2;
     89   }
     90 
     91   /**
     92    * Test basic splitting of HArrayGet.
     93    */
     94 
     95   /// CHECK-START-ARM64: int Main.get(int[], int) instruction_simplifier_arm64 (before)
     96   /// CHECK:             <<Array:l\d+>>         NullCheck
     97   /// CHECK:             <<Index:i\d+>>         BoundsCheck
     98   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
     99 
    100   /// CHECK-START-ARM64: int Main.get(int[], int) instruction_simplifier_arm64 (after)
    101   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
    102   /// CHECK:             <<Array:l\d+>>         NullCheck
    103   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    104   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    105   /// CHECK-NEXT:                               ArrayGet [<<Address>>,<<Index>>]
    106 
    107 
    108   /// CHECK-START-ARM:   int Main.get(int[], int) instruction_simplifier_arm (before)
    109   /// CHECK:             <<Array:l\d+>>         NullCheck
    110   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    111   /// CHECK:                                    ArrayGet [<<Array>>,<<Index>>]
    112 
    113   /// CHECK-START-ARM:   int Main.get(int[], int) instruction_simplifier_arm (after)
    114   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
    115   /// CHECK:             <<Array:l\d+>>         NullCheck
    116   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    117   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    118   /// CHECK-NEXT:                               ArrayGet [<<Address>>,<<Index>>]
    119 
    120   public static int get(int array[], int index) {
    121     return array[index];
    122   }
    123 
    124   /**
    125    * Test basic splitting of HArraySet.
    126    */
    127 
    128   /// CHECK-START-ARM64: void Main.set(int[], int, int) instruction_simplifier_arm64 (before)
    129   /// CHECK:                                    ParameterValue
    130   /// CHECK:                                    ParameterValue
    131   /// CHECK:             <<Arg:i\d+>>           ParameterValue
    132   /// CHECK:             <<Array:l\d+>>         NullCheck
    133   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    134   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Arg>>]
    135 
    136   /// CHECK-START-ARM64: void Main.set(int[], int, int) instruction_simplifier_arm64 (after)
    137   /// CHECK:                                    ParameterValue
    138   /// CHECK:                                    ParameterValue
    139   /// CHECK:             <<Arg:i\d+>>           ParameterValue
    140   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
    141   /// CHECK:             <<Array:l\d+>>         NullCheck
    142   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    143   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    144   /// CHECK-NEXT:                               ArraySet [<<Address>>,<<Index>>,<<Arg>>]
    145 
    146 
    147   /// CHECK-START-ARM:   void Main.set(int[], int, int) instruction_simplifier_arm (before)
    148   /// CHECK:                                    ParameterValue
    149   /// CHECK:                                    ParameterValue
    150   /// CHECK:             <<Arg:i\d+>>           ParameterValue
    151   /// CHECK:             <<Array:l\d+>>         NullCheck
    152   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    153   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Arg>>]
    154 
    155   /// CHECK-START-ARM:   void Main.set(int[], int, int) instruction_simplifier_arm (after)
    156   /// CHECK:                                    ParameterValue
    157   /// CHECK:                                    ParameterValue
    158   /// CHECK:             <<Arg:i\d+>>           ParameterValue
    159   /// CHECK:             <<DataOffset:i\d+>>    IntConstant
    160   /// CHECK:             <<Array:l\d+>>         NullCheck
    161   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    162   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    163   /// CHECK-NEXT:                               ArraySet [<<Address>>,<<Index>>,<<Arg>>]
    164 
    165   public static void set(int array[], int index, int value) {
    166     array[index] = value;
    167   }
    168 
    169   /**
    170    * Check that the intermediate address can be shared after GVN.
    171    */
    172 
    173   /// CHECK-START-ARM64: void Main.getSet(int[], int) instruction_simplifier_arm64 (before)
    174   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
    175   /// CHECK:             <<Array:l\d+>>         NullCheck
    176   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    177   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
    178   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    179   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
    180 
    181   /// CHECK-START-ARM64: void Main.getSet(int[], int) instruction_simplifier_arm64 (after)
    182   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    183   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    184   /// CHECK:             <<Array:l\d+>>         NullCheck
    185   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    186   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    187   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    188   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    189   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    190   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
    191 
    192   /// CHECK-START-ARM64: void Main.getSet(int[], int) GVN$after_arch (after)
    193   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    194   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    195   /// CHECK:             <<Array:l\d+>>         NullCheck
    196   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    197   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    198   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
    199   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    200   /// CHECK-NOT:                                IntermediateAddress
    201   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Add>>]
    202 
    203 
    204   /// CHECK-START-ARM:   void Main.getSet(int[], int) instruction_simplifier_arm (before)
    205   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
    206   /// CHECK:             <<Array:l\d+>>         NullCheck
    207   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    208   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
    209   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    210   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
    211 
    212   /// CHECK-START-ARM:   void Main.getSet(int[], int) instruction_simplifier_arm (after)
    213   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    214   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    215   /// CHECK:             <<Array:l\d+>>         NullCheck
    216   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    217   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    218   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    219   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    220   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    221   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
    222 
    223   /// CHECK-START-ARM:   void Main.getSet(int[], int) GVN$after_arch (after)
    224   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    225   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    226   /// CHECK:             <<Array:l\d+>>         NullCheck
    227   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    228   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    229   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
    230   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    231   /// CHECK-NOT:                                IntermediateAddress
    232   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Add>>]
    233   public static void getSet(int array[], int index) {
    234     array[index] = array[index] + 1;
    235   }
    236 
    237   /**
    238    * Check that the intermediate address computation is not reordered or merged
    239    * across IRs that can trigger GC.
    240    */
    241 
    242   /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) instruction_simplifier_arm64 (before)
    243   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
    244   /// CHECK:             <<Array:l\d+>>         NullCheck
    245   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    246   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
    247   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    248   /// CHECK:                                    NewArray
    249   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
    250 
    251   /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) instruction_simplifier_arm64 (after)
    252   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    253   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    254   /// CHECK:             <<Array:l\d+>>         NullCheck
    255   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    256   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    257   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    258   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    259   /// CHECK:                                    NewArray
    260   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    261   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
    262 
    263   /// CHECK-START-ARM64: int[] Main.accrossGC(int[], int) GVN$after_arch (after)
    264   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    265   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    266   /// CHECK:             <<Array:l\d+>>         NullCheck
    267   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    268   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    269   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    270   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    271   /// CHECK:                                    NewArray
    272   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    273   /// CHECK:                                    ArraySet [<<Address2>>,<<Index>>,<<Add>>]
    274 
    275 
    276   /// CHECK-START-ARM:   int[] Main.accrossGC(int[], int) instruction_simplifier_arm (before)
    277   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
    278   /// CHECK:             <<Array:l\d+>>         NullCheck
    279   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    280   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
    281   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    282   /// CHECK:                                    NewArray
    283   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Add>>]
    284 
    285   /// CHECK-START-ARM:   int[] Main.accrossGC(int[], int) instruction_simplifier_arm (after)
    286   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    287   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    288   /// CHECK:             <<Array:l\d+>>         NullCheck
    289   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    290   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    291   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    292   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    293   /// CHECK:                                    NewArray
    294   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    295   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Add>>]
    296 
    297   /// CHECK-START-ARM:   int[] Main.accrossGC(int[], int) GVN$after_arch (after)
    298   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    299   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant
    300   /// CHECK:             <<Array:l\d+>>         NullCheck
    301   /// CHECK:             <<Index:i\d+>>         BoundsCheck
    302   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    303   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    304   /// CHECK:             <<Add:i\d+>>           Add [<<ArrayGet>>,<<Const1>>]
    305   /// CHECK:                                    NewArray
    306   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    307   /// CHECK:                                    ArraySet [<<Address2>>,<<Index>>,<<Add>>]
    308 
    309   public static int[] accrossGC(int array[], int index) {
    310     int tmp = array[index] + 1;
    311     int[] new_array = new int[1];
    312     array[index] = tmp;
    313     return new_array;
    314   }
    315 
    316   /**
    317    * Test that the intermediate address is shared between array accesses after
    318    * the bounds check have been removed by BCE.
    319    */
    320   // For checker tests `instruction_simplifier_<arch> (after)` below, by the time we reach
    321   // the architecture-specific instruction simplifier, BCE has removed the bounds checks in
    322   // the loop.
    323 
    324   // Note that we do not care that the `DataOffset` is `12`. But if we do not
    325   // specify it and any other `IntConstant` appears before that instruction,
    326   // checker will match the previous `IntConstant`, and we will thus fail the
    327   // check.
    328 
    329   /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() instruction_simplifier_arm64 (before)
    330   /// CHECK:             <<Const7:i\d+>>        IntConstant 7
    331   /// CHECK:             <<Array:l\d+>>         NewArray
    332   /// CHECK:             <<Index:i\d+>>         Phi
    333   /// CHECK:                                    If
    334   //  -------------- Loop
    335   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
    336   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
    337   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Div>>]
    338 
    339   /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() instruction_simplifier_arm64 (after)
    340   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
    341   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    342   /// CHECK:             <<Array:l\d+>>         NewArray
    343   /// CHECK:             <<Index:i\d+>>         Phi
    344   /// CHECK:                                    If
    345   //  -------------- Loop
    346   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    347   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    348   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
    349   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    350   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Div>>]
    351 
    352   /// CHECK-START-ARM64: int Main.canMergeAfterBCE1() GVN$after_arch (after)
    353   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
    354   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    355   /// CHECK:             <<Array:l\d+>>         NewArray
    356   /// CHECK:             <<Index:i\d+>>         Phi
    357   /// CHECK:                                    If
    358   //  -------------- Loop
    359   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    360   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
    361   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
    362   /// CHECK-NOT:                                IntermediateAddress
    363   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Div>>]
    364 
    365 
    366   /// CHECK-START-ARM:   int Main.canMergeAfterBCE1() instruction_simplifier_arm (before)
    367   /// CHECK:             <<Const7:i\d+>>        IntConstant 7
    368   /// CHECK:             <<Array:l\d+>>         NewArray
    369   /// CHECK:             <<Index:i\d+>>         Phi
    370   /// CHECK:                                    If
    371   //  -------------- Loop
    372   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Array>>,<<Index>>]
    373   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
    374   /// CHECK:                                    ArraySet [<<Array>>,<<Index>>,<<Div>>]
    375 
    376   /// CHECK-START-ARM:   int Main.canMergeAfterBCE1() instruction_simplifier_arm (after)
    377   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
    378   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    379   /// CHECK:             <<Array:l\d+>>         NewArray
    380   /// CHECK:             <<Index:i\d+>>         Phi
    381   /// CHECK:                                    If
    382   //  -------------- Loop
    383   /// CHECK:             <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    384   /// CHECK-NEXT:        <<ArrayGet:i\d+>>      ArrayGet [<<Address1>>,<<Index>>]
    385   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
    386   /// CHECK:             <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    387   /// CHECK-NEXT:                               ArraySet [<<Address2>>,<<Index>>,<<Div>>]
    388 
    389   /// CHECK-START-ARM:   int Main.canMergeAfterBCE1() GVN$after_arch (after)
    390   /// CHECK-DAG:         <<Const7:i\d+>>        IntConstant 7
    391   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    392   /// CHECK:             <<Array:l\d+>>         NewArray
    393   /// CHECK:             <<Index:i\d+>>         Phi
    394   /// CHECK:                                    If
    395   //  -------------- Loop
    396   /// CHECK:             <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    397   /// CHECK:             <<ArrayGet:i\d+>>      ArrayGet [<<Address>>,<<Index>>]
    398   /// CHECK:             <<Div:i\d+>>           Div [<<ArrayGet>>,<<Const7>>]
    399   /// CHECK-NOT:                                IntermediateAddress
    400   /// CHECK:                                    ArraySet [<<Address>>,<<Index>>,<<Div>>]
    401 
    402   public static int canMergeAfterBCE1() {
    403     int[] array = {0, 7, 14, 21};
    404     for (int i = 0; i < array.length; i++) {
    405       array[i] = array[i] / 7;
    406     }
    407     return array[array.length - 1];
    408   }
    409 
    410   /**
    411    * This test case is similar to `canMergeAfterBCE1`, but with different
    412    * indexes for the accesses.
    413    */
    414 
    415   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() instruction_simplifier_arm64 (before)
    416   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
    417   /// CHECK:             <<Array:l\d+>>         NewArray
    418   /// CHECK:             <<Index:i\d+>>         Phi
    419   /// CHECK:                                    If
    420   //  -------------- Loop
    421   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
    422   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Array>>,<<Index>>]
    423   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Array>>,<<Index1>>]
    424   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
    425   /// CHECK:                                    ArraySet [<<Array>>,<<Index1>>,<<Shl>>]
    426 
    427   // Note that we do not care that the `DataOffset` is `12`. But if we do not
    428   // specify it and any other `IntConstant` appears before that instruction,
    429   // checker will match the previous `IntConstant`, and we will thus fail the
    430   // check.
    431 
    432   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() instruction_simplifier_arm64 (after)
    433   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    434   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    435   /// CHECK:             <<Array:l\d+>>         NewArray
    436   /// CHECK:             <<Index:i\d+>>         Phi
    437   /// CHECK:                                    If
    438   //  -------------- Loop
    439   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
    440   /// CHECK-DAG:         <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    441   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address1>>,<<Index>>]
    442   /// CHECK-DAG:         <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    443   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address2>>,<<Index1>>]
    444   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
    445   /// CHECK:             <<Address3:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    446   /// CHECK:                                    ArraySet [<<Address3>>,<<Index1>>,<<Shl>>]
    447 
    448   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() GVN$after_arch (after)
    449   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    450   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    451   /// CHECK:             <<Array:l\d+>>         NewArray
    452   /// CHECK:             <<Index:i\d+>>         Phi
    453   /// CHECK:                                    If
    454   //  -------------- Loop
    455   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
    456   /// CHECK-DAG:         <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    457   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address>>,<<Index>>]
    458   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address>>,<<Index1>>]
    459   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
    460   /// CHECK:                                    ArraySet [<<Address>>,<<Index1>>,<<Shl>>]
    461 
    462   // There should be only one intermediate address computation in the loop.
    463 
    464   /// CHECK-START-ARM64: int Main.canMergeAfterBCE2() GVN$after_arch (after)
    465   /// CHECK:                                    IntermediateAddress
    466   /// CHECK-NOT:                                IntermediateAddress
    467 
    468 
    469   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() instruction_simplifier_arm (before)
    470   /// CHECK:             <<Const1:i\d+>>        IntConstant 1
    471   /// CHECK:             <<Array:l\d+>>         NewArray
    472   /// CHECK:             <<Index:i\d+>>         Phi
    473   /// CHECK:                                    If
    474   //  -------------- Loop
    475   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
    476   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Array>>,<<Index>>]
    477   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Array>>,<<Index1>>]
    478   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
    479   /// CHECK:                                    ArraySet [<<Array>>,<<Index1>>,<<Shl>>]
    480 
    481   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() instruction_simplifier_arm (after)
    482   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    483   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    484   /// CHECK:             <<Array:l\d+>>         NewArray
    485   /// CHECK:             <<Index:i\d+>>         Phi
    486   /// CHECK:                                    If
    487   //  -------------- Loop
    488   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
    489   /// CHECK-DAG:         <<Address1:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    490   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address1>>,<<Index>>]
    491   /// CHECK-DAG:         <<Address2:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    492   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address2>>,<<Index1>>]
    493   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
    494   /// CHECK:             <<Address3:i\d+>>      IntermediateAddress [<<Array>>,<<DataOffset>>]
    495   /// CHECK:                                    ArraySet [<<Address3>>,<<Index1>>,<<Shl>>]
    496 
    497   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() GVN$after_arch (after)
    498   /// CHECK-DAG:         <<Const1:i\d+>>        IntConstant 1
    499   /// CHECK-DAG:         <<DataOffset:i\d+>>    IntConstant 12
    500   /// CHECK:             <<Array:l\d+>>         NewArray
    501   /// CHECK:             <<Index:i\d+>>         Phi
    502   /// CHECK:                                    If
    503   //  -------------- Loop
    504   /// CHECK-DAG:         <<Index1:i\d+>>        Add [<<Index>>,<<Const1>>]
    505   /// CHECK-DAG:         <<Address:i\d+>>       IntermediateAddress [<<Array>>,<<DataOffset>>]
    506   /// CHECK-DAG:         <<ArrayGetI:i\d+>>     ArrayGet [<<Address>>,<<Index>>]
    507   /// CHECK-DAG:         <<ArrayGetI1:i\d+>>    ArrayGet [<<Address>>,<<Index1>>]
    508   /// CHECK:             <<Shl:i\d+>>           Shl [<<ArrayGetI>>,<<ArrayGetI1>>]
    509   /// CHECK:                                    ArraySet [<<Address>>,<<Index1>>,<<Shl>>]
    510 
    511   /// CHECK-START-ARM:   int Main.canMergeAfterBCE2() GVN$after_arch (after)
    512   /// CHECK:                                    IntermediateAddress
    513   /// CHECK-NOT:                                IntermediateAddress
    514 
    515   public static int canMergeAfterBCE2() {
    516     int[] array = {64, 8, 4, 2 };
    517     for (int i = 0; i < array.length - 1; i++) {
    518       array[i + 1] = array[i] << array[i + 1];
    519     }
    520     return array[array.length - 1];
    521   }
    522 
    523   /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (before)
    524   /// CHECK-DAG:         <<Array1:l\d+>>        NewArray
    525   /// CHECK-DAG:         <<Array2:l\d+>>        NewArray
    526   /// CHECK-DAG:         <<Array3:l\d+>>        NewArray
    527   /// CHECK-DAG:         <<Index:i\d+>>         Phi
    528   /// CHECK-DAG:                                ArrayGet [<<Array1>>,<<Index>>]
    529   /// CHECK-DAG:                                ArrayGet [<<Array2>>,<<Index>>]
    530   /// CHECK-DAG:                                ArrayGet [<<Array3>>,<<Index>>]
    531 
    532   /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (after)
    533   /// CHECK-DAG:         <<Array1:l\d+>>        NewArray
    534   /// CHECK-DAG:         <<Array2:l\d+>>        NewArray
    535   /// CHECK-DAG:         <<Array3:l\d+>>        NewArray
    536   /// CHECK-DAG:         <<Index:i\d+>>         Phi
    537   /// CHECK-DAG:                                ArrayGet [<<Array1>>,<<Index>>]
    538   /// CHECK-DAG:                                ArrayGet [<<Array2>>,<<Index>>]
    539   /// CHECK-DAG:                                ArrayGet [<<Array3>>,<<Index>>]
    540 
    541   /// CHECK-START-ARM: int Main.checkLongFloatDouble() instruction_simplifier_arm (after)
    542   /// CHECK-NOT:                                IntermediateAddress
    543   public static int checkLongFloatDouble() {
    544     long[] array_long = {0, 1, 2, 3};
    545     float[] array_float = {(float)0.0, (float)1.0, (float)2.0, (float)3.0};
    546     double[] array_double = {0.0, 1.0, 2.0, 3.0};
    547     double s = 0.0;
    548 
    549     for (int i = 0; i < 4; i++) {
    550       s += (double)array_long[i] + (double)array_float[i] + array_double[i];
    551     }
    552     return (int)s;
    553   }
    554 
    555   public static void main(String[] args) {
    556     int[] array = {123, 456, 789};
    557 
    558     assertIntEquals(456, constantIndexGet(array));
    559 
    560     constantIndexSet(array);
    561     assertIntEquals(2, array[1]);
    562 
    563     assertIntEquals(789, get(array, 2));
    564 
    565     set(array, 1, 456);
    566     assertIntEquals(456, array[1]);
    567 
    568     getSet(array, 0);
    569     assertIntEquals(124, array[0]);
    570 
    571     accrossGC(array, 0);
    572     assertIntEquals(125, array[0]);
    573 
    574     assertIntEquals(3, canMergeAfterBCE1());
    575     assertIntEquals(1048576, canMergeAfterBCE2());
    576 
    577     assertIntEquals(18, checkLongFloatDouble());
    578   }
    579 }
    580