Home | History | Annotate | Download | only in src
      1 /*
      2 * Copyright (C) 2014 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   public static void assertLongEquals(long expected, long result) {
     26     if (expected != result) {
     27       throw new Error("Expected: " + expected + ", found: " + result);
     28     }
     29   }
     30 
     31   /**
     32    * Tiny three-register program exercising int constant folding
     33    * on negation.
     34    */
     35 
     36   // CHECK-START: int Main.IntNegation() constant_folding (before)
     37   // CHECK-DAG:     [[Const42:i\d+]]  IntConstant 42
     38   // CHECK-DAG:     [[Neg:i\d+]]      Neg [ [[Const42]] ]
     39   // CHECK-DAG:                       Return [ [[Neg]] ]
     40 
     41   // CHECK-START: int Main.IntNegation() constant_folding (after)
     42   // CHECK-DAG:     [[ConstN42:i\d+]] IntConstant -42
     43   // CHECK-DAG:                       Return [ [[ConstN42]] ]
     44 
     45   public static int IntNegation() {
     46     int x, y;
     47     x = 42;
     48     y = -x;
     49     return y;
     50   }
     51 
     52   /**
     53    * Tiny three-register program exercising int constant folding
     54    * on addition.
     55    */
     56 
     57   // CHECK-START: int Main.IntAddition1() constant_folding (before)
     58   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
     59   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
     60   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const1]] [[Const2]] ]
     61   // CHECK-DAG:                      Return [ [[Add]] ]
     62 
     63   // CHECK-START: int Main.IntAddition1() constant_folding (after)
     64   // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
     65   // CHECK-DAG:                      Return [ [[Const3]] ]
     66 
     67   public static int IntAddition1() {
     68     int a, b, c;
     69     a = 1;
     70     b = 2;
     71     c = a + b;
     72     return c;
     73   }
     74 
     75  /**
     76   * Small three-register program exercising int constant folding
     77   * on addition.
     78   */
     79 
     80   // CHECK-START: int Main.IntAddition2() constant_folding (before)
     81   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
     82   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
     83   // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
     84   // CHECK-DAG:     [[Const6:i\d+]]  IntConstant 6
     85   // CHECK-DAG:     [[Add1:i\d+]]    Add [ [[Const1]] [[Const2]] ]
     86   // CHECK-DAG:     [[Add2:i\d+]]    Add [ [[Const5]] [[Const6]] ]
     87   // CHECK-DAG:     [[Add3:i\d+]]    Add [ [[Add1]] [[Add2]] ]
     88   // CHECK-DAG:                      Return [ [[Add3]] ]
     89 
     90   // CHECK-START: int Main.IntAddition2() constant_folding (after)
     91   // CHECK-DAG:     [[Const14:i\d+]] IntConstant 14
     92   // CHECK-DAG:                      Return [ [[Const14]] ]
     93 
     94   public static int IntAddition2() {
     95     int a, b, c;
     96     a = 1;
     97     b = 2;
     98     a += b;
     99     b = 5;
    100     c = 6;
    101     b += c;
    102     c = a + b;
    103     return c;
    104   }
    105 
    106   /**
    107    * Tiny three-register program exercising int constant folding
    108    * on subtraction.
    109    */
    110 
    111   // CHECK-START: int Main.IntSubtraction() constant_folding (before)
    112   // CHECK-DAG:     [[Const6:i\d+]]  IntConstant 6
    113   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
    114   // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const6]] [[Const2]] ]
    115   // CHECK-DAG:                      Return [ [[Sub]] ]
    116 
    117   // CHECK-START: int Main.IntSubtraction() constant_folding (after)
    118   // CHECK-DAG:     [[Const4:i\d+]]  IntConstant 4
    119   // CHECK-DAG:                      Return [ [[Const4]] ]
    120 
    121   public static int IntSubtraction() {
    122     int a, b, c;
    123     a = 6;
    124     b = 2;
    125     c = a - b;
    126     return c;
    127   }
    128 
    129   /**
    130    * Tiny three-register program exercising long constant folding
    131    * on addition.
    132    */
    133 
    134   // CHECK-START: long Main.LongAddition() constant_folding (before)
    135   // CHECK-DAG:     [[Const1:j\d+]]  LongConstant 1
    136   // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
    137   // CHECK-DAG:     [[Add:j\d+]]     Add [ [[Const1]] [[Const2]] ]
    138   // CHECK-DAG:                      Return [ [[Add]] ]
    139 
    140   // CHECK-START: long Main.LongAddition() constant_folding (after)
    141   // CHECK-DAG:     [[Const3:j\d+]]  LongConstant 3
    142   // CHECK-DAG:                      Return [ [[Const3]] ]
    143 
    144   public static long LongAddition() {
    145     long a, b, c;
    146     a = 1L;
    147     b = 2L;
    148     c = a + b;
    149     return c;
    150   }
    151 
    152   /**
    153    * Tiny three-register program exercising long constant folding
    154    * on subtraction.
    155    */
    156 
    157   // CHECK-START: long Main.LongSubtraction() constant_folding (before)
    158   // CHECK-DAG:     [[Const6:j\d+]]  LongConstant 6
    159   // CHECK-DAG:     [[Const2:j\d+]]  LongConstant 2
    160   // CHECK-DAG:     [[Sub:j\d+]]     Sub [ [[Const6]] [[Const2]] ]
    161   // CHECK-DAG:                      Return [ [[Sub]] ]
    162 
    163   // CHECK-START: long Main.LongSubtraction() constant_folding (after)
    164   // CHECK-DAG:     [[Const4:j\d+]]  LongConstant 4
    165   // CHECK-DAG:                      Return [ [[Const4]] ]
    166 
    167   public static long LongSubtraction() {
    168     long a, b, c;
    169     a = 6L;
    170     b = 2L;
    171     c = a - b;
    172     return c;
    173   }
    174 
    175   /**
    176    * Three-register program with a constant (static) condition.
    177    */
    178 
    179   // CHECK-START: int Main.StaticCondition() constant_folding (before)
    180   // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
    181   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
    182   // CHECK-DAG:     [[Cond:z\d+]]    GreaterThanOrEqual [ [[Const7]] [[Const2]] ]
    183   // CHECK-DAG:                      If [ [[Cond]] ]
    184 
    185   // CHECK-START: int Main.StaticCondition() constant_folding (after)
    186   // CHECK-DAG:     [[Const1:i\d+]]  IntConstant 1
    187   // CHECK-DAG:                      If [ [[Const1]] ]
    188 
    189   public static int StaticCondition() {
    190     int a, b, c;
    191     a = 7;
    192     b = 2;
    193     if (a < b)
    194       c = a + b;
    195     else
    196       c = a - b;
    197     return c;
    198   }
    199 
    200   /**
    201    * Four-variable program with jumps leading to the creation of many
    202    * blocks.
    203    *
    204    * The intent of this test is to ensure that all constant expressions
    205    * are actually evaluated at compile-time, thanks to the reverse
    206    * (forward) post-order traversal of the the dominator tree.
    207    */
    208 
    209   // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (before)
    210   // CHECK-DAG:     [[Const2:i\d+]]  IntConstant 2
    211   // CHECK-DAG:     [[Const5:i\d+]]  IntConstant 5
    212   // CHECK-DAG:     [[Add:i\d+]]     Add [ [[Const5]] [[Const2]] ]
    213   // CHECK-DAG:     [[Sub:i\d+]]     Sub [ [[Const5]] [[Const2]] ]
    214   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Add]] [[Sub]] ]
    215   // CHECK-DAG:                      Return [ [[Phi]] ]
    216 
    217   // CHECK-START: int Main.JumpsAndConditionals(boolean) constant_folding (after)
    218   // CHECK-DAG:     [[Const3:i\d+]]  IntConstant 3
    219   // CHECK-DAG:     [[Const7:i\d+]]  IntConstant 7
    220   // CHECK-DAG:     [[Phi:i\d+]]     Phi [ [[Const7]] [[Const3]] ]
    221   // CHECK-DAG:                      Return [ [[Phi]] ]
    222 
    223   public static int JumpsAndConditionals(boolean cond) {
    224     int a, b, c;
    225     a = 5;
    226     b = 2;
    227     if (cond)
    228       c = a + b;
    229     else
    230       c = a - b;
    231     return c;
    232   }
    233 
    234   /**
    235    * Test optimizations of arithmetic identities yielding a constant result.
    236    */
    237 
    238   // CHECK-START: int Main.And0(int) constant_folding (before)
    239   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    240   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    241   // CHECK-DAG:     [[And:i\d+]]      And [ [[Arg]] [[Const0]] ]
    242   // CHECK-DAG:                       Return [ [[And]] ]
    243 
    244   // CHECK-START: int Main.And0(int) constant_folding (after)
    245   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    246   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    247   // CHECK-NOT:                       And
    248   // CHECK-DAG:                       Return [ [[Const0]] ]
    249 
    250   public static int And0(int arg) {
    251     return arg & 0;
    252   }
    253 
    254   // CHECK-START: long Main.Mul0(long) constant_folding (before)
    255   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
    256   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
    257   // CHECK-DAG:     [[Mul:j\d+]]      Mul [ [[Arg]] [[Const0]] ]
    258   // CHECK-DAG:                       Return [ [[Mul]] ]
    259 
    260   // CHECK-START: long Main.Mul0(long) constant_folding (after)
    261   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
    262   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
    263   // CHECK-NOT:                       Mul
    264   // CHECK-DAG:                       Return [ [[Const0]] ]
    265 
    266   public static long Mul0(long arg) {
    267     return arg * 0;
    268   }
    269 
    270   // CHECK-START: int Main.OrAllOnes(int) constant_folding (before)
    271   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    272   // CHECK-DAG:     [[ConstF:i\d+]]   IntConstant -1
    273   // CHECK-DAG:     [[Or:i\d+]]       Or [ [[Arg]] [[ConstF]] ]
    274   // CHECK-DAG:                       Return [ [[Or]] ]
    275 
    276   // CHECK-START: int Main.OrAllOnes(int) constant_folding (after)
    277   // CHECK-DAG:     [[ConstF:i\d+]]   IntConstant -1
    278   // CHECK-NOT:                       Or
    279   // CHECK-DAG:                       Return [ [[ConstF]] ]
    280 
    281   public static int OrAllOnes(int arg) {
    282     return arg | -1;
    283   }
    284 
    285   // CHECK-START: long Main.Rem0(long) constant_folding (before)
    286   // CHECK-DAG:     [[Arg:j\d+]]           ParameterValue
    287   // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
    288   // CHECK-DAG:     [[DivZeroCheck:j\d+]]  DivZeroCheck [ [[Arg]] ]
    289   // CHECK-DAG:     [[Rem:j\d+]]           Rem [ [[Const0]] [[DivZeroCheck]] ]
    290   // CHECK-DAG:                            Return [ [[Rem]] ]
    291 
    292   // CHECK-START: long Main.Rem0(long) constant_folding (after)
    293   // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
    294   // CHECK-NOT:                            Rem
    295   // CHECK-DAG:                            Return [ [[Const0]] ]
    296 
    297   public static long Rem0(long arg) {
    298     return 0 % arg;
    299   }
    300 
    301   // CHECK-START: int Main.Rem1(int) constant_folding (before)
    302   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    303   // CHECK-DAG:     [[Const1:i\d+]]   IntConstant 1
    304   // CHECK-DAG:     [[Rem:i\d+]]      Rem [ [[Arg]] [[Const1]] ]
    305   // CHECK-DAG:                       Return [ [[Rem]] ]
    306 
    307   // CHECK-START: int Main.Rem1(int) constant_folding (after)
    308   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    309   // CHECK-NOT:                       Rem
    310   // CHECK-DAG:                       Return [ [[Const0]] ]
    311 
    312   public static int Rem1(int arg) {
    313     return arg % 1;
    314   }
    315 
    316   // CHECK-START: long Main.RemN1(long) constant_folding (before)
    317   // CHECK-DAG:     [[Arg:j\d+]]           ParameterValue
    318   // CHECK-DAG:     [[ConstN1:j\d+]]       LongConstant -1
    319   // CHECK-DAG:     [[DivZeroCheck:j\d+]]  DivZeroCheck [ [[Arg]] ]
    320   // CHECK-DAG:     [[Rem:j\d+]]           Rem [ [[Arg]] [[DivZeroCheck]] ]
    321   // CHECK-DAG:                            Return [ [[Rem]] ]
    322 
    323   // CHECK-START: long Main.RemN1(long) constant_folding (after)
    324   // CHECK-DAG:     [[Const0:j\d+]]        LongConstant 0
    325   // CHECK-NOT:                            Rem
    326   // CHECK-DAG:                            Return [ [[Const0]] ]
    327 
    328   public static long RemN1(long arg) {
    329     return arg % -1;
    330   }
    331 
    332   // CHECK-START: int Main.Shl0(int) constant_folding (before)
    333   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    334   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    335   // CHECK-DAG:     [[Shl:i\d+]]      Shl [ [[Const0]] [[Arg]] ]
    336   // CHECK-DAG:                       Return [ [[Shl]] ]
    337 
    338   // CHECK-START: int Main.Shl0(int) constant_folding (after)
    339   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    340   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    341   // CHECK-NOT:                       Shl
    342   // CHECK-DAG:                       Return [ [[Const0]] ]
    343 
    344   public static int Shl0(int arg) {
    345     return 0 << arg;
    346   }
    347 
    348   // CHECK-START: long Main.Shr0(int) constant_folding (before)
    349   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    350   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
    351   // CHECK-DAG:     [[Shr:j\d+]]      Shr [ [[Const0]] [[Arg]] ]
    352   // CHECK-DAG:                       Return [ [[Shr]] ]
    353 
    354   // CHECK-START: long Main.Shr0(int) constant_folding (after)
    355   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    356   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
    357   // CHECK-NOT:                       Shr
    358   // CHECK-DAG:                       Return [ [[Const0]] ]
    359 
    360   public static long Shr0(int arg) {
    361     return (long)0 >> arg;
    362   }
    363 
    364   // CHECK-START: long Main.SubSameLong(long) constant_folding (before)
    365   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
    366   // CHECK-DAG:     [[Sub:j\d+]]      Sub [ [[Arg]] [[Arg]] ]
    367   // CHECK-DAG:                       Return [ [[Sub]] ]
    368 
    369   // CHECK-START: long Main.SubSameLong(long) constant_folding (after)
    370   // CHECK-DAG:     [[Arg:j\d+]]      ParameterValue
    371   // CHECK-DAG:     [[Const0:j\d+]]   LongConstant 0
    372   // CHECK-NOT:                       Sub
    373   // CHECK-DAG:                       Return [ [[Const0]] ]
    374 
    375   public static long SubSameLong(long arg) {
    376     return arg - arg;
    377   }
    378 
    379   // CHECK-START: int Main.UShr0(int) constant_folding (before)
    380   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    381   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    382   // CHECK-DAG:     [[UShr:i\d+]]     UShr [ [[Const0]] [[Arg]] ]
    383   // CHECK-DAG:                       Return [ [[UShr]] ]
    384 
    385   // CHECK-START: int Main.UShr0(int) constant_folding (after)
    386   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    387   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    388   // CHECK-NOT:                       UShr
    389   // CHECK-DAG:                       Return [ [[Const0]] ]
    390 
    391   public static int UShr0(int arg) {
    392     return 0 >>> arg;
    393   }
    394 
    395   // CHECK-START: int Main.XorSameInt(int) constant_folding (before)
    396   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    397   // CHECK-DAG:     [[Xor:i\d+]]      Xor [ [[Arg]] [[Arg]] ]
    398   // CHECK-DAG:                       Return [ [[Xor]] ]
    399 
    400   // CHECK-START: int Main.XorSameInt(int) constant_folding (after)
    401   // CHECK-DAG:     [[Arg:i\d+]]      ParameterValue
    402   // CHECK-DAG:     [[Const0:i\d+]]   IntConstant 0
    403   // CHECK-NOT:                       Xor
    404   // CHECK-DAG:                       Return [ [[Const0]] ]
    405 
    406   public static int XorSameInt(int arg) {
    407     return arg ^ arg;
    408   }
    409 
    410   public static void main(String[] args) {
    411     assertIntEquals(IntNegation(), -42);
    412     assertIntEquals(IntAddition1(), 3);
    413     assertIntEquals(IntAddition2(), 14);
    414     assertIntEquals(IntSubtraction(), 4);
    415     assertLongEquals(LongAddition(), 3L);
    416     assertLongEquals(LongSubtraction(), 4L);
    417     assertIntEquals(StaticCondition(), 5);
    418     assertIntEquals(JumpsAndConditionals(true), 7);
    419     assertIntEquals(JumpsAndConditionals(false), 3);
    420     int random = 123456;  // Chosen randomly.
    421     assertIntEquals(And0(random), 0);
    422     assertLongEquals(Mul0(random), 0);
    423     assertIntEquals(OrAllOnes(random), -1);
    424     assertLongEquals(Rem0(random), 0);
    425     assertIntEquals(Rem1(random), 0);
    426     assertLongEquals(RemN1(random), 0);
    427     assertIntEquals(Shl0(random), 0);
    428     assertLongEquals(Shr0(random), 0);
    429     assertLongEquals(SubSameLong(random), 0);
    430     assertIntEquals(UShr0(random), 0);
    431     assertIntEquals(XorSameInt(random), 0);
    432   }
    433 }
    434