Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2016 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 assertIntEquals(int expected, int result) {
     23     if (expected != result) {
     24       throw new Error("Expected: " + expected + ", found: " + result);
     25     }
     26   }
     27 
     28   public static void assertLongEquals(long expected, long result) {
     29     if (expected != result) {
     30       throw new Error("Expected: " + expected + ", found: " + result);
     31     }
     32   }
     33 
     34   /**
     35    * Test transformation of Not/Not/And into Or/Not.
     36    */
     37 
     38   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
     39   /// CHECK:       <<P1:i\d+>>          ParameterValue
     40   /// CHECK:       <<P2:i\d+>>          ParameterValue
     41   /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
     42   /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
     43   /// CHECK:       <<And:i\d+>>         And [<<Not1>>,<<Not2>>]
     44   /// CHECK:                            Return [<<And>>]
     45 
     46   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
     47   /// CHECK:       <<P1:i\d+>>          ParameterValue
     48   /// CHECK:       <<P2:i\d+>>          ParameterValue
     49   /// CHECK:       <<Or:i\d+>>          Or [<<P1>>,<<P2>>]
     50   /// CHECK:       <<Not:i\d+>>         Not [<<Or>>]
     51   /// CHECK:                            Return [<<Not>>]
     52 
     53   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
     54   /// CHECK:                            Not
     55   /// CHECK-NOT:                        Not
     56 
     57   /// CHECK-START: int Main.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
     58   /// CHECK-NOT:                        And
     59 
     60   public static int $opt$noinline$andToOr(int a, int b) {
     61     if (doThrow) throw new Error();
     62     return ~a & ~b;
     63   }
     64 
     65   /**
     66    * Test transformation of Not/Not/And into Or/Not for boolean negations.
     67    * Note that the graph before this instruction simplification pass does not
     68    * contain `HBooleanNot` instructions. This is because this transformation
     69    * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
     70    * same pass.
     71    */
     72 
     73   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (before)
     74   /// CHECK:       <<P1:z\d+>>          ParameterValue
     75   /// CHECK:       <<P2:z\d+>>          ParameterValue
     76   /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
     77   /// CHECK-DAG:   <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
     78   /// CHECK-DAG:   <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
     79   /// CHECK:       <<And:i\d+>>         And [<<NotP1>>,<<NotP2>>]
     80   /// CHECK:                            Return [<<And>>]
     81 
     82   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (after)
     83   /// CHECK:       <<Cond1:z\d+>>       ParameterValue
     84   /// CHECK:       <<Cond2:z\d+>>       ParameterValue
     85   /// CHECK:       <<Or:i\d+>>          Or [<<Cond1>>,<<Cond2>>]
     86   /// CHECK:       <<BooleanNot:z\d+>>  BooleanNot [<<Or>>]
     87   /// CHECK:                            Return [<<BooleanNot>>]
     88 
     89   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
     90   /// CHECK:                            BooleanNot
     91   /// CHECK-NOT:                        BooleanNot
     92 
     93   /// CHECK-START: boolean Main.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
     94   /// CHECK-NOT:                        And
     95 
     96   public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
     97     if (doThrow) throw new Error();
     98     return !a & !b;
     99   }
    100 
    101   /**
    102    * Test transformation of Not/Not/Or into And/Not.
    103    */
    104 
    105   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
    106   /// CHECK:       <<P1:j\d+>>          ParameterValue
    107   /// CHECK:       <<P2:j\d+>>          ParameterValue
    108   /// CHECK:       <<Not1:j\d+>>        Not [<<P1>>]
    109   /// CHECK:       <<Not2:j\d+>>        Not [<<P2>>]
    110   /// CHECK:       <<Or:j\d+>>          Or [<<Not1>>,<<Not2>>]
    111   /// CHECK:                            Return [<<Or>>]
    112 
    113   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
    114   /// CHECK:       <<P1:j\d+>>          ParameterValue
    115   /// CHECK:       <<P2:j\d+>>          ParameterValue
    116   /// CHECK:       <<And:j\d+>>         And [<<P1>>,<<P2>>]
    117   /// CHECK:       <<Not:j\d+>>         Not [<<And>>]
    118   /// CHECK:                            Return [<<Not>>]
    119 
    120   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
    121   /// CHECK:                            Not
    122   /// CHECK-NOT:                        Not
    123 
    124   /// CHECK-START: long Main.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
    125   /// CHECK-NOT:                        Or
    126 
    127   public static long $opt$noinline$orToAnd(long a, long b) {
    128     if (doThrow) throw new Error();
    129     return ~a | ~b;
    130   }
    131 
    132   /**
    133    * Test transformation of Not/Not/Or into Or/And for boolean negations.
    134    * Note that the graph before this instruction simplification pass does not
    135    * contain `HBooleanNot` instructions. This is because this transformation
    136    * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
    137    * same pass.
    138    */
    139 
    140   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (before)
    141   /// CHECK:       <<P1:z\d+>>          ParameterValue
    142   /// CHECK:       <<P2:z\d+>>          ParameterValue
    143   /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
    144   /// CHECK:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
    145   /// CHECK:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
    146   /// CHECK:       <<Or:i\d+>>          Or [<<NotP1>>,<<NotP2>>]
    147   /// CHECK:                            Return [<<Or>>]
    148 
    149   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (after)
    150   /// CHECK:       <<Cond1:z\d+>>       ParameterValue
    151   /// CHECK:       <<Cond2:z\d+>>       ParameterValue
    152   /// CHECK:       <<And:i\d+>>         And [<<Cond1>>,<<Cond2>>]
    153   /// CHECK:       <<BooleanNot:z\d+>>  BooleanNot [<<And>>]
    154   /// CHECK:                            Return [<<BooleanNot>>]
    155 
    156   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
    157   /// CHECK:                            BooleanNot
    158   /// CHECK-NOT:                        BooleanNot
    159 
    160   /// CHECK-START: boolean Main.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
    161   /// CHECK-NOT:                        Or
    162 
    163   public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
    164     if (doThrow) throw new Error();
    165     return !a | !b;
    166   }
    167 
    168   /**
    169    * Test that the transformation copes with inputs being separated from the
    170    * bitwise operations.
    171    * This is a regression test. The initial logic was inserting the new bitwise
    172    * operation incorrectly.
    173    */
    174 
    175   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
    176   /// CHECK:       <<P1:i\d+>>          ParameterValue
    177   /// CHECK:       <<P2:i\d+>>          ParameterValue
    178   /// CHECK:       <<Cst1:i\d+>>        IntConstant 1
    179   /// CHECK:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
    180   /// CHECK:       <<Not1:i\d+>>        Not [<<AddP1>>]
    181   /// CHECK:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
    182   /// CHECK:       <<Not2:i\d+>>        Not [<<AddP2>>]
    183   /// CHECK:       <<Or:i\d+>>          Or [<<Not1>>,<<Not2>>]
    184   /// CHECK:                            Return [<<Or>>]
    185 
    186   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
    187   /// CHECK:       <<P1:i\d+>>          ParameterValue
    188   /// CHECK:       <<P2:i\d+>>          ParameterValue
    189   /// CHECK:       <<Cst1:i\d+>>        IntConstant 1
    190   /// CHECK:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
    191   /// CHECK:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
    192   /// CHECK:       <<And:i\d+>>         And [<<AddP1>>,<<AddP2>>]
    193   /// CHECK:       <<Not:i\d+>>         Not [<<And>>]
    194   /// CHECK:                            Return [<<Not>>]
    195 
    196   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
    197   /// CHECK:                            Not
    198   /// CHECK-NOT:                        Not
    199 
    200   /// CHECK-START: int Main.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
    201   /// CHECK-NOT:                        Or
    202 
    203   public static int $opt$noinline$regressInputsAway(int a, int b) {
    204     if (doThrow) throw new Error();
    205     int a1 = a + 1;
    206     int not_a1 = ~a1;
    207     int b1 = b + 1;
    208     int not_b1 = ~b1;
    209     return not_a1 | not_b1;
    210   }
    211 
    212   /**
    213    * Test transformation of Not/Not/Xor into Xor.
    214    */
    215 
    216   // See first note above.
    217   /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
    218   /// CHECK:       <<P1:i\d+>>          ParameterValue
    219   /// CHECK:       <<P2:i\d+>>          ParameterValue
    220   /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
    221   /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
    222   /// CHECK:       <<Xor:i\d+>>         Xor [<<Not1>>,<<Not2>>]
    223   /// CHECK:                            Return [<<Xor>>]
    224 
    225   /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
    226   /// CHECK:       <<P1:i\d+>>          ParameterValue
    227   /// CHECK:       <<P2:i\d+>>          ParameterValue
    228   /// CHECK:       <<Xor:i\d+>>         Xor [<<P1>>,<<P2>>]
    229   /// CHECK:                            Return [<<Xor>>]
    230 
    231   /// CHECK-START: int Main.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
    232   /// CHECK-NOT:                        Not
    233 
    234   public static int $opt$noinline$notXorToXor(int a, int b) {
    235     if (doThrow) throw new Error();
    236     return ~a ^ ~b;
    237   }
    238 
    239   /**
    240    * Test transformation of Not/Not/Xor into Xor for boolean negations.
    241    * Note that the graph before this instruction simplification pass does not
    242    * contain `HBooleanNot` instructions. This is because this transformation
    243    * follows the optimization of `HSelect` to `HBooleanNot` occurring in the
    244    * same pass.
    245    */
    246 
    247   /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (before)
    248   /// CHECK:       <<P1:z\d+>>          ParameterValue
    249   /// CHECK:       <<P2:z\d+>>          ParameterValue
    250   /// CHECK-DAG:   <<Const1:i\d+>>      IntConstant 1
    251   /// CHECK:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
    252   /// CHECK:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
    253   /// CHECK:       <<Xor:i\d+>>         Xor [<<NotP1>>,<<NotP2>>]
    254   /// CHECK:                            Return [<<Xor>>]
    255 
    256   /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (after)
    257   /// CHECK:       <<Cond1:z\d+>>       ParameterValue
    258   /// CHECK:       <<Cond2:z\d+>>       ParameterValue
    259   /// CHECK:       <<Xor:i\d+>>         Xor [<<Cond1>>,<<Cond2>>]
    260   /// CHECK:                            Return [<<Xor>>]
    261 
    262   /// CHECK-START: boolean Main.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
    263   /// CHECK-NOT:                        BooleanNot
    264 
    265   public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
    266     if (doThrow) throw new Error();
    267     return !a ^ !b;
    268   }
    269 
    270   /**
    271    * Check that no transformation is done when one Not has multiple uses.
    272    */
    273 
    274   /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
    275   /// CHECK:       <<P1:i\d+>>          ParameterValue
    276   /// CHECK:       <<P2:i\d+>>          ParameterValue
    277   /// CHECK:       <<One:i\d+>>         IntConstant 1
    278   /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
    279   /// CHECK:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
    280   /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
    281   /// CHECK:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
    282   /// CHECK:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
    283   /// CHECK:                            Return [<<Add>>]
    284 
    285   /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
    286   /// CHECK:       <<P1:i\d+>>          ParameterValue
    287   /// CHECK:       <<P2:i\d+>>          ParameterValue
    288   /// CHECK:       <<One:i\d+>>         IntConstant 1
    289   /// CHECK:       <<Not2:i\d+>>        Not [<<P2>>]
    290   /// CHECK:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
    291   /// CHECK:       <<Not1:i\d+>>        Not [<<P1>>]
    292   /// CHECK:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
    293   /// CHECK:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
    294   /// CHECK:                            Return [<<Add>>]
    295 
    296   /// CHECK-START: int Main.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
    297   /// CHECK-NOT:                        Or
    298 
    299   public static int $opt$noinline$notMultipleUses(int a, int b) {
    300     if (doThrow) throw new Error();
    301     int tmp = ~b;
    302     return (tmp & 0x1) + (~a & tmp);
    303   }
    304 
    305   public static void main(String[] args) {
    306     assertIntEquals(~0xff, $opt$noinline$andToOr(0xf, 0xff));
    307     assertLongEquals(~0xf, $opt$noinline$orToAnd(0xf, 0xff));
    308     assertIntEquals(0xf0, $opt$noinline$notXorToXor(0xf, 0xff));
    309     assertIntEquals(~0xff, $opt$noinline$notMultipleUses(0xf, 0xff));
    310   }
    311 }
    312