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   // A dummy value to defeat inlining of these routines.
     20   static boolean doThrow = false;
     21 
     22   public static void assertByteEquals(byte expected, byte result) {
     23     if (expected != result) {
     24       throw new Error("Expected: " + expected + ", found: " + result);
     25     }
     26   }
     27 
     28   public static void assertCharEquals(char expected, char result) {
     29     if (expected != result) {
     30       throw new Error("Expected: " + expected + ", found: " + result);
     31     }
     32   }
     33 
     34   public static void assertShortEquals(short expected, short result) {
     35     if (expected != result) {
     36       throw new Error("Expected: " + expected + ", found: " + result);
     37     }
     38   }
     39 
     40   public static void assertIntEquals(int expected, int result) {
     41     if (expected != result) {
     42       throw new Error("Expected: " + expected + ", found: " + result);
     43     }
     44   }
     45 
     46   public static void assertLongEquals(long expected, long result) {
     47     if (expected != result) {
     48       throw new Error("Expected: " + expected + ", found: " + result);
     49     }
     50   }
     51 
     52   // Non-inlinable type-casting helpers.
     53   static  char $noinline$byteToChar   (byte v) { if (doThrow) throw new Error(); return  (char)v; }
     54   static short $noinline$byteToShort  (byte v) { if (doThrow) throw new Error(); return (short)v; }
     55   static   int $noinline$byteToInt    (byte v) { if (doThrow) throw new Error(); return   (int)v; }
     56   static  long $noinline$byteToLong   (byte v) { if (doThrow) throw new Error(); return  (long)v; }
     57   static  byte $noinline$charToByte   (char v) { if (doThrow) throw new Error(); return  (byte)v; }
     58   static short $noinline$charToShort  (char v) { if (doThrow) throw new Error(); return (short)v; }
     59   static   int $noinline$charToInt    (char v) { if (doThrow) throw new Error(); return   (int)v; }
     60   static  long $noinline$charToLong   (char v) { if (doThrow) throw new Error(); return  (long)v; }
     61   static  byte $noinline$shortToByte (short v) { if (doThrow) throw new Error(); return  (byte)v; }
     62   static  char $noinline$shortToChar (short v) { if (doThrow) throw new Error(); return  (char)v; }
     63   static   int $noinline$shortToInt  (short v) { if (doThrow) throw new Error(); return   (int)v; }
     64   static  long $noinline$shortToLong (short v) { if (doThrow) throw new Error(); return  (long)v; }
     65   static  byte $noinline$intToByte     (int v) { if (doThrow) throw new Error(); return  (byte)v; }
     66   static  char $noinline$intToChar     (int v) { if (doThrow) throw new Error(); return  (char)v; }
     67   static short $noinline$intToShort    (int v) { if (doThrow) throw new Error(); return (short)v; }
     68   static  long $noinline$intToLong     (int v) { if (doThrow) throw new Error(); return  (long)v; }
     69   static  byte $noinline$longToByte   (long v) { if (doThrow) throw new Error(); return  (byte)v; }
     70   static  char $noinline$longToChar   (long v) { if (doThrow) throw new Error(); return  (char)v; }
     71   static short $noinline$longToShort  (long v) { if (doThrow) throw new Error(); return (short)v; }
     72   static   int $noinline$longToInt    (long v) { if (doThrow) throw new Error(); return   (int)v; }
     73 
     74   /**
     75    * Basic test merging a bitfield move operation (here a type conversion) into
     76    * the shifter operand.
     77    */
     78 
     79   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (before)
     80   /// CHECK-DAG:   <<l:j\d+>>           ParameterValue
     81   /// CHECK-DAG:   <<b:b\d+>>           ParameterValue
     82   /// CHECK:       <<tmp:j\d+>>         TypeConversion [<<b>>]
     83   /// CHECK:                            Sub [<<l>>,<<tmp>>]
     84 
     85   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (after)
     86   /// CHECK-DAG:   <<l:j\d+>>           ParameterValue
     87   /// CHECK-DAG:   <<b:b\d+>>           ParameterValue
     88   /// CHECK:                            Arm64DataProcWithShifterOp [<<l>>,<<b>>] kind:Sub+SXTB
     89 
     90   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) instruction_simplifier_arm64 (after)
     91   /// CHECK-NOT:                        TypeConversion
     92   /// CHECK-NOT:                        Sub
     93 
     94   /// CHECK-START-ARM64: long Main.$opt$noinline$translate(long, byte) disassembly (after)
     95   /// CHECK:                            sub x{{\d+}}, x{{\d+}}, w{{\d+}}, sxtb
     96 
     97   public static long $opt$noinline$translate(long l, byte b) {
     98     if (doThrow) throw new Error();
     99     long tmp = (long)b;
    100     return l - tmp;
    101   }
    102 
    103 
    104   /**
    105    * Test that we do not merge into the shifter operand when the left and right
    106    * inputs are the the IR.
    107    */
    108 
    109   /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (before)
    110   /// CHECK:       <<a:i\d+>>           ParameterValue
    111   /// CHECK:       <<Const2:i\d+>>      IntConstant 2
    112   /// CHECK:       <<tmp:i\d+>>         Shl [<<a>>,<<Const2>>]
    113   /// CHECK:                            Add [<<tmp>>,<<tmp>>]
    114 
    115   /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (after)
    116   /// CHECK-DAG:   <<a:i\d+>>           ParameterValue
    117   /// CHECK-DAG:   <<Const2:i\d+>>      IntConstant 2
    118   /// CHECK:       <<Shl:i\d+>>         Shl [<<a>>,<<Const2>>]
    119   /// CHECK:                            Add [<<Shl>>,<<Shl>>]
    120 
    121   /// CHECK-START-ARM64: int Main.$opt$noinline$sameInput(int) instruction_simplifier_arm64 (after)
    122   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    123 
    124   public static int $opt$noinline$sameInput(int a) {
    125     if (doThrow) throw new Error();
    126     int tmp = a << 2;
    127     return tmp + tmp;
    128   }
    129 
    130   /**
    131    * Check that we perform the merge for multiple uses.
    132    */
    133 
    134   /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (before)
    135   /// CHECK:       <<arg:i\d+>>         ParameterValue
    136   /// CHECK:       <<Const23:i\d+>>     IntConstant 23
    137   /// CHECK:       <<tmp:i\d+>>         Shl [<<arg>>,<<Const23>>]
    138   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
    139   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
    140   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
    141   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
    142   /// CHECK:                            Add [<<tmp>>,{{i\d+}}]
    143 
    144   /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (after)
    145   /// CHECK:       <<arg:i\d+>>         ParameterValue
    146   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
    147   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
    148   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
    149   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
    150   /// CHECK:                            Arm64DataProcWithShifterOp [{{i\d+}},<<arg>>] kind:Add+LSL shift:23
    151 
    152   /// CHECK-START-ARM64: int Main.$opt$noinline$multipleUses(int) instruction_simplifier_arm64 (after)
    153   /// CHECK-NOT:                        Shl
    154   /// CHECK-NOT:                        Add
    155 
    156   public static int $opt$noinline$multipleUses(int arg) {
    157     if (doThrow) throw new Error();
    158     int tmp = arg << 23;
    159     switch (arg) {
    160       case 1:  return (arg | 1) + tmp;
    161       case 2:  return (arg | 2) + tmp;
    162       case 3:  return (arg | 3) + tmp;
    163       case 4:  return (arg | 4) + tmp;
    164       case (1 << 20):  return (arg | 5) + tmp;
    165       default: return 0;
    166     }
    167   }
    168 
    169   /**
    170    * Logical instructions cannot take 'extend' operations into the shift
    171    * operand, so test that only the shifts are merged.
    172    */
    173 
    174   /// CHECK-START-ARM64: void Main.$opt$noinline$testAnd(long, long) instruction_simplifier_arm64 (after)
    175   /// CHECK:                            Arm64DataProcWithShifterOp
    176   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    177 
    178   /// CHECK-START-ARM64: void Main.$opt$noinline$testAnd(long, long) disassembly (after)
    179   /// CHECK:                            and lsl
    180   /// CHECK:                            sxtb
    181   /// CHECK:                            and
    182 
    183   static void $opt$noinline$testAnd(long a, long b) {
    184     if (doThrow) throw new Error();
    185     assertLongEquals((a & $noinline$LongShl(b, 5)) | (a & $noinline$longToByte(b)),
    186                      (a & (b << 5)) | (a & (byte)b));
    187   }
    188 
    189   /// CHECK-START-ARM64: void Main.$opt$noinline$testOr(int, int) instruction_simplifier_arm64 (after)
    190   /// CHECK:                            Arm64DataProcWithShifterOp
    191   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    192 
    193   /// CHECK-START-ARM64: void Main.$opt$noinline$testOr(int, int) disassembly (after)
    194   /// CHECK:                            orr asr
    195   /// CHECK:                            uxth
    196   /// CHECK:                            orr
    197 
    198   static void $opt$noinline$testOr(int a, int b) {
    199     if (doThrow) throw new Error();
    200     assertIntEquals((a | $noinline$IntShr(b, 6)) | (a | $noinline$intToChar(b)),
    201                     (a | (b >> 6)) | (a | (char)b));
    202   }
    203 
    204   /// CHECK-START-ARM64: void Main.$opt$noinline$testXor(long, long) instruction_simplifier_arm64 (after)
    205   /// CHECK:                            Arm64DataProcWithShifterOp
    206   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    207 
    208   /// CHECK-START-ARM64: void Main.$opt$noinline$testXor(long, long) disassembly (after)
    209   /// CHECK:                            eor lsr
    210   /// CHECK:                            sxtw
    211   /// CHECK:                            eor
    212 
    213   static void $opt$noinline$testXor(long a, long b) {
    214     if (doThrow) throw new Error();
    215     assertLongEquals((a ^ $noinline$LongUshr(b, 7)) | (a ^ $noinline$longToInt(b)),
    216                      (a ^ (b >>> 7)) | (a ^ (int)b));
    217   }
    218 
    219   /// CHECK-START-ARM64: void Main.$opt$noinline$testNeg(int) instruction_simplifier_arm64 (after)
    220   /// CHECK:                            Arm64DataProcWithShifterOp
    221   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    222 
    223   /// CHECK-START-ARM64: void Main.$opt$noinline$testNeg(int) disassembly (after)
    224   /// CHECK:                            neg lsl
    225   /// CHECK:                            sxth
    226   /// CHECK:                            neg
    227 
    228   static void $opt$noinline$testNeg(int a) {
    229     if (doThrow) throw new Error();
    230     assertIntEquals(-$noinline$IntShl(a, 8) | -$noinline$intToShort(a),
    231                     (-(a << 8)) | (-(short)a));
    232   }
    233 
    234   /**
    235    * The functions below are used to compare the result of optimized operations
    236    * to non-optimized operations.
    237    * On the left-hand side we use a non-inlined function call to ensure the
    238    * optimization does not occur. The checker tests ensure that the optimization
    239    * does occur on the right-hand.
    240    */
    241 
    242   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt1(int, byte) instruction_simplifier_arm64 (after)
    243   /// CHECK:                            Arm64DataProcWithShifterOp
    244   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    245 
    246   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt1(int, byte) instruction_simplifier_arm64 (after)
    247   /// CHECK-NOT:                        TypeConversion
    248 
    249   public static void $opt$validateExtendByteInt1(int a, byte b) {
    250     assertIntEquals(a + $noinline$byteToChar (b), a +  (char)b);
    251     // Conversions byte->short and short->int are implicit; nothing to merge.
    252     assertIntEquals(a + $noinline$byteToShort(b), a + (short)b);
    253   }
    254 
    255   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteInt2(int, byte) instruction_simplifier_arm64 (after)
    256   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    257   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    258 
    259   public static void $opt$validateExtendByteInt2(int a, byte b) {
    260     // The conversion to `int` has been optimized away, so there is nothing to merge.
    261     assertIntEquals (a + $noinline$byteToInt (b), a +  (int)b);
    262     // There is an environment use for `(long)b`, preventing the merge.
    263     assertLongEquals(a + $noinline$byteToLong(b), a + (long)b);
    264   }
    265 
    266   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteLong(long, byte) instruction_simplifier_arm64 (after)
    267   /// CHECK:                            Arm64DataProcWithShifterOp
    268   /// CHECK:                            Arm64DataProcWithShifterOp
    269   /// CHECK:                            Arm64DataProcWithShifterOp
    270   /// CHECK:                            Arm64DataProcWithShifterOp
    271   /// CHECK:                            Arm64DataProcWithShifterOp
    272   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    273 
    274   /// CHECK-START-ARM64: void Main.$opt$validateExtendByteLong(long, byte) instruction_simplifier_arm64 (after)
    275   /// CHECK:                            TypeConversion
    276   /// CHECK-NOT:                        TypeConversion
    277 
    278   public static void $opt$validateExtendByteLong(long a, byte b) {
    279     // In each of the following tests, there will be a merge on the LHS.
    280 
    281     // The first test has an explicit byte->char conversion on RHS,
    282     // followed by a conversion that is merged with the Add.
    283     assertLongEquals(a + $noinline$byteToChar (b), a +  (char)b);
    284     // Since conversions byte->short and byte->int are implicit, the RHS
    285     // for the two tests below is the same and one is eliminated by GVN.
    286     // The other is then merged to a shifter operand instruction.
    287     assertLongEquals(a + $noinline$byteToShort(b), a + (short)b);
    288     assertLongEquals(a + $noinline$byteToInt  (b), a +  (int)b);
    289   }
    290 
    291   public static void $opt$validateExtendByte(long a, byte b) {
    292     $opt$validateExtendByteInt1((int)a, b);
    293     $opt$validateExtendByteInt2((int)a, b);
    294     $opt$validateExtendByteLong(a, b);
    295   }
    296 
    297   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt1(int, char) instruction_simplifier_arm64 (after)
    298   /// CHECK:                            Arm64DataProcWithShifterOp
    299   /// CHECK:                            Arm64DataProcWithShifterOp
    300 
    301   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt1(int, char) instruction_simplifier_arm64 (after)
    302   /// CHECK-NOT:                        TypeConversion
    303 
    304   public static void $opt$validateExtendCharInt1(int a, char b) {
    305     assertIntEquals(a + $noinline$charToByte (b), a +  (byte)b);
    306     assertIntEquals(a + $noinline$charToShort(b), a + (short)b);
    307   }
    308 
    309   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharInt2(int, char) instruction_simplifier_arm64 (after)
    310   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    311   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    312 
    313   public static void $opt$validateExtendCharInt2(int a, char b) {
    314     // The conversion to `int` has been optimized away, so there is nothing to merge.
    315     assertIntEquals (a + $noinline$charToInt (b), a +  (int)b);
    316     // There is an environment use for `(long)b`, preventing the merge.
    317     assertLongEquals(a + $noinline$charToLong(b), a + (long)b);
    318   }
    319 
    320   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharLong(long, char) instruction_simplifier_arm64 (after)
    321   /// CHECK:                            Arm64DataProcWithShifterOp
    322   /// CHECK:                            Arm64DataProcWithShifterOp
    323   /// CHECK:                            Arm64DataProcWithShifterOp
    324   /// CHECK:                            Arm64DataProcWithShifterOp
    325 
    326   /// CHECK-START-ARM64: void Main.$opt$validateExtendCharLong(long, char) instruction_simplifier_arm64 (after)
    327   /// CHECK:                            TypeConversion
    328   /// CHECK:                            TypeConversion
    329   /// CHECK-NOT:                        TypeConversion
    330 
    331   public static void $opt$validateExtendCharLong(long a, char b) {
    332     // The first two tests have a type conversion.
    333     assertLongEquals(a + $noinline$charToByte (b), a +  (byte)b);
    334     assertLongEquals(a + $noinline$charToShort(b), a + (short)b);
    335     // This test does not because the conversion to `int` is optimized away.
    336     assertLongEquals(a + $noinline$charToInt  (b), a +   (int)b);
    337   }
    338 
    339   public static void $opt$validateExtendChar(long a, char b) {
    340     $opt$validateExtendCharInt1((int)a, b);
    341     $opt$validateExtendCharInt2((int)a, b);
    342     $opt$validateExtendCharLong(a, b);
    343   }
    344 
    345   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt1(int, short) instruction_simplifier_arm64 (after)
    346   /// CHECK:                            Arm64DataProcWithShifterOp
    347   /// CHECK:                            Arm64DataProcWithShifterOp
    348 
    349   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt1(int, short) instruction_simplifier_arm64 (after)
    350   /// CHECK-NOT:                        TypeConversion
    351 
    352   public static void $opt$validateExtendShortInt1(int a, short b) {
    353     assertIntEquals(a + $noinline$shortToByte (b), a + (byte)b);
    354     assertIntEquals(a + $noinline$shortToChar (b), a + (char)b);
    355   }
    356 
    357   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortInt2(int, short) instruction_simplifier_arm64 (after)
    358   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    359   /// CHECK-NOT:                        Arm64DataProcWithShifterOp
    360 
    361   public static void $opt$validateExtendShortInt2(int a, short b) {
    362     // The conversion to `int` has been optimized away, so there is nothing to merge.
    363     assertIntEquals (a + $noinline$shortToInt  (b), a +  (int)b);
    364     // There is an environment use for `(long)b`, preventing the merge.
    365     assertLongEquals(a + $noinline$shortToLong (b), a + (long)b);
    366   }
    367 
    368   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortLong(long, short) instruction_simplifier_arm64 (after)
    369   /// CHECK:                            Arm64DataProcWithShifterOp
    370   /// CHECK:                            Arm64DataProcWithShifterOp
    371   /// CHECK:                            Arm64DataProcWithShifterOp
    372 
    373   /// CHECK-START-ARM64: void Main.$opt$validateExtendShortLong(long, short) instruction_simplifier_arm64 (after)
    374   /// CHECK:                            TypeConversion
    375   /// CHECK:                            TypeConversion
    376   /// CHECK-NOT:                        TypeConversion
    377 
    378   public static void $opt$validateExtendShortLong(long a, short b) {
    379     // The first two tests have a type conversion.
    380     assertLongEquals(a + $noinline$shortToByte(b), a + (byte)b);
    381     assertLongEquals(a + $noinline$shortToChar(b), a + (char)b);
    382     // This test does not because the conversion to `int` is optimized away.
    383     assertLongEquals(a + $noinline$shortToInt (b), a +  (int)b);
    384   }
    385 
    386   public static void $opt$validateExtendShort(long a, short b) {
    387     $opt$validateExtendShortInt1((int)a, b);
    388     $opt$validateExtendShortInt2((int)a, b);
    389     $opt$validateExtendShortLong(a, b);
    390   }
    391 
    392   /// CHECK-START-ARM64: void Main.$opt$validateExtendInt(long, int) instruction_simplifier_arm64 (after)
    393   /// CHECK:                            Arm64DataProcWithShifterOp
    394   /// CHECK:                            Arm64DataProcWithShifterOp
    395   /// CHECK:                            Arm64DataProcWithShifterOp
    396   /// CHECK:                            Arm64DataProcWithShifterOp
    397 
    398   /// CHECK-START-ARM64: void Main.$opt$validateExtendInt(long, int) instruction_simplifier_arm64 (after)
    399   /// CHECK:                            TypeConversion
    400   /// CHECK:                            TypeConversion
    401   /// CHECK:                            TypeConversion
    402   /// CHECK-NOT:                        TypeConversion
    403 
    404   public static void $opt$validateExtendInt(long a, int b) {
    405     // All tests have a conversion to `long`. The first three tests also have a
    406     // conversion from `int` to the specified type. For each test the conversion
    407     // to `long` is merged into the shifter operand.
    408     assertLongEquals(a + $noinline$intToByte (b), a +  (byte)b);
    409     assertLongEquals(a + $noinline$intToChar (b), a +  (char)b);
    410     assertLongEquals(a + $noinline$intToShort(b), a + (short)b);
    411     assertLongEquals(a + $noinline$intToLong (b), a +  (long)b);
    412   }
    413 
    414   /// CHECK-START-ARM64: void Main.$opt$validateExtendLong(long, long) instruction_simplifier_arm64 (after)
    415   /// CHECK:                            Arm64DataProcWithShifterOp
    416   /// CHECK:                            Arm64DataProcWithShifterOp
    417   /// CHECK:                            Arm64DataProcWithShifterOp
    418   /// CHECK:                            Arm64DataProcWithShifterOp
    419 
    420   /// CHECK-START-ARM64: void Main.$opt$validateExtendLong(long, long) instruction_simplifier_arm64 (after)
    421   /// CHECK:                            TypeConversion
    422   /// CHECK:                            TypeConversion
    423   /// CHECK:                            TypeConversion
    424   /// CHECK:                            TypeConversion
    425   /// CHECK-NOT:                        TypeConversion
    426 
    427   public static void $opt$validateExtendLong(long a, long b) {
    428     // Each test has two conversions, from `long` and then back to `long`. The
    429     // conversions to `long` are merged.
    430     assertLongEquals(a + $noinline$longToByte (b), a +  (byte)b);
    431     assertLongEquals(a + $noinline$longToChar (b), a +  (char)b);
    432     assertLongEquals(a + $noinline$longToShort(b), a + (short)b);
    433     assertLongEquals(a + $noinline$longToInt  (b), a +   (int)b);
    434   }
    435 
    436 
    437   static int $noinline$IntShl(int b, int c) {
    438     if (doThrow) throw new Error();
    439     return b << c;
    440   }
    441   static int $noinline$IntShr(int b, int c) {
    442     if (doThrow) throw new Error();
    443     return b >> c;
    444   }
    445   static int $noinline$IntUshr(int b, int c) {
    446     if (doThrow) throw new Error();
    447     return b >>> c;
    448   }
    449 
    450 
    451   // Each test line below should see one merge.
    452   /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after)
    453   /// CHECK:                            Arm64DataProcWithShifterOp
    454   /// CHECK:                            Arm64DataProcWithShifterOp
    455   /// CHECK:                            Arm64DataProcWithShifterOp
    456   /// CHECK:                            Arm64DataProcWithShifterOp
    457   /// CHECK:                            Arm64DataProcWithShifterOp
    458   /// CHECK:                            Arm64DataProcWithShifterOp
    459   /// CHECK:                            Arm64DataProcWithShifterOp
    460   /// CHECK:                            Arm64DataProcWithShifterOp
    461   /// CHECK:                            Arm64DataProcWithShifterOp
    462   /// CHECK:                            Arm64DataProcWithShifterOp
    463   /// CHECK:                            Arm64DataProcWithShifterOp
    464   /// CHECK:                            Arm64DataProcWithShifterOp
    465   /// CHECK:                            Arm64DataProcWithShifterOp
    466   /// CHECK:                            Arm64DataProcWithShifterOp
    467   /// CHECK:                            Arm64DataProcWithShifterOp
    468   /// CHECK:                            Arm64DataProcWithShifterOp
    469   /// CHECK:                            Arm64DataProcWithShifterOp
    470   /// CHECK:                            Arm64DataProcWithShifterOp
    471   /// CHECK:                            Arm64DataProcWithShifterOp
    472   /// CHECK:                            Arm64DataProcWithShifterOp
    473   /// CHECK:                            Arm64DataProcWithShifterOp
    474   /// CHECK:                            Arm64DataProcWithShifterOp
    475   /// CHECK:                            Arm64DataProcWithShifterOp
    476   /// CHECK:                            Arm64DataProcWithShifterOp
    477   /// CHECK:                            Arm64DataProcWithShifterOp
    478   /// CHECK:                            Arm64DataProcWithShifterOp
    479   /// CHECK:                            Arm64DataProcWithShifterOp
    480   /// CHECK:                            Arm64DataProcWithShifterOp
    481   /// CHECK:                            Arm64DataProcWithShifterOp
    482   /// CHECK:                            Arm64DataProcWithShifterOp
    483   /// CHECK:                            Arm64DataProcWithShifterOp
    484   /// CHECK:                            Arm64DataProcWithShifterOp
    485   /// CHECK:                            Arm64DataProcWithShifterOp
    486   // Note: `b << 32`, `b >> 32` and `b >>> 32` are optimized away by generic simplifier.
    487 
    488   /// CHECK-START-ARM64: void Main.$opt$validateShiftInt(int, int) instruction_simplifier_arm64 (after)
    489   /// CHECK-NOT:                        Shl
    490   /// CHECK-NOT:                        Shr
    491   /// CHECK-NOT:                        UShr
    492 
    493   public static void $opt$validateShiftInt(int a, int b) {
    494     assertIntEquals(a + $noinline$IntShl(b, 1),   a + (b <<  1));
    495     assertIntEquals(a + $noinline$IntShl(b, 6),   a + (b <<  6));
    496     assertIntEquals(a + $noinline$IntShl(b, 7),   a + (b <<  7));
    497     assertIntEquals(a + $noinline$IntShl(b, 8),   a + (b <<  8));
    498     assertIntEquals(a + $noinline$IntShl(b, 14),  a + (b << 14));
    499     assertIntEquals(a + $noinline$IntShl(b, 15),  a + (b << 15));
    500     assertIntEquals(a + $noinline$IntShl(b, 16),  a + (b << 16));
    501     assertIntEquals(a + $noinline$IntShl(b, 30),  a + (b << 30));
    502     assertIntEquals(a + $noinline$IntShl(b, 31),  a + (b << 31));
    503     assertIntEquals(a + $noinline$IntShl(b, 32),  a + (b << $opt$inline$IntConstant32()));
    504     assertIntEquals(a + $noinline$IntShl(b, 62),  a + (b << $opt$inline$IntConstant62()));
    505     assertIntEquals(a + $noinline$IntShl(b, 63),  a + (b << $opt$inline$IntConstant63()));
    506 
    507     assertIntEquals(a - $noinline$IntShr(b, 1),   a - (b >>  1));
    508     assertIntEquals(a - $noinline$IntShr(b, 6),   a - (b >>  6));
    509     assertIntEquals(a - $noinline$IntShr(b, 7),   a - (b >>  7));
    510     assertIntEquals(a - $noinline$IntShr(b, 8),   a - (b >>  8));
    511     assertIntEquals(a - $noinline$IntShr(b, 14),  a - (b >> 14));
    512     assertIntEquals(a - $noinline$IntShr(b, 15),  a - (b >> 15));
    513     assertIntEquals(a - $noinline$IntShr(b, 16),  a - (b >> 16));
    514     assertIntEquals(a - $noinline$IntShr(b, 30),  a - (b >> 30));
    515     assertIntEquals(a - $noinline$IntShr(b, 31),  a - (b >> 31));
    516     assertIntEquals(a - $noinline$IntShr(b, 32),  a - (b >> $opt$inline$IntConstant32()));
    517     assertIntEquals(a - $noinline$IntShr(b, 62),  a - (b >> $opt$inline$IntConstant62()));
    518     assertIntEquals(a - $noinline$IntShr(b, 63),  a - (b >> $opt$inline$IntConstant63()));
    519 
    520     assertIntEquals(a ^ $noinline$IntUshr(b, 1),   a ^ (b >>>  1));
    521     assertIntEquals(a ^ $noinline$IntUshr(b, 6),   a ^ (b >>>  6));
    522     assertIntEquals(a ^ $noinline$IntUshr(b, 7),   a ^ (b >>>  7));
    523     assertIntEquals(a ^ $noinline$IntUshr(b, 8),   a ^ (b >>>  8));
    524     assertIntEquals(a ^ $noinline$IntUshr(b, 14),  a ^ (b >>> 14));
    525     assertIntEquals(a ^ $noinline$IntUshr(b, 15),  a ^ (b >>> 15));
    526     assertIntEquals(a ^ $noinline$IntUshr(b, 16),  a ^ (b >>> 16));
    527     assertIntEquals(a ^ $noinline$IntUshr(b, 30),  a ^ (b >>> 30));
    528     assertIntEquals(a ^ $noinline$IntUshr(b, 31),  a ^ (b >>> 31));
    529     assertIntEquals(a ^ $noinline$IntUshr(b, 32),  a ^ (b >>> $opt$inline$IntConstant32()));
    530     assertIntEquals(a ^ $noinline$IntUshr(b, 62),  a ^ (b >>> $opt$inline$IntConstant62()));
    531     assertIntEquals(a ^ $noinline$IntUshr(b, 63),  a ^ (b >>> $opt$inline$IntConstant63()));
    532   }
    533 
    534   // Hiding constants outside the range [0, 32) used for int shifts from Jack.
    535   // (Jack extracts only the low 5 bits.)
    536   public static int $opt$inline$IntConstant32() { return 32; }
    537   public static int $opt$inline$IntConstant62() { return 62; }
    538   public static int $opt$inline$IntConstant63() { return 63; }
    539 
    540 
    541   static long $noinline$LongShl(long b, long c) {
    542     if (doThrow) throw new Error();
    543     return b << c;
    544   }
    545   static long $noinline$LongShr(long b, long c) {
    546     if (doThrow) throw new Error();
    547     return b >> c;
    548   }
    549   static long $noinline$LongUshr(long b, long c) {
    550     if (doThrow) throw new Error();
    551     return b >>> c;
    552   }
    553 
    554   // Each test line below should see one merge.
    555   /// CHECK-START-ARM64: void Main.$opt$validateShiftLong(long, long) instruction_simplifier_arm64 (after)
    556   /// CHECK:                            Arm64DataProcWithShifterOp
    557   /// CHECK:                            Arm64DataProcWithShifterOp
    558   /// CHECK:                            Arm64DataProcWithShifterOp
    559   /// CHECK:                            Arm64DataProcWithShifterOp
    560   /// CHECK:                            Arm64DataProcWithShifterOp
    561   /// CHECK:                            Arm64DataProcWithShifterOp
    562   /// CHECK:                            Arm64DataProcWithShifterOp
    563   /// CHECK:                            Arm64DataProcWithShifterOp
    564   /// CHECK:                            Arm64DataProcWithShifterOp
    565   /// CHECK:                            Arm64DataProcWithShifterOp
    566   /// CHECK:                            Arm64DataProcWithShifterOp
    567   /// CHECK:                            Arm64DataProcWithShifterOp
    568   /// CHECK:                            Arm64DataProcWithShifterOp
    569   /// CHECK:                            Arm64DataProcWithShifterOp
    570   /// CHECK:                            Arm64DataProcWithShifterOp
    571   /// CHECK:                            Arm64DataProcWithShifterOp
    572   /// CHECK:                            Arm64DataProcWithShifterOp
    573   /// CHECK:                            Arm64DataProcWithShifterOp
    574   /// CHECK:                            Arm64DataProcWithShifterOp
    575   /// CHECK:                            Arm64DataProcWithShifterOp
    576   /// CHECK:                            Arm64DataProcWithShifterOp
    577   /// CHECK:                            Arm64DataProcWithShifterOp
    578   /// CHECK:                            Arm64DataProcWithShifterOp
    579   /// CHECK:                            Arm64DataProcWithShifterOp
    580   /// CHECK:                            Arm64DataProcWithShifterOp
    581   /// CHECK:                            Arm64DataProcWithShifterOp
    582   /// CHECK:                            Arm64DataProcWithShifterOp
    583   /// CHECK:                            Arm64DataProcWithShifterOp
    584   /// CHECK:                            Arm64DataProcWithShifterOp
    585   /// CHECK:                            Arm64DataProcWithShifterOp
    586   /// CHECK:                            Arm64DataProcWithShifterOp
    587   /// CHECK:                            Arm64DataProcWithShifterOp
    588   /// CHECK:                            Arm64DataProcWithShifterOp
    589   /// CHECK:                            Arm64DataProcWithShifterOp
    590   /// CHECK:                            Arm64DataProcWithShifterOp
    591   /// CHECK:                            Arm64DataProcWithShifterOp
    592 
    593   /// CHECK-START-ARM64: void Main.$opt$validateShiftLong(long, long) instruction_simplifier_arm64 (after)
    594   /// CHECK-NOT:                        Shl
    595   /// CHECK-NOT:                        Shr
    596   /// CHECK-NOT:                        UShr
    597 
    598   public static void $opt$validateShiftLong(long a, long b) {
    599     assertLongEquals(a + $noinline$LongShl(b, 1),   a + (b <<  1));
    600     assertLongEquals(a + $noinline$LongShl(b, 6),   a + (b <<  6));
    601     assertLongEquals(a + $noinline$LongShl(b, 7),   a + (b <<  7));
    602     assertLongEquals(a + $noinline$LongShl(b, 8),   a + (b <<  8));
    603     assertLongEquals(a + $noinline$LongShl(b, 14),  a + (b << 14));
    604     assertLongEquals(a + $noinline$LongShl(b, 15),  a + (b << 15));
    605     assertLongEquals(a + $noinline$LongShl(b, 16),  a + (b << 16));
    606     assertLongEquals(a + $noinline$LongShl(b, 30),  a + (b << 30));
    607     assertLongEquals(a + $noinline$LongShl(b, 31),  a + (b << 31));
    608     assertLongEquals(a + $noinline$LongShl(b, 32),  a + (b << 32));
    609     assertLongEquals(a + $noinline$LongShl(b, 62),  a + (b << 62));
    610     assertLongEquals(a + $noinline$LongShl(b, 63),  a + (b << 63));
    611 
    612     assertLongEquals(a - $noinline$LongShr(b, 1),   a - (b >>  1));
    613     assertLongEquals(a - $noinline$LongShr(b, 6),   a - (b >>  6));
    614     assertLongEquals(a - $noinline$LongShr(b, 7),   a - (b >>  7));
    615     assertLongEquals(a - $noinline$LongShr(b, 8),   a - (b >>  8));
    616     assertLongEquals(a - $noinline$LongShr(b, 14),  a - (b >> 14));
    617     assertLongEquals(a - $noinline$LongShr(b, 15),  a - (b >> 15));
    618     assertLongEquals(a - $noinline$LongShr(b, 16),  a - (b >> 16));
    619     assertLongEquals(a - $noinline$LongShr(b, 30),  a - (b >> 30));
    620     assertLongEquals(a - $noinline$LongShr(b, 31),  a - (b >> 31));
    621     assertLongEquals(a - $noinline$LongShr(b, 32),  a - (b >> 32));
    622     assertLongEquals(a - $noinline$LongShr(b, 62),  a - (b >> 62));
    623     assertLongEquals(a - $noinline$LongShr(b, 63),  a - (b >> 63));
    624 
    625     assertLongEquals(a ^ $noinline$LongUshr(b, 1),   a ^ (b >>>  1));
    626     assertLongEquals(a ^ $noinline$LongUshr(b, 6),   a ^ (b >>>  6));
    627     assertLongEquals(a ^ $noinline$LongUshr(b, 7),   a ^ (b >>>  7));
    628     assertLongEquals(a ^ $noinline$LongUshr(b, 8),   a ^ (b >>>  8));
    629     assertLongEquals(a ^ $noinline$LongUshr(b, 14),  a ^ (b >>> 14));
    630     assertLongEquals(a ^ $noinline$LongUshr(b, 15),  a ^ (b >>> 15));
    631     assertLongEquals(a ^ $noinline$LongUshr(b, 16),  a ^ (b >>> 16));
    632     assertLongEquals(a ^ $noinline$LongUshr(b, 30),  a ^ (b >>> 30));
    633     assertLongEquals(a ^ $noinline$LongUshr(b, 31),  a ^ (b >>> 31));
    634     assertLongEquals(a ^ $noinline$LongUshr(b, 32),  a ^ (b >>> 32));
    635     assertLongEquals(a ^ $noinline$LongUshr(b, 62),  a ^ (b >>> 62));
    636     assertLongEquals(a ^ $noinline$LongUshr(b, 63),  a ^ (b >>> 63));
    637   }
    638 
    639 
    640   public static void main(String[] args) {
    641     assertLongEquals(10000L - 3L, $opt$noinline$translate(10000L, (byte)3));
    642     assertLongEquals(-10000L - -3L, $opt$noinline$translate(-10000L, (byte)-3));
    643 
    644     assertIntEquals(4096, $opt$noinline$sameInput(512));
    645     assertIntEquals(-8192, $opt$noinline$sameInput(-1024));
    646 
    647     assertIntEquals(((1 << 23) | 1), $opt$noinline$multipleUses(1));
    648     assertIntEquals(((1 << 20) | 5), $opt$noinline$multipleUses(1 << 20));
    649 
    650     long inputs[] = {
    651       -((1L <<  7) - 1L), -((1L <<  7)), -((1L <<  7) + 1L),
    652       -((1L << 15) - 1L), -((1L << 15)), -((1L << 15) + 1L),
    653       -((1L << 16) - 1L), -((1L << 16)), -((1L << 16) + 1L),
    654       -((1L << 31) - 1L), -((1L << 31)), -((1L << 31) + 1L),
    655       -((1L << 32) - 1L), -((1L << 32)), -((1L << 32) + 1L),
    656       -((1L << 63) - 1L), -((1L << 63)), -((1L << 63) + 1L),
    657       -42L, -314L, -2718281828L, -0x123456789L, -0x987654321L,
    658       -1L, -20L, -300L, -4000L, -50000L, -600000L, -7000000L, -80000000L,
    659       0L,
    660       1L, 20L, 300L, 4000L, 50000L, 600000L, 7000000L, 80000000L,
    661       42L,  314L,  2718281828L,  0x123456789L,  0x987654321L,
    662       (1L <<  7) - 1L, (1L <<  7), (1L <<  7) + 1L,
    663       (1L <<  8) - 1L, (1L <<  8), (1L <<  8) + 1L,
    664       (1L << 15) - 1L, (1L << 15), (1L << 15) + 1L,
    665       (1L << 16) - 1L, (1L << 16), (1L << 16) + 1L,
    666       (1L << 31) - 1L, (1L << 31), (1L << 31) + 1L,
    667       (1L << 32) - 1L, (1L << 32), (1L << 32) + 1L,
    668       (1L << 63) - 1L, (1L << 63), (1L << 63) + 1L,
    669       Long.MIN_VALUE, Long.MAX_VALUE
    670     };
    671     for (int i = 0; i < inputs.length; i++) {
    672       $opt$noinline$testNeg((int)inputs[i]);
    673       for (int j = 0; j < inputs.length; j++) {
    674         $opt$noinline$testAnd(inputs[i], inputs[j]);
    675         $opt$noinline$testOr((int)inputs[i], (int)inputs[j]);
    676         $opt$noinline$testXor(inputs[i], inputs[j]);
    677 
    678         $opt$validateExtendByte(inputs[i], (byte)inputs[j]);
    679         $opt$validateExtendChar(inputs[i], (char)inputs[j]);
    680         $opt$validateExtendShort(inputs[i], (short)inputs[j]);
    681         $opt$validateExtendInt(inputs[i], (int)inputs[j]);
    682         $opt$validateExtendLong(inputs[i], inputs[j]);
    683 
    684         $opt$validateShiftInt((int)inputs[i], (int)inputs[j]);
    685         $opt$validateShiftLong(inputs[i], inputs[j]);
    686       }
    687     }
    688 
    689   }
    690 }
    691