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 merging of `NOT+AND` into `BIC`.
     36    */
     37 
     38   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (before)
     39   /// CHECK:       <<Base:i\d+>>        ParameterValue
     40   /// CHECK:       <<Mask:i\d+>>        ParameterValue
     41   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
     42   /// CHECK:       <<Op:i\d+>>          And [<<Base>>,<<Not>>]
     43   /// CHECK:                            Return [<<Op>>]
     44 
     45   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after)
     46   /// CHECK:       <<Base:i\d+>>        ParameterValue
     47   /// CHECK:       <<Mask:i\d+>>        ParameterValue
     48   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And
     49   /// CHECK:                            Return [<<NegOp>>]
     50 
     51   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm64 (after)
     52   /// CHECK-NOT:                        Not
     53   /// CHECK-NOT:                        And
     54 
     55   /// CHECK-START-ARM64: int Main.$opt$noinline$notAnd(int, int) disassembly (after)
     56   /// CHECK:                            bic w{{\d+}}, w{{\d+}}, w{{\d+}}
     57 
     58 
     59   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (before)
     60   /// CHECK:       <<Base:i\d+>>        ParameterValue
     61   /// CHECK:       <<Mask:i\d+>>        ParameterValue
     62   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
     63   /// CHECK:       <<Op:i\d+>>          And [<<Base>>,<<Not>>]
     64   /// CHECK:                            Return [<<Op>>]
     65 
     66   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after)
     67   /// CHECK:       <<Base:i\d+>>        ParameterValue
     68   /// CHECK:       <<Mask:i\d+>>        ParameterValue
     69   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:And
     70   /// CHECK:                            Return [<<NegOp>>]
     71 
     72   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) instruction_simplifier_arm (after)
     73   /// CHECK-NOT:                        Not
     74   /// CHECK-NOT:                        And
     75 
     76   /// CHECK-START-ARM:   int Main.$opt$noinline$notAnd(int, int) disassembly (after)
     77   /// CHECK:                            bic.w r{{\d+}}, r{{\d+}}, r{{\d+}}
     78 
     79   public static int $opt$noinline$notAnd(int base, int mask) {
     80     if (doThrow) throw new Error();
     81     return base & ~mask;
     82   }
     83 
     84   /**
     85    * Test merging of `NOT+ORR` into `ORN`.
     86    */
     87 
     88   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (before)
     89   /// CHECK:       <<Base:j\d+>>        ParameterValue
     90   /// CHECK:       <<Mask:j\d+>>        ParameterValue
     91   /// CHECK:       <<Not:j\d+>>         Not [<<Mask>>]
     92   /// CHECK:       <<Op:j\d+>>          Or [<<Base>>,<<Not>>]
     93   /// CHECK:                            Return [<<Op>>]
     94 
     95   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after)
     96   /// CHECK:       <<Base:j\d+>>        ParameterValue
     97   /// CHECK:       <<Mask:j\d+>>        ParameterValue
     98   /// CHECK:       <<NegOp:j\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or
     99   /// CHECK:                            Return [<<NegOp>>]
    100 
    101   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm64 (after)
    102   /// CHECK-NOT:                        Not
    103   /// CHECK-NOT:                        Or
    104 
    105   /// CHECK-START-ARM64: long Main.$opt$noinline$notOr(long, long) disassembly (after)
    106   /// CHECK:                            orn x{{\d+}}, x{{\d+}}, x{{\d+}}
    107 
    108 
    109   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (before)
    110   /// CHECK:       <<Base:j\d+>>        ParameterValue
    111   /// CHECK:       <<Mask:j\d+>>        ParameterValue
    112   /// CHECK:       <<Not:j\d+>>         Not [<<Mask>>]
    113   /// CHECK:       <<Op:j\d+>>          Or [<<Base>>,<<Not>>]
    114   /// CHECK:                            Return [<<Op>>]
    115 
    116   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after)
    117   /// CHECK:       <<Base:j\d+>>        ParameterValue
    118   /// CHECK:       <<Mask:j\d+>>        ParameterValue
    119   /// CHECK:       <<NegOp:j\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Or
    120   /// CHECK:                            Return [<<NegOp>>]
    121 
    122   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) instruction_simplifier_arm (after)
    123   /// CHECK-NOT:                        Not
    124   /// CHECK-NOT:                        Or
    125 
    126   /// CHECK-START-ARM:   long Main.$opt$noinline$notOr(long, long) disassembly (after)
    127   /// CHECK:                            orn.w r{{\d+}}, r{{\d+}}, r{{\d+}}
    128 
    129   public static long $opt$noinline$notOr(long base, long mask) {
    130     if (doThrow) throw new Error();
    131     return base | ~mask;
    132   }
    133 
    134   /**
    135    * Test merging of `NOT+EOR` into `EON`.
    136    */
    137 
    138   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (before)
    139   /// CHECK:       <<Base:i\d+>>        ParameterValue
    140   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    141   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
    142   /// CHECK:       <<Op:i\d+>>          Xor [<<Base>>,<<Not>>]
    143   /// CHECK:                            Return [<<Op>>]
    144 
    145   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after)
    146   /// CHECK:       <<Base:i\d+>>        ParameterValue
    147   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    148   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Base>>,<<Mask>>] kind:Xor
    149   /// CHECK:                            Return [<<NegOp>>]
    150 
    151   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm64 (after)
    152   /// CHECK-NOT:                        Not
    153   /// CHECK-NOT:                        Xor
    154 
    155   /// CHECK-START-ARM64: int Main.$opt$noinline$notXor(int, int) disassembly (after)
    156   /// CHECK:                            eon w{{\d+}}, w{{\d+}}, w{{\d+}}
    157 
    158 
    159   /// CHECK-START-ARM:   int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (before)
    160   /// CHECK:       <<Base:i\d+>>        ParameterValue
    161   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    162   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
    163   /// CHECK:       <<Op:i\d+>>          Xor [<<Base>>,<<Not>>]
    164   /// CHECK:                            Return [<<Op>>]
    165 
    166   /// CHECK-START-ARM:   int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after)
    167   /// CHECK:       <<Base:i\d+>>        ParameterValue
    168   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    169   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
    170   /// CHECK:       <<Op:i\d+>>          Xor [<<Base>>,<<Not>>]
    171   /// CHECK:                            Return [<<Op>>]
    172 
    173   /// CHECK-START-ARM:   int Main.$opt$noinline$notXor(int, int) instruction_simplifier_arm (after)
    174   /// CHECK-NOT:                        BitwiseNegatedRight
    175 
    176   public static int $opt$noinline$notXor(int base, int mask) {
    177     if (doThrow) throw new Error();
    178     return base ^ ~mask;
    179   }
    180 
    181   /**
    182    * Check that transformation is done when the argument is a constant.
    183    */
    184 
    185   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (before)
    186   /// CHECK:       <<Base:i\d+>>        ParameterValue
    187   /// CHECK:       <<Constant:i\d+>>    IntConstant
    188   /// CHECK:       <<Not:i\d+>>         Not [<<Base>>]
    189   /// CHECK:       <<Op:i\d+>>          And [<<Not>>,<<Constant>>]
    190   /// CHECK:                            Return [<<Op>>]
    191 
    192   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm64 (after)
    193   /// CHECK:       <<Base:i\d+>>        ParameterValue
    194   /// CHECK:       <<Constant:i\d+>>    IntConstant
    195   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
    196   /// CHECK:                            Return [<<NegOp>>]
    197 
    198 
    199   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (before)
    200   /// CHECK:       <<Base:i\d+>>        ParameterValue
    201   /// CHECK:       <<Constant:i\d+>>    IntConstant
    202   /// CHECK:       <<Not:i\d+>>         Not [<<Base>>]
    203   /// CHECK:       <<Op:i\d+>>          And [<<Not>>,<<Constant>>]
    204   /// CHECK:                            Return [<<Op>>]
    205 
    206   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndConstant(int) instruction_simplifier_arm (after)
    207   /// CHECK:       <<Base:i\d+>>        ParameterValue
    208   /// CHECK:       <<Constant:i\d+>>    IntConstant
    209   /// CHECK:       <<NegOp:i\d+>>       BitwiseNegatedRight [<<Constant>>,<<Base>>] kind:And
    210   /// CHECK:                            Return [<<NegOp>>]
    211 
    212   public static int $opt$noinline$notAndConstant(int mask) {
    213     if (doThrow) throw new Error();
    214     return 0xf & ~mask;
    215   }
    216 
    217   /**
    218    * Check that no transformation is done when Not has multiple uses.
    219    */
    220 
    221   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (before)
    222   /// CHECK:       <<Base:i\d+>>        ParameterValue
    223   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    224   /// CHECK:       <<One:i\d+>>         IntConstant
    225   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
    226   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
    227   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
    228   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
    229   /// CHECK:                            Return [<<Add>>]
    230 
    231   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after)
    232   /// CHECK:       <<Base:i\d+>>        ParameterValue
    233   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    234   /// CHECK:       <<One:i\d+>>         IntConstant
    235   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
    236   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
    237   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
    238   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
    239   /// CHECK:                            Return [<<Add>>]
    240 
    241   /// CHECK-START-ARM64: int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm64 (after)
    242   /// CHECK-NOT:                        BitwiseNegatedRight
    243 
    244 
    245   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (before)
    246   /// CHECK:       <<Base:i\d+>>        ParameterValue
    247   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    248   /// CHECK:       <<One:i\d+>>         IntConstant
    249   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
    250   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
    251   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
    252   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
    253   /// CHECK:                            Return [<<Add>>]
    254 
    255   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after)
    256   /// CHECK:       <<Base:i\d+>>        ParameterValue
    257   /// CHECK:       <<Mask:i\d+>>        ParameterValue
    258   /// CHECK:       <<One:i\d+>>         IntConstant
    259   /// CHECK:       <<Not:i\d+>>         Not [<<Mask>>]
    260   /// CHECK:       <<Op1:i\d+>>         And [<<Not>>,<<One>>]
    261   /// CHECK:       <<Op2:i\d+>>         And [<<Base>>,<<Not>>]
    262   /// CHECK:       <<Add:i\d+>>         Add [<<Op1>>,<<Op2>>]
    263   /// CHECK:                            Return [<<Add>>]
    264 
    265   /// CHECK-START-ARM:   int Main.$opt$noinline$notAndMultipleUses(int, int) instruction_simplifier_arm (after)
    266   /// CHECK-NOT:                        BitwiseNegatedRight
    267 
    268   public static int $opt$noinline$notAndMultipleUses(int base, int mask) {
    269     if (doThrow) throw new Error();
    270     int tmp = ~mask;
    271     return (tmp & 0x1) + (base & tmp);
    272   }
    273 
    274   /**
    275    * Check that no transformation is done when both inputs are Not's.
    276    */
    277 
    278   // We don't check the instructions before the pass, since if De Morgan's laws
    279   // have been applied then Not/Not/Or is replaced by And/Not.
    280 
    281   /// CHECK-START-ARM64: int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm64 (after)
    282   /// CHECK-NOT:                        BitwiseNegatedRight
    283 
    284   /// CHECK-START-ARM:   int Main.$opt$noinline$deMorganOr(int, int) instruction_simplifier_arm (after)
    285   /// CHECK-NOT:                        BitwiseNegatedRight
    286 
    287   public static int $opt$noinline$deMorganOr(int a, int b) {
    288     if (doThrow) throw new Error();
    289     return ~a | ~b;
    290   }
    291 
    292   public static void main(String[] args) {
    293     assertIntEquals(0xe,   $opt$noinline$notAnd(0xf, 0x1));
    294     assertLongEquals(~0x0, $opt$noinline$notOr(0xf, 0x1));
    295     assertIntEquals(~0xe,  $opt$noinline$notXor(0xf, 0x1));
    296     assertIntEquals(0xe,  $opt$noinline$notAndConstant(0x1));
    297     assertIntEquals(0xe,   $opt$noinline$notAndMultipleUses(0xf, 0x1));
    298     assertIntEquals(~0x1,  $opt$noinline$deMorganOr(0x3, 0x1));
    299   }
    300 }
    301