Home | History | Annotate | Download | only in smali
      1 # Copyright (C) 2017 The Android Open Source Project
      2 #
      3 # Licensed under the Apache License, Version 2.0 (the "License");
      4 # you may not use this file except in compliance with the License.
      5 # You may obtain a copy of the License at
      6 #
      7 #      http://www.apache.org/licenses/LICENSE-2.0
      8 #
      9 # Unless required by applicable law or agreed to in writing, software
     10 # distributed under the License is distributed on an "AS IS" BASIS,
     11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 # See the License for the specific language governing permissions and
     13 # limitations under the License.
     14 
     15 .class public LSmaliTests;
     16 .super Ljava/lang/Object;
     17 
     18 #
     19 # Test transformation of Not/Not/And into Or/Not.
     20 #
     21 
     22 ## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
     23 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
     24 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
     25 ## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
     26 ## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
     27 ## CHECK-DAG:       <<And:i\d+>>         And [<<Not1>>,<<Not2>>]
     28 ## CHECK-DAG:                            Return [<<And>>]
     29 
     30 ## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
     31 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
     32 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
     33 ## CHECK-DAG:       <<Or:i\d+>>          Or [<<P1>>,<<P2>>]
     34 ## CHECK-DAG:       <<Not:i\d+>>         Not [<<Or>>]
     35 ## CHECK-DAG:                            Return [<<Not>>]
     36 
     37 ## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
     38 ## CHECK-DAG:                            Not
     39 ## CHECK-NOT:                            Not
     40 
     41 ## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
     42 ## CHECK-NOT:                            And
     43 .method public static $opt$noinline$andToOr(II)I
     44     .registers 4
     45     .param p0, "a"    # I
     46     .param p1, "b"    # I
     47 
     48     .prologue
     49     sget-boolean v0, LSmaliTests;->doThrow:Z
     50     if-eqz v0, :cond_a
     51     new-instance v0, Ljava/lang/Error;
     52     invoke-direct {v0}, Ljava/lang/Error;-><init>()V
     53     throw v0
     54 
     55   :cond_a
     56     # return ~a & ~b;
     57     not-int v0, p0
     58     not-int v1, p1
     59     and-int/2addr v0, v1
     60 
     61     return v0
     62 .end method
     63 
     64 # Test transformation of Not/Not/And into Or/Not for boolean negations.
     65 # Note that the graph before this instruction simplification pass does not
     66 # contain `HBooleanNot` instructions. This is because this transformation
     67 # follows the optimization of `HSelect` to `HBooleanNot` occurring in the
     68 # same pass.
     69 
     70 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (before)
     71 ## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
     72 ## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
     73 ## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
     74 ## CHECK-DAG:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
     75 ## CHECK-DAG:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
     76 ## CHECK-DAG:       <<And:i\d+>>         And [<<NotP1>>,<<NotP2>>]
     77 ## CHECK-DAG:                            Return [<<And>>]
     78 
     79 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (after)
     80 ## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
     81 ## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
     82 ## CHECK-DAG:       <<Or:i\d+>>          Or [<<Cond1>>,<<Cond2>>]
     83 ## CHECK-DAG:       <<BooleanNot:z\d+>>  BooleanNot [<<Or>>]
     84 ## CHECK-DAG:                            Return [<<BooleanNot>>]
     85 
     86 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
     87 ## CHECK-DAG:                            BooleanNot
     88 ## CHECK-NOT:                            BooleanNot
     89 
     90 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
     91 ## CHECK-NOT:                            And
     92 .method public static $opt$noinline$booleanAndToOr(ZZ)Z
     93     .registers 4
     94     .param p0, "a"    # Z
     95     .param p1, "b"    # Z
     96 
     97     .prologue
     98     sget-boolean v0, LSmaliTests;->doThrow:Z
     99     if-eqz v0, :cond_a
    100     new-instance v0, Ljava/lang/Error;
    101     invoke-direct {v0}, Ljava/lang/Error;-><init>()V
    102     throw v0
    103 
    104   :cond_a
    105     # return !a & !b;
    106     xor-int/lit8 v0, p0, 0x1
    107     xor-int/lit8 v1, p1, 0x1
    108     and-int/2addr v0, v1
    109     return v0
    110 .end method
    111 
    112 # Test transformation of Not/Not/Or into And/Not.
    113 
    114 ## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
    115 ## CHECK-DAG:       <<P1:j\d+>>          ParameterValue
    116 ## CHECK-DAG:       <<P2:j\d+>>          ParameterValue
    117 ## CHECK-DAG:       <<Not1:j\d+>>        Not [<<P1>>]
    118 ## CHECK-DAG:       <<Not2:j\d+>>        Not [<<P2>>]
    119 ## CHECK-DAG:       <<Or:j\d+>>          Or [<<Not1>>,<<Not2>>]
    120 ## CHECK-DAG:                            Return [<<Or>>]
    121 
    122 ## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
    123 ## CHECK-DAG:       <<P1:j\d+>>          ParameterValue
    124 ## CHECK-DAG:       <<P2:j\d+>>          ParameterValue
    125 ## CHECK-DAG:       <<And:j\d+>>         And [<<P1>>,<<P2>>]
    126 ## CHECK-DAG:       <<Not:j\d+>>         Not [<<And>>]
    127 ## CHECK-DAG:                            Return [<<Not>>]
    128 
    129 ## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
    130 ## CHECK-DAG:                            Not
    131 ## CHECK-NOT:                            Not
    132 
    133 ## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
    134 ## CHECK-NOT:                            Or
    135 .method public static $opt$noinline$orToAnd(JJ)J
    136     .registers 8
    137     .param p0, "a"    # J
    138     .param p2, "b"    # J
    139 
    140     .prologue
    141     sget-boolean v0, LSmaliTests;->doThrow:Z
    142     if-eqz v0, :cond_a
    143     new-instance v0, Ljava/lang/Error;
    144     invoke-direct {v0}, Ljava/lang/Error;-><init>()V
    145     throw v0
    146 
    147   :cond_a
    148     # return ~a | ~b;
    149     not-long v0, p0
    150     not-long v2, p2
    151     or-long/2addr v0, v2
    152     return-wide v0
    153 .end method
    154 
    155 # Test transformation of Not/Not/Or into Or/And for boolean negations.
    156 # Note that the graph before this instruction simplification pass does not
    157 # contain `HBooleanNot` instructions. This is because this transformation
    158 # follows the optimization of `HSelect` to `HBooleanNot` occurring in the
    159 # same pass.
    160 
    161 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (before)
    162 ## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
    163 ## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
    164 ## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
    165 ## CHECK-DAG:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
    166 ## CHECK-DAG:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
    167 ## CHECK-DAG:       <<Or:i\d+>>          Or [<<NotP1>>,<<NotP2>>]
    168 ## CHECK-DAG:                            Return [<<Or>>]
    169 
    170 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (after)
    171 ## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
    172 ## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
    173 ## CHECK-DAG:       <<And:i\d+>>         And [<<Cond1>>,<<Cond2>>]
    174 ## CHECK-DAG:       <<BooleanNot:z\d+>>  BooleanNot [<<And>>]
    175 ## CHECK-DAG:                            Return [<<BooleanNot>>]
    176 
    177 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
    178 ## CHECK-DAG:                            BooleanNot
    179 ## CHECK-NOT:                            BooleanNot
    180 
    181 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
    182 ## CHECK-NOT:                            Or
    183 .method public static $opt$noinline$booleanOrToAnd(ZZ)Z
    184     .registers 4
    185     .param p0, "a"    # Z
    186     .param p1, "b"    # Z
    187 
    188     .prologue
    189     sget-boolean v0, LSmaliTests;->doThrow:Z
    190     if-eqz v0, :cond_a
    191     new-instance v0, Ljava/lang/Error;
    192     invoke-direct {v0}, Ljava/lang/Error;-><init>()V
    193     throw v0
    194 
    195   :cond_a
    196     # return !a | !b;
    197     xor-int/lit8 v0, p0, 0x1
    198     xor-int/lit8 v1, p1, 0x1
    199     or-int/2addr v0, v1
    200     return v0
    201 .end method
    202 
    203 # Test that the transformation copes with inputs being separated from the
    204 # bitwise operations.
    205 # This is a regression test. The initial logic was inserting the new bitwise
    206 # operation incorrectly.
    207 
    208 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
    209 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
    210 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
    211 ## CHECK-DAG:       <<Cst1:i\d+>>        IntConstant 1
    212 ## CHECK-DAG:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
    213 ## CHECK-DAG:       <<Not1:i\d+>>        Not [<<AddP1>>]
    214 ## CHECK-DAG:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
    215 ## CHECK-DAG:       <<Not2:i\d+>>        Not [<<AddP2>>]
    216 ## CHECK-DAG:       <<Or:i\d+>>          Or [<<Not1>>,<<Not2>>]
    217 ## CHECK-DAG:                            Return [<<Or>>]
    218 
    219 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
    220 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
    221 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
    222 ## CHECK-DAG:       <<Cst1:i\d+>>        IntConstant 1
    223 ## CHECK-DAG:       <<AddP1:i\d+>>       Add [<<P1>>,<<Cst1>>]
    224 ## CHECK-DAG:       <<AddP2:i\d+>>       Add [<<P2>>,<<Cst1>>]
    225 ## CHECK-DAG:       <<And:i\d+>>         And [<<AddP1>>,<<AddP2>>]
    226 ## CHECK-DAG:       <<Not:i\d+>>         Not [<<And>>]
    227 ## CHECK-DAG:                            Return [<<Not>>]
    228 
    229 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
    230 ## CHECK-DAG:                            Not
    231 ## CHECK-NOT:                            Not
    232 
    233 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
    234 ## CHECK-NOT:                            Or
    235 .method public static $opt$noinline$regressInputsAway(II)I
    236     .registers 7
    237     .param p0, "a"    # I
    238     .param p1, "b"    # I
    239 
    240     .prologue
    241     sget-boolean v4, LSmaliTests;->doThrow:Z
    242     if-eqz v4, :cond_a
    243     new-instance v4, Ljava/lang/Error;
    244     invoke-direct {v4}, Ljava/lang/Error;-><init>()V
    245     throw v4
    246 
    247   :cond_a
    248     # int a1 = a + 1;
    249     add-int/lit8 v0, p0, 0x1
    250     # int not_a1 = ~a1;
    251     not-int v2, v0
    252     # int b1 = b + 1;
    253     add-int/lit8 v1, p1, 0x1
    254     # int not_b1 = ~b1;
    255     not-int v3, v1
    256 
    257     # return not_a1 | not_b1
    258     or-int v4, v2, v3
    259     return v4
    260 .end method
    261 
    262 # Test transformation of Not/Not/Xor into Xor.
    263 
    264 # See first note above.
    265 ## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
    266 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
    267 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
    268 ## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
    269 ## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
    270 ## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<Not1>>,<<Not2>>]
    271 ## CHECK-DAG:                            Return [<<Xor>>]
    272 
    273 ## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
    274 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
    275 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
    276 ## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<P1>>,<<P2>>]
    277 ## CHECK-DAG:                            Return [<<Xor>>]
    278 
    279 ## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
    280 ## CHECK-NOT:                            Not
    281 .method public static $opt$noinline$notXorToXor(II)I
    282     .registers 4
    283     .param p0, "a"    # I
    284     .param p1, "b"    # I
    285 
    286     .prologue
    287     sget-boolean v0, LSmaliTests;->doThrow:Z
    288     if-eqz v0, :cond_a
    289     new-instance v0, Ljava/lang/Error;
    290     invoke-direct {v0}, Ljava/lang/Error;-><init>()V
    291     throw v0
    292 
    293   :cond_a
    294     # return ~a ^ ~b;
    295     not-int v0, p0
    296     not-int v1, p1
    297     xor-int/2addr v0, v1
    298     return v0
    299 .end method
    300 
    301 # Test transformation of Not/Not/Xor into Xor for boolean negations.
    302 # Note that the graph before this instruction simplification pass does not
    303 # contain `HBooleanNot` instructions. This is because this transformation
    304 # follows the optimization of `HSelect` to `HBooleanNot` occurring in the
    305 # same pass.
    306 
    307 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (before)
    308 ## CHECK-DAG:       <<P1:z\d+>>          ParameterValue
    309 ## CHECK-DAG:       <<P2:z\d+>>          ParameterValue
    310 ## CHECK-DAG:       <<Const1:i\d+>>      IntConstant 1
    311 ## CHECK-DAG:       <<NotP1:i\d+>>       Xor [<<P1>>,<<Const1>>]
    312 ## CHECK-DAG:       <<NotP2:i\d+>>       Xor [<<P2>>,<<Const1>>]
    313 ## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<NotP1>>,<<NotP2>>]
    314 ## CHECK-DAG:                            Return [<<Xor>>]
    315 
    316 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (after)
    317 ## CHECK-DAG:       <<Cond1:z\d+>>       ParameterValue
    318 ## CHECK-DAG:       <<Cond2:z\d+>>       ParameterValue
    319 ## CHECK-DAG:       <<Xor:i\d+>>         Xor [<<Cond1>>,<<Cond2>>]
    320 ## CHECK-DAG:                            Return [<<Xor>>]
    321 
    322 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
    323 ## CHECK-NOT:                            BooleanNot
    324 .method public static $opt$noinline$booleanNotXorToXor(ZZ)Z
    325     .registers 4
    326     .param p0, "a"    # Z
    327     .param p1, "b"    # Z
    328 
    329     .prologue
    330     sget-boolean v0, LSmaliTests;->doThrow:Z
    331     if-eqz v0, :cond_a
    332     new-instance v0, Ljava/lang/Error;
    333     invoke-direct {v0}, Ljava/lang/Error;-><init>()V
    334     throw v0
    335 
    336   :cond_a
    337     # return !a ^ !b;
    338     xor-int/lit8 v0, p0, 0x1
    339     xor-int/lit8 v1, p1, 0x1
    340     xor-int/2addr v0, v1
    341     return v0
    342 .end method
    343 
    344 # Check that no transformation is done when one Not has multiple uses.
    345 
    346 ## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
    347 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
    348 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
    349 ## CHECK-DAG:       <<One:i\d+>>         IntConstant 1
    350 ## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
    351 ## CHECK-DAG:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
    352 ## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
    353 ## CHECK-DAG:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
    354 ## CHECK-DAG:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
    355 ## CHECK-DAG:                            Return [<<Add>>]
    356 
    357 ## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
    358 ## CHECK-DAG:       <<P1:i\d+>>          ParameterValue
    359 ## CHECK-DAG:       <<P2:i\d+>>          ParameterValue
    360 ## CHECK-DAG:       <<One:i\d+>>         IntConstant 1
    361 ## CHECK-DAG:       <<Not2:i\d+>>        Not [<<P2>>]
    362 ## CHECK-DAG:       <<And2:i\d+>>        And [<<Not2>>,<<One>>]
    363 ## CHECK-DAG:       <<Not1:i\d+>>        Not [<<P1>>]
    364 ## CHECK-DAG:       <<And1:i\d+>>        And [<<Not1>>,<<Not2>>]
    365 ## CHECK-DAG:       <<Add:i\d+>>         Add [<<And2>>,<<And1>>]
    366 ## CHECK-DAG:                            Return [<<Add>>]
    367 
    368 ## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
    369 ## CHECK-NOT:                            Or
    370 .method public static $opt$noinline$notMultipleUses(II)I
    371     .registers 5
    372     .param p0, "a"    # I
    373     .param p1, "b"    # I
    374 
    375     .prologue
    376     sget-boolean v1, LSmaliTests;->doThrow:Z
    377     if-eqz v1, :cond_a
    378     new-instance v1, Ljava/lang/Error;
    379     invoke-direct {v1}, Ljava/lang/Error;-><init>()V
    380     throw v1
    381 
    382   :cond_a
    383     # int tmp = ~b;
    384     not-int v0, p1
    385     # return (tmp & 0x1) + (~a & tmp);
    386     and-int/lit8 v1, v0, 0x1
    387     not-int v2, p0
    388     and-int/2addr v2, v0
    389     add-int/2addr v1, v2
    390     return v1
    391 .end method
    392 
    393 # static fields
    394 .field static doThrow:Z # boolean
    395 
    396 # direct methods
    397 .method static constructor <clinit>()V
    398     .registers 1
    399 
    400     .prologue
    401     # doThrow = false
    402     const/4 v0, 0x0
    403     sput-boolean v0, LSmaliTests;->doThrow:Z
    404     return-void
    405 .end method
    406