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