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 # return ~a & ~b; 50 not-int v0, p0 51 not-int v1, p1 52 and-int/2addr v0, v1 53 54 return v0 55.end method 56 57# Test transformation of Not/Not/And into Or/Not for boolean negations. 58# Note that the graph before this instruction simplification pass does not 59# contain `HBooleanNot` instructions. This is because this transformation 60# follows the optimization of `HSelect` to `HBooleanNot` occurring in the 61# same pass. 62 63## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (before) 64## CHECK-DAG: <<P1:z\d+>> ParameterValue 65## CHECK-DAG: <<P2:z\d+>> ParameterValue 66## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 67## CHECK-DAG: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>] 68## CHECK-DAG: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>] 69## CHECK-DAG: <<And:i\d+>> And [<<NotP1>>,<<NotP2>>] 70## CHECK-DAG: Return [<<And>>] 71 72## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (after) 73## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 74## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 75## CHECK-DAG: <<Or:i\d+>> Or [<<Cond1>>,<<Cond2>>] 76## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<Or>>] 77## CHECK-DAG: Return [<<BooleanNot>>] 78 79## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after) 80## CHECK-DAG: BooleanNot 81## CHECK-NOT: BooleanNot 82 83## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after) 84## CHECK-NOT: And 85.method public static $opt$noinline$booleanAndToOr(ZZ)Z 86 .registers 4 87 .param p0, "a" # Z 88 .param p1, "b" # Z 89 90 .prologue 91 # return !a & !b; 92 xor-int/lit8 v0, p0, 0x1 93 xor-int/lit8 v1, p1, 0x1 94 and-int/2addr v0, v1 95 return v0 96.end method 97 98# Test transformation of Not/Not/Or into And/Not. 99 100## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (before) 101## CHECK-DAG: <<P1:j\d+>> ParameterValue 102## CHECK-DAG: <<P2:j\d+>> ParameterValue 103## CHECK-DAG: <<Not1:j\d+>> Not [<<P1>>] 104## CHECK-DAG: <<Not2:j\d+>> Not [<<P2>>] 105## CHECK-DAG: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>] 106## CHECK-DAG: Return [<<Or>>] 107 108## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after) 109## CHECK-DAG: <<P1:j\d+>> ParameterValue 110## CHECK-DAG: <<P2:j\d+>> ParameterValue 111## CHECK-DAG: <<And:j\d+>> And [<<P1>>,<<P2>>] 112## CHECK-DAG: <<Not:j\d+>> Not [<<And>>] 113## CHECK-DAG: Return [<<Not>>] 114 115## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after) 116## CHECK-DAG: Not 117## CHECK-NOT: Not 118 119## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after) 120## CHECK-NOT: Or 121.method public static $opt$noinline$orToAnd(JJ)J 122 .registers 8 123 .param p0, "a" # J 124 .param p2, "b" # J 125 126 .prologue 127 # return ~a | ~b; 128 not-long v0, p0 129 not-long v2, p2 130 or-long/2addr v0, v2 131 return-wide v0 132.end method 133 134# Test transformation of Not/Not/Or into Or/And for boolean negations. 135# Note that the graph before this instruction simplification pass does not 136# contain `HBooleanNot` instructions. This is because this transformation 137# follows the optimization of `HSelect` to `HBooleanNot` occurring in the 138# same pass. 139 140## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (before) 141## CHECK-DAG: <<P1:z\d+>> ParameterValue 142## CHECK-DAG: <<P2:z\d+>> ParameterValue 143## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 144## CHECK-DAG: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>] 145## CHECK-DAG: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>] 146## CHECK-DAG: <<Or:i\d+>> Or [<<NotP1>>,<<NotP2>>] 147## CHECK-DAG: Return [<<Or>>] 148 149## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (after) 150## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 151## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 152## CHECK-DAG: <<And:i\d+>> And [<<Cond1>>,<<Cond2>>] 153## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<And>>] 154## CHECK-DAG: Return [<<BooleanNot>>] 155 156## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after) 157## CHECK-DAG: BooleanNot 158## CHECK-NOT: BooleanNot 159 160## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after) 161## CHECK-NOT: Or 162.method public static $opt$noinline$booleanOrToAnd(ZZ)Z 163 .registers 4 164 .param p0, "a" # Z 165 .param p1, "b" # Z 166 167 .prologue 168 # return !a | !b; 169 xor-int/lit8 v0, p0, 0x1 170 xor-int/lit8 v1, p1, 0x1 171 or-int/2addr v0, v1 172 return v0 173.end method 174 175# Test that the transformation copes with inputs being separated from the 176# bitwise operations. 177# This is a regression test. The initial logic was inserting the new bitwise 178# operation incorrectly. 179 180## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before) 181## CHECK-DAG: <<P1:i\d+>> ParameterValue 182## CHECK-DAG: <<P2:i\d+>> ParameterValue 183## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 184## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] 185## CHECK-DAG: <<Not1:i\d+>> Not [<<AddP1>>] 186## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] 187## CHECK-DAG: <<Not2:i\d+>> Not [<<AddP2>>] 188## CHECK-DAG: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>] 189## CHECK-DAG: Return [<<Or>>] 190 191## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after) 192## CHECK-DAG: <<P1:i\d+>> ParameterValue 193## CHECK-DAG: <<P2:i\d+>> ParameterValue 194## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 195## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] 196## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] 197## CHECK-DAG: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>] 198## CHECK-DAG: <<Not:i\d+>> Not [<<And>>] 199## CHECK-DAG: Return [<<Not>>] 200 201## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after) 202## CHECK-DAG: Not 203## CHECK-NOT: Not 204 205## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after) 206## CHECK-NOT: Or 207.method public static $opt$noinline$regressInputsAway(II)I 208 .registers 7 209 .param p0, "a" # I 210 .param p1, "b" # I 211 212 .prologue 213 # int a1 = a + 1; 214 add-int/lit8 v0, p0, 0x1 215 # int not_a1 = ~a1; 216 not-int v2, v0 217 # int b1 = b + 1; 218 add-int/lit8 v1, p1, 0x1 219 # int not_b1 = ~b1; 220 not-int v3, v1 221 222 # return not_a1 | not_b1 223 or-int v4, v2, v3 224 return v4 225.end method 226 227# Test transformation of Not/Not/Xor into Xor. 228 229# See first note above. 230## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before) 231## CHECK-DAG: <<P1:i\d+>> ParameterValue 232## CHECK-DAG: <<P2:i\d+>> ParameterValue 233## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>] 234## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>] 235## CHECK-DAG: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>] 236## CHECK-DAG: Return [<<Xor>>] 237 238## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after) 239## CHECK-DAG: <<P1:i\d+>> ParameterValue 240## CHECK-DAG: <<P2:i\d+>> ParameterValue 241## CHECK-DAG: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>] 242## CHECK-DAG: Return [<<Xor>>] 243 244## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after) 245## CHECK-NOT: Not 246.method public static $opt$noinline$notXorToXor(II)I 247 .registers 4 248 .param p0, "a" # I 249 .param p1, "b" # I 250 251 .prologue 252 # return ~a ^ ~b; 253 not-int v0, p0 254 not-int v1, p1 255 xor-int/2addr v0, v1 256 return v0 257.end method 258 259# Test transformation of Not/Not/Xor into Xor for boolean negations. 260# Note that the graph before this instruction simplification pass does not 261# contain `HBooleanNot` instructions. This is because this transformation 262# follows the optimization of `HSelect` to `HBooleanNot` occurring in the 263# same pass. 264 265## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (before) 266## CHECK-DAG: <<P1:z\d+>> ParameterValue 267## CHECK-DAG: <<P2:z\d+>> ParameterValue 268## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 269## CHECK-DAG: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>] 270## CHECK-DAG: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>] 271## CHECK-DAG: <<Xor:i\d+>> Xor [<<NotP1>>,<<NotP2>>] 272## CHECK-DAG: Return [<<Xor>>] 273 274## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (after) 275## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 276## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 277## CHECK-DAG: <<Xor:i\d+>> Xor [<<Cond1>>,<<Cond2>>] 278## CHECK-DAG: Return [<<Xor>>] 279 280## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after) 281## CHECK-NOT: BooleanNot 282.method public static $opt$noinline$booleanNotXorToXor(ZZ)Z 283 .registers 4 284 .param p0, "a" # Z 285 .param p1, "b" # Z 286 287 .prologue 288 # return !a ^ !b; 289 xor-int/lit8 v0, p0, 0x1 290 xor-int/lit8 v1, p1, 0x1 291 xor-int/2addr v0, v1 292 return v0 293.end method 294 295# Check that no transformation is done when one Not has multiple uses. 296 297## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before) 298## CHECK-DAG: <<P1:i\d+>> ParameterValue 299## CHECK-DAG: <<P2:i\d+>> ParameterValue 300## CHECK-DAG: <<One:i\d+>> IntConstant 1 301## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>] 302## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>] 303## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>] 304## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] 305## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>] 306## CHECK-DAG: Return [<<Add>>] 307 308## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after) 309## CHECK-DAG: <<P1:i\d+>> ParameterValue 310## CHECK-DAG: <<P2:i\d+>> ParameterValue 311## CHECK-DAG: <<One:i\d+>> IntConstant 1 312## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>] 313## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>] 314## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>] 315## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] 316## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>] 317## CHECK-DAG: Return [<<Add>>] 318 319## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after) 320## CHECK-NOT: Or 321.method public static $opt$noinline$notMultipleUses(II)I 322 .registers 5 323 .param p0, "a" # I 324 .param p1, "b" # I 325 326 .prologue 327 # int tmp = ~b; 328 not-int v0, p1 329 # return (tmp & 0x1) + (~a & tmp); 330 and-int/lit8 v1, v0, 0x1 331 not-int v2, p0 332 and-int/2addr v2, v0 333 add-int/2addr v1, v2 334 return v1 335.end method 336 337 338# Test transformation of Not/Not/And into Or/Not. 339 340# Note: before the instruction_simplifier pass, Xor's are used instead of 341# Not's (the simplification happens during the same pass). 342## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (before) 343## CHECK-DAG: <<P1:i\d+>> ParameterValue 344## CHECK-DAG: <<P2:i\d+>> ParameterValue 345## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 346## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] 347## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] 348## CHECK-DAG: <<And:i\d+>> And [<<Not1>>,<<Not2>>] 349## CHECK-DAG: Return [<<And>>] 350 351## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after) 352## CHECK-DAG: <<P1:i\d+>> ParameterValue 353## CHECK-DAG: <<P2:i\d+>> ParameterValue 354## CHECK-DAG: <<Or:i\d+>> Or [<<P1>>,<<P2>>] 355## CHECK-DAG: <<Not:i\d+>> Not [<<Or>>] 356## CHECK-DAG: Return [<<Not>>] 357 358## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after) 359## CHECK-DAG: Not 360## CHECK-NOT: Not 361 362## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after) 363## CHECK-NOT: And 364 365# Original java source: 366# 367# public static int $opt$noinline$andToOr(int a, int b) { 368# return ~a & ~b; 369# } 370 371.method public static $opt$noinline$andToOrV2(II)I 372 .registers 4 373 .param p0, "a" # I 374 .param p1, "b" # I 375 376 .prologue 377 .line 85 378 xor-int/lit8 v0, p0, -0x1 379 380 xor-int/lit8 v1, p1, -0x1 381 382 and-int/2addr v0, v1 383 384 return v0 385.end method 386 387 388# Test transformation of Not/Not/And into Or/Not for boolean negations. 389# Note that the graph before this instruction simplification pass does not 390# contain `HBooleanNot` instructions. This is because this transformation 391# follows the optimization of `HSelect` to `HBooleanNot` occurring in the 392# same pass. 393 394## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (before) 395## CHECK-DAG: <<P1:z\d+>> ParameterValue 396## CHECK-DAG: <<P2:z\d+>> ParameterValue 397## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 398## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 399## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>] 400## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>] 401## CHECK-DAG: <<And:i\d+>> And [<<Select1>>,<<Select2>>] 402## CHECK-DAG: Return [<<And>>] 403 404## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (after) 405## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 406## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 407## CHECK-DAG: <<Or:i\d+>> Or [<<Cond1>>,<<Cond2>>] 408## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<Or>>] 409## CHECK-DAG: Return [<<BooleanNot>>] 410 411## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after) 412## CHECK-DAG: BooleanNot 413## CHECK-NOT: BooleanNot 414 415## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after) 416## CHECK-NOT: And 417 418# Original java source: 419# 420# public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) { 421# return !a & !b; 422# } 423 424.method public static $opt$noinline$booleanAndToOrV2(ZZ)Z 425 .registers 5 426 .param p0, "a" # Z 427 .param p1, "b" # Z 428 429 .prologue 430 const/4 v0, 0x1 431 432 const/4 v1, 0x0 433 434 .line 122 435 if-nez p0, :cond_13 436 437 move v2, v0 438 439 :goto_f 440 if-nez p1, :cond_15 441 442 :goto_11 443 and-int/2addr v0, v2 444 445 return v0 446 447 :cond_13 448 move v2, v1 449 450 goto :goto_f 451 452 :cond_15 453 move v0, v1 454 455 goto :goto_11 456.end method 457 458 459# Test transformation of Not/Not/Or into And/Not. 460 461# See note above. 462# The second Xor has its arguments reversed for no obvious reason. 463## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (before) 464## CHECK-DAG: <<P1:j\d+>> ParameterValue 465## CHECK-DAG: <<P2:j\d+>> ParameterValue 466## CHECK-DAG: <<CstM1:j\d+>> LongConstant -1 467## CHECK-DAG: <<Not1:j\d+>> Xor [<<P1>>,<<CstM1>>] 468## CHECK-DAG: <<Not2:j\d+>> Xor [<<CstM1>>,<<P2>>] 469## CHECK-DAG: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>] 470## CHECK-DAG: Return [<<Or>>] 471 472## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after) 473## CHECK-DAG: <<P1:j\d+>> ParameterValue 474## CHECK-DAG: <<P2:j\d+>> ParameterValue 475## CHECK-DAG: <<And:j\d+>> And [<<P1>>,<<P2>>] 476## CHECK-DAG: <<Not:j\d+>> Not [<<And>>] 477## CHECK-DAG: Return [<<Not>>] 478 479## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after) 480## CHECK-DAG: Not 481## CHECK-NOT: Not 482 483## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after) 484## CHECK-NOT: Or 485 486# Original java source: 487# 488# public static long $opt$noinline$orToAnd(long a, long b) { 489# return ~a | ~b; 490# } 491 492.method public static $opt$noinline$orToAndV2(JJ)J 493 .registers 8 494 .param p0, "a" # J 495 .param p2, "b" # J 496 497 .prologue 498 const-wide/16 v2, -0x1 499 500 .line 156 501 xor-long v0, p0, v2 502 503 xor-long/2addr v2, p2 504 505 or-long/2addr v0, v2 506 507 return-wide v0 508.end method 509 510# Test transformation of Not/Not/Or into Or/And for boolean negations. 511# Note that the graph before this instruction simplification pass does not 512# contain `HBooleanNot` instructions. This is because this transformation 513# follows the optimization of `HSelect` to `HBooleanNot` occurring in the 514# same pass. 515 516## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (before) 517## CHECK-DAG: <<P1:z\d+>> ParameterValue 518## CHECK-DAG: <<P2:z\d+>> ParameterValue 519## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 520## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 521## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>] 522## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>] 523## CHECK-DAG: <<Or:i\d+>> Or [<<Select1>>,<<Select2>>] 524## CHECK-DAG: Return [<<Or>>] 525 526## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (after) 527## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 528## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 529## CHECK-DAG: <<And:i\d+>> And [<<Cond1>>,<<Cond2>>] 530## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<And>>] 531## CHECK-DAG: Return [<<BooleanNot>>] 532 533## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after) 534## CHECK-DAG: BooleanNot 535## CHECK-NOT: BooleanNot 536 537## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after) 538## CHECK-NOT: Or 539 540# Original java source: 541# 542# public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) { 543# return !a | !b; 544# } 545 546.method public static $opt$noinline$booleanOrToAndV2(ZZ)Z 547 .registers 5 548 .param p0, "a" # Z 549 .param p1, "b" # Z 550 551 .prologue 552 const/4 v0, 0x1 553 554 const/4 v1, 0x0 555 556 .line 193 557 if-nez p0, :cond_13 558 559 move v2, v0 560 561 :goto_f 562 if-nez p1, :cond_15 563 564 :goto_11 565 or-int/2addr v0, v2 566 567 return v0 568 569 :cond_13 570 move v2, v1 571 572 goto :goto_f 573 574 :cond_15 575 move v0, v1 576 577 goto :goto_11 578.end method 579 580 581# Test that the transformation copes with inputs being separated from the 582# bitwise operations. 583# This is a regression test. The initial logic was inserting the new bitwise 584# operation incorrectly. 585 586## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (before) 587## CHECK-DAG: <<P1:i\d+>> ParameterValue 588## CHECK-DAG: <<P2:i\d+>> ParameterValue 589## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 590## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 591## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] 592## CHECK-DAG: <<Not1:i\d+>> Xor [<<AddP1>>,<<CstM1>>] 593## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] 594## CHECK-DAG: <<Not2:i\d+>> Xor [<<AddP2>>,<<CstM1>>] 595## CHECK-DAG: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>] 596## CHECK-DAG: Return [<<Or>>] 597 598## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after) 599## CHECK-DAG: <<P1:i\d+>> ParameterValue 600## CHECK-DAG: <<P2:i\d+>> ParameterValue 601## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 602## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>] 603## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>] 604## CHECK-DAG: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>] 605## CHECK-DAG: <<Not:i\d+>> Not [<<And>>] 606## CHECK-DAG: Return [<<Not>>] 607 608## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after) 609## CHECK-DAG: Not 610## CHECK-NOT: Not 611 612## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after) 613## CHECK-NOT: Or 614 615# Original java source: 616# 617# public static int $opt$noinline$regressInputsAway(int a, int b) { 618# int a1 = a + 1; 619# int not_a1 = ~a1; 620# int b1 = b + 1; 621# int not_b1 = ~b1; 622# return not_a1 | not_b1; 623# } 624 625.method public static $opt$noinline$regressInputsAwayV2(II)I 626 .registers 7 627 .param p0, "a" # I 628 .param p1, "b" # I 629 630 .prologue 631 .line 234 632 add-int/lit8 v0, p0, 0x1 633 634 .line 236 635 .local v0, "a1":I 636 xor-int/lit8 v2, v0, -0x1 637 638 .line 237 639 .local v2, "not_a1":I 640 add-int/lit8 v1, p1, 0x1 641 642 .line 238 643 .local v1, "b1":I 644 xor-int/lit8 v3, v1, -0x1 645 646 .line 239 647 .local v3, "not_b1":I 648 or-int v4, v2, v3 649 650 return v4 651.end method 652 653 654# Test transformation of Not/Not/Xor into Xor. 655 656# See first note above. 657## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (before) 658## CHECK-DAG: <<P1:i\d+>> ParameterValue 659## CHECK-DAG: <<P2:i\d+>> ParameterValue 660## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 661## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] 662## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] 663## CHECK-DAG: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>] 664## CHECK-DAG: Return [<<Xor>>] 665 666## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after) 667## CHECK-DAG: <<P1:i\d+>> ParameterValue 668## CHECK-DAG: <<P2:i\d+>> ParameterValue 669## CHECK-DAG: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>] 670## CHECK-DAG: Return [<<Xor>>] 671 672## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after) 673## CHECK-NOT: Not 674 675# Original java source: 676# 677# public static int $opt$noinline$notXorToXor(int a, int b) { 678# return ~a ^ ~b; 679# } 680 681.method public static $opt$noinline$notXorToXorV2(II)I 682 .registers 4 683 .param p0, "a" # I 684 .param p1, "b" # I 685 686 .prologue 687 .line 266 688 xor-int/lit8 v0, p0, -0x1 689 690 xor-int/lit8 v1, p1, -0x1 691 692 xor-int/2addr v0, v1 693 694 return v0 695.end method 696 697 698# Test transformation of Not/Not/Xor into Xor for boolean negations. 699# Note that the graph before this instruction simplification pass does not 700# contain `HBooleanNot` instructions. This is because this transformation 701# follows the optimization of `HSelect` to `HBooleanNot` occurring in the 702# same pass. 703 704## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (before) 705## CHECK-DAG: <<P1:z\d+>> ParameterValue 706## CHECK-DAG: <<P2:z\d+>> ParameterValue 707## CHECK-DAG: <<Const0:i\d+>> IntConstant 0 708## CHECK-DAG: <<Const1:i\d+>> IntConstant 1 709## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>] 710## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>] 711## CHECK-DAG: <<Xor:i\d+>> Xor [<<Select1>>,<<Select2>>] 712## CHECK-DAG: Return [<<Xor>>] 713 714## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (after) 715## CHECK-DAG: <<Cond1:z\d+>> ParameterValue 716## CHECK-DAG: <<Cond2:z\d+>> ParameterValue 717## CHECK-DAG: <<Xor:i\d+>> Xor [<<Cond1>>,<<Cond2>>] 718## CHECK-DAG: Return [<<Xor>>] 719 720## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_bce (after) 721## CHECK-NOT: BooleanNot 722 723# Original java source: 724# 725# public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) { 726# return !a ^ !b; 727# } 728 729.method public static $opt$noinline$booleanNotXorToXorV2(ZZ)Z 730 .registers 5 731 .param p0, "a" # Z 732 .param p1, "b" # Z 733 734 .prologue 735 const/4 v0, 0x1 736 737 const/4 v1, 0x0 738 739 .line 298 740 if-nez p0, :cond_13 741 742 move v2, v0 743 744 :goto_f 745 if-nez p1, :cond_15 746 747 :goto_11 748 xor-int/2addr v0, v2 749 750 return v0 751 752 :cond_13 753 move v2, v1 754 755 goto :goto_f 756 757 :cond_15 758 move v0, v1 759 760 goto :goto_11 761.end method 762 763 764# Check that no transformation is done when one Not has multiple uses. 765 766## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (before) 767## CHECK-DAG: <<P1:i\d+>> ParameterValue 768## CHECK-DAG: <<P2:i\d+>> ParameterValue 769## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1 770## CHECK-DAG: <<One:i\d+>> IntConstant 1 771## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>] 772## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>] 773## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>] 774## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] 775## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>] 776## CHECK-DAG: Return [<<Add>>] 777 778## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after) 779## CHECK-DAG: <<P1:i\d+>> ParameterValue 780## CHECK-DAG: <<P2:i\d+>> ParameterValue 781## CHECK-DAG: <<One:i\d+>> IntConstant 1 782## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>] 783## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>] 784## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>] 785## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>] 786## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>] 787## CHECK-DAG: Return [<<Add>>] 788 789## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after) 790## CHECK-NOT: Or 791 792# Original java source: 793# 794# public static int $opt$noinline$notMultipleUses(int a, int b) { 795# int tmp = ~b; 796# return (tmp & 0x1) + (~a & tmp); 797# } 798 799.method public static $opt$noinline$notMultipleUsesV2(II)I 800 .registers 5 801 .param p0, "a" # I 802 .param p1, "b" # I 803 804 .prologue 805 .line 333 806 xor-int/lit8 v0, p1, -0x1 807 808 .line 335 809 .local v0, "tmp":I 810 and-int/lit8 v1, v0, 0x1 811 812 xor-int/lit8 v2, p0, -0x1 813 814 and-int/2addr v2, v0 815 816 add-int/2addr v1, v2 817 818 return v1 819.end method 820