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