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 407 408 # Test transformation of Not/Not/And into Or/Not. 409 410 # Note: before the instruction_simplifier pass, Xor's are used instead of 411 # Not's (the simplification happens during the same pass). 412 ## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (before) 413 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 414 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 415 ## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 416 ## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] 417 ## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] 418 ## CHECK-DAG: <<And:i\d+>> And [<<Not1>>,<<Not2>>] 419 ## CHECK-DAG: Return [<<And>>] 420 421 ## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after) 422 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 423 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 424 ## CHECK-DAG: <<Or:i\d+>> Or [<<P1>>,<<P2>>] 425 ## CHECK-DAG: <<Not:i\d+>> Not [<<Or>>] 426 ## CHECK-DAG: Return [<<Not>>] 427 428 ## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after) 429 ## CHECK-DAG: Not 430 ## CHECK-NOT: Not 431 432 ## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after) 433 ## CHECK-NOT: And 434 435 # Original java source: 436 # 437 # public static int $opt$noinline$andToOr(int a, int b) { 438 # if (doThrow) throw new Error(); 439 # return ~a & ~b; 440 # } 441 442 .method public static $opt$noinline$andToOrV2(II)I 443 .registers 4 444 .param p0, "a" # I 445 .param p1, "b" # I 446 447 .prologue 448 .line 85 449 sget-boolean v0, LMain;->doThrow:Z 450 451 if-eqz v0, :cond_a 452 453 new-instance v0, Ljava/lang/Error; 454 455 invoke-direct {v0}, Ljava/lang/Error;-><init>()V 456 457 throw v0 458 459 .line 86 460 :cond_a 461 xor-int/lit8 v0, p0, -0x1 462 463 xor-int/lit8 v1, p1, -0x1 464 465 and-int/2addr v0, v1 466 467 return v0 468 .end method 469 470 471 # Test transformation of Not/Not/And into Or/Not for boolean negations. 472 # Note that the graph before this instruction simplification pass does not 473 # contain `HBooleanNot` instructions. This is because this transformation 474 # follows the optimization of `HSelect` to `HBooleanNot` occurring in the 475 # same pass. 476 477 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (before) 478 ## CHECK-DAG: <<P1:z\d+>> ParameterValue 479 ## CHECK-DAG: <<P2:z\d+>> ParameterValue 480 ## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 481 ## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 482 ## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>] 483 ## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>] 484 ## CHECK-DAG: <<And:i\d+>> And [<<Select1>>,<<Select2>>] 485 ## CHECK-DAG: Return [<<And>>] 486 487 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (after) 488 ## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 489 ## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 490 ## CHECK-DAG: <<Or:i\d+>> Or [<<Cond1>>,<<Cond2>>] 491 ## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<Or>>] 492 ## CHECK-DAG: Return [<<BooleanNot>>] 493 494 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after) 495 ## CHECK-DAG: BooleanNot 496 ## CHECK-NOT: BooleanNot 497 498 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after) 499 ## CHECK-NOT: And 500 501 # Original java source: 502 # 503 # public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) { 504 # if (doThrow) throw new Error(); 505 # return !a & !b; 506 # } 507 508 .method public static $opt$noinline$booleanAndToOrV2(ZZ)Z 509 .registers 5 510 .param p0, "a" # Z 511 .param p1, "b" # Z 512 513 .prologue 514 const/4 v0, 0x1 515 516 const/4 v1, 0x0 517 518 .line 122 519 sget-boolean v2, LMain;->doThrow:Z 520 521 if-eqz v2, :cond_c 522 523 new-instance v0, Ljava/lang/Error; 524 525 invoke-direct {v0}, Ljava/lang/Error;-><init>()V 526 527 throw v0 528 529 .line 123 530 :cond_c 531 if-nez p0, :cond_13 532 533 move v2, v0 534 535 :goto_f 536 if-nez p1, :cond_15 537 538 :goto_11 539 and-int/2addr v0, v2 540 541 return v0 542 543 :cond_13 544 move v2, v1 545 546 goto :goto_f 547 548 :cond_15 549 move v0, v1 550 551 goto :goto_11 552 .end method 553 554 555 # Test transformation of Not/Not/Or into And/Not. 556 557 # See note above. 558 # The second Xor has its arguments reversed for no obvious reason. 559 ## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (before) 560 ## CHECK-DAG: <<P1:j\d+>> ParameterValue 561 ## CHECK-DAG: <<P2:j\d+>> ParameterValue 562 ## CHECK-DAG: <<CstM1:j\d+>> LongConstant -1 563 ## CHECK-DAG: <<Not1:j\d+>> Xor [<<P1>>,<<CstM1>>] 564 ## CHECK-DAG: <<Not2:j\d+>> Xor [<<CstM1>>,<<P2>>] 565 ## CHECK-DAG: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>] 566 ## CHECK-DAG: Return [<<Or>>] 567 568 ## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after) 569 ## CHECK-DAG: <<P1:j\d+>> ParameterValue 570 ## CHECK-DAG: <<P2:j\d+>> ParameterValue 571 ## CHECK-DAG: <<And:j\d+>> And [<<P1>>,<<P2>>] 572 ## CHECK-DAG: <<Not:j\d+>> Not [<<And>>] 573 ## CHECK-DAG: Return [<<Not>>] 574 575 ## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after) 576 ## CHECK-DAG: Not 577 ## CHECK-NOT: Not 578 579 ## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after) 580 ## CHECK-NOT: Or 581 582 # Original java source: 583 # 584 # public static long $opt$noinline$orToAnd(long a, long b) { 585 # if (doThrow) throw new Error(); 586 # return ~a | ~b; 587 # } 588 589 .method public static $opt$noinline$orToAndV2(JJ)J 590 .registers 8 591 .param p0, "a" # J 592 .param p2, "b" # J 593 594 .prologue 595 const-wide/16 v2, -0x1 596 597 .line 156 598 sget-boolean v0, LMain;->doThrow:Z 599 600 if-eqz v0, :cond_c 601 602 new-instance v0, Ljava/lang/Error; 603 604 invoke-direct {v0}, Ljava/lang/Error;-><init>()V 605 606 throw v0 607 608 .line 157 609 :cond_c 610 xor-long v0, p0, v2 611 612 xor-long/2addr v2, p2 613 614 or-long/2addr v0, v2 615 616 return-wide v0 617 .end method 618 619 # Test transformation of Not/Not/Or into Or/And for boolean negations. 620 # Note that the graph before this instruction simplification pass does not 621 # contain `HBooleanNot` instructions. This is because this transformation 622 # follows the optimization of `HSelect` to `HBooleanNot` occurring in the 623 # same pass. 624 625 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (before) 626 ## CHECK-DAG: <<P1:z\d+>> ParameterValue 627 ## CHECK-DAG: <<P2:z\d+>> ParameterValue 628 ## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 629 ## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 630 ## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>] 631 ## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>] 632 ## CHECK-DAG: <<Or:i\d+>> Or [<<Select1>>,<<Select2>>] 633 ## CHECK-DAG: Return [<<Or>>] 634 635 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (after) 636 ## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 637 ## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 638 ## CHECK-DAG: <<And:i\d+>> And [<<Cond1>>,<<Cond2>>] 639 ## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<And>>] 640 ## CHECK-DAG: Return [<<BooleanNot>>] 641 642 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after) 643 ## CHECK-DAG: BooleanNot 644 ## CHECK-NOT: BooleanNot 645 646 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after) 647 ## CHECK-NOT: Or 648 649 # Original java source: 650 # 651 # public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) { 652 # if (doThrow) throw new Error(); 653 # return !a | !b; 654 # } 655 656 .method public static $opt$noinline$booleanOrToAndV2(ZZ)Z 657 .registers 5 658 .param p0, "a" # Z 659 .param p1, "b" # Z 660 661 .prologue 662 const/4 v0, 0x1 663 664 const/4 v1, 0x0 665 666 .line 193 667 sget-boolean v2, LMain;->doThrow:Z 668 669 if-eqz v2, :cond_c 670 671 new-instance v0, Ljava/lang/Error; 672 673 invoke-direct {v0}, Ljava/lang/Error;-><init>()V 674 675 throw v0 676 677 .line 194 678 :cond_c 679 if-nez p0, :cond_13 680 681 move v2, v0 682 683 :goto_f 684 if-nez p1, :cond_15 685 686 :goto_11 687 or-int/2addr v0, v2 688 689 return v0 690 691 :cond_13 692 move v2, v1 693 694 goto :goto_f 695 696 :cond_15 697 move v0, v1 698 699 goto :goto_11 700 .end method 701 702 703 # Test that the transformation copes with inputs being separated from the 704 # bitwise operations. 705 # This is a regression test. The initial logic was inserting the new bitwise 706 # operation incorrectly. 707 708 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (before) 709 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 710 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 711 ## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 712 ## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 713 ## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] 714 ## CHECK-DAG: <<Not1:i\d+>> Xor [<<AddP1>>,<<CstM1>>] 715 ## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] 716 ## CHECK-DAG: <<Not2:i\d+>> Xor [<<AddP2>>,<<CstM1>>] 717 ## CHECK-DAG: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>] 718 ## CHECK-DAG: Return [<<Or>>] 719 720 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after) 721 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 722 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 723 ## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 724 ## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] 725 ## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] 726 ## CHECK-DAG: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>] 727 ## CHECK-DAG: <<Not:i\d+>> Not [<<And>>] 728 ## CHECK-DAG: Return [<<Not>>] 729 730 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after) 731 ## CHECK-DAG: Not 732 ## CHECK-NOT: Not 733 734 ## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after) 735 ## CHECK-NOT: Or 736 737 # Original java source: 738 # 739 # public static int $opt$noinline$regressInputsAway(int a, int b) { 740 # if (doThrow) throw new Error(); 741 # int a1 = a + 1; 742 # int not_a1 = ~a1; 743 # int b1 = b + 1; 744 # int not_b1 = ~b1; 745 # return not_a1 | not_b1; 746 # } 747 748 .method public static $opt$noinline$regressInputsAwayV2(II)I 749 .registers 7 750 .param p0, "a" # I 751 .param p1, "b" # I 752 753 .prologue 754 .line 234 755 sget-boolean v4, LMain;->doThrow:Z 756 757 if-eqz v4, :cond_a 758 759 new-instance v4, Ljava/lang/Error; 760 761 invoke-direct {v4}, Ljava/lang/Error;-><init>()V 762 763 throw v4 764 765 .line 235 766 :cond_a 767 add-int/lit8 v0, p0, 0x1 768 769 .line 236 770 .local v0, "a1":I 771 xor-int/lit8 v2, v0, -0x1 772 773 .line 237 774 .local v2, "not_a1":I 775 add-int/lit8 v1, p1, 0x1 776 777 .line 238 778 .local v1, "b1":I 779 xor-int/lit8 v3, v1, -0x1 780 781 .line 239 782 .local v3, "not_b1":I 783 or-int v4, v2, v3 784 785 return v4 786 .end method 787 788 789 # Test transformation of Not/Not/Xor into Xor. 790 791 # See first note above. 792 ## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (before) 793 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 794 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 795 ## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 796 ## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] 797 ## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] 798 ## CHECK-DAG: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>] 799 ## CHECK-DAG: Return [<<Xor>>] 800 801 ## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after) 802 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 803 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 804 ## CHECK-DAG: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>] 805 ## CHECK-DAG: Return [<<Xor>>] 806 807 ## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after) 808 ## CHECK-NOT: Not 809 810 # Original java source: 811 # 812 # public static int $opt$noinline$notXorToXor(int a, int b) { 813 # if (doThrow) throw new Error(); 814 # return ~a ^ ~b; 815 # } 816 817 .method public static $opt$noinline$notXorToXorV2(II)I 818 .registers 4 819 .param p0, "a" # I 820 .param p1, "b" # I 821 822 .prologue 823 .line 266 824 sget-boolean v0, LMain;->doThrow:Z 825 826 if-eqz v0, :cond_a 827 828 new-instance v0, Ljava/lang/Error; 829 830 invoke-direct {v0}, Ljava/lang/Error;-><init>()V 831 832 throw v0 833 834 .line 267 835 :cond_a 836 xor-int/lit8 v0, p0, -0x1 837 838 xor-int/lit8 v1, p1, -0x1 839 840 xor-int/2addr v0, v1 841 842 return v0 843 .end method 844 845 846 # Test transformation of Not/Not/Xor into Xor for boolean negations. 847 # Note that the graph before this instruction simplification pass does not 848 # contain `HBooleanNot` instructions. This is because this transformation 849 # follows the optimization of `HSelect` to `HBooleanNot` occurring in the 850 # same pass. 851 852 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (before) 853 ## CHECK-DAG: <<P1:z\d+>> ParameterValue 854 ## CHECK-DAG: <<P2:z\d+>> ParameterValue 855 ## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 856 ## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 857 ## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>] 858 ## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>] 859 ## CHECK-DAG: <<Xor:i\d+>> Xor [<<Select1>>,<<Select2>>] 860 ## CHECK-DAG: Return [<<Xor>>] 861 862 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (after) 863 ## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 864 ## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 865 ## CHECK-DAG: <<Xor:i\d+>> Xor [<<Cond1>>,<<Cond2>>] 866 ## CHECK-DAG: Return [<<Xor>>] 867 868 ## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_bce (after) 869 ## CHECK-NOT: BooleanNot 870 871 # Original java source: 872 # 873 # public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) { 874 # if (doThrow) throw new Error(); 875 # return !a ^ !b; 876 # } 877 878 .method public static $opt$noinline$booleanNotXorToXorV2(ZZ)Z 879 .registers 5 880 .param p0, "a" # Z 881 .param p1, "b" # Z 882 883 .prologue 884 const/4 v0, 0x1 885 886 const/4 v1, 0x0 887 888 .line 298 889 sget-boolean v2, LMain;->doThrow:Z 890 891 if-eqz v2, :cond_c 892 893 new-instance v0, Ljava/lang/Error; 894 895 invoke-direct {v0}, Ljava/lang/Error;-><init>()V 896 897 throw v0 898 899 .line 299 900 :cond_c 901 if-nez p0, :cond_13 902 903 move v2, v0 904 905 :goto_f 906 if-nez p1, :cond_15 907 908 :goto_11 909 xor-int/2addr v0, v2 910 911 return v0 912 913 :cond_13 914 move v2, v1 915 916 goto :goto_f 917 918 :cond_15 919 move v0, v1 920 921 goto :goto_11 922 .end method 923 924 925 # Check that no transformation is done when one Not has multiple uses. 926 927 ## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (before) 928 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 929 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 930 ## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 931 ## CHECK-DAG: <<One:i\d+>> IntConstant 1 932 ## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] 933 ## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>] 934 ## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] 935 ## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] 936 ## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>] 937 ## CHECK-DAG: Return [<<Add>>] 938 939 ## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after) 940 ## CHECK-DAG: <<P1:i\d+>> ParameterValue 941 ## CHECK-DAG: <<P2:i\d+>> ParameterValue 942 ## CHECK-DAG: <<One:i\d+>> IntConstant 1 943 ## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>] 944 ## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>] 945 ## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>] 946 ## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] 947 ## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>] 948 ## CHECK-DAG: Return [<<Add>>] 949 950 ## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after) 951 ## CHECK-NOT: Or 952 953 # Original java source: 954 # 955 # public static int $opt$noinline$notMultipleUses(int a, int b) { 956 # if (doThrow) throw new Error(); 957 # int tmp = ~b; 958 # return (tmp & 0x1) + (~a & tmp); 959 # } 960 961 .method public static $opt$noinline$notMultipleUsesV2(II)I 962 .registers 5 963 .param p0, "a" # I 964 .param p1, "b" # I 965 966 .prologue 967 .line 333 968 sget-boolean v1, LMain;->doThrow:Z 969 970 if-eqz v1, :cond_a 971 972 new-instance v1, Ljava/lang/Error; 973 974 invoke-direct {v1}, Ljava/lang/Error;-><init>()V 975 976 throw v1 977 978 .line 334 979 :cond_a 980 xor-int/lit8 v0, p1, -0x1 981 982 .line 335 983 .local v0, "tmp":I 984 and-int/lit8 v1, v0, 0x1 985 986 xor-int/lit8 v2, p0, -0x1 987 988 and-int/2addr v2, v0 989 990 add-int/2addr v1, v2 991 992 return v1 993 .end method 994