820 lines
30 KiB
Smali
820 lines
30 KiB
Smali
# Copyright (C) 2017 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
.class public LSmaliTests;
|
|
.super Ljava/lang/Object;
|
|
|
|
#
|
|
# Test transformation of Not/Not/And into Or/Not.
|
|
#
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>]
|
|
## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>]
|
|
## CHECK-DAG: <<And:i\d+>> And [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<And>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<P1>>,<<P2>>]
|
|
## CHECK-DAG: <<Not:i\d+>> Not [<<Or>>]
|
|
## CHECK-DAG: Return [<<Not>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: Not
|
|
## CHECK-NOT: Not
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOr(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: And
|
|
.method public static $opt$noinline$andToOr(II)I
|
|
.registers 4
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
# return ~a & ~b;
|
|
not-int v0, p0
|
|
not-int v1, p1
|
|
and-int/2addr v0, v1
|
|
|
|
return v0
|
|
.end method
|
|
|
|
# Test transformation of Not/Not/And into Or/Not for boolean negations.
|
|
# Note that the graph before this instruction simplification pass does not
|
|
# contain `HBooleanNot` instructions. This is because this transformation
|
|
# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
|
|
# same pass.
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>]
|
|
## CHECK-DAG: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>]
|
|
## CHECK-DAG: <<And:i\d+>> And [<<NotP1>>,<<NotP2>>]
|
|
## CHECK-DAG: Return [<<And>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier (after)
|
|
## CHECK-DAG: <<Cond1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cond2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<Cond1>>,<<Cond2>>]
|
|
## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<Or>>]
|
|
## CHECK-DAG: Return [<<BooleanNot>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-DAG: BooleanNot
|
|
## CHECK-NOT: BooleanNot
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOr(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-NOT: And
|
|
.method public static $opt$noinline$booleanAndToOr(ZZ)Z
|
|
.registers 4
|
|
.param p0, "a" # Z
|
|
.param p1, "b" # Z
|
|
|
|
.prologue
|
|
# return !a & !b;
|
|
xor-int/lit8 v0, p0, 0x1
|
|
xor-int/lit8 v1, p1, 0x1
|
|
and-int/2addr v0, v1
|
|
return v0
|
|
.end method
|
|
|
|
# Test transformation of Not/Not/Or into And/Not.
|
|
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<Not1:j\d+>> Not [<<P1>>]
|
|
## CHECK-DAG: <<Not2:j\d+>> Not [<<P2>>]
|
|
## CHECK-DAG: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<Or>>]
|
|
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<And:j\d+>> And [<<P1>>,<<P2>>]
|
|
## CHECK-DAG: <<Not:j\d+>> Not [<<And>>]
|
|
## CHECK-DAG: Return [<<Not>>]
|
|
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
|
|
## CHECK-DAG: Not
|
|
## CHECK-NOT: Not
|
|
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAnd(long, long) instruction_simplifier (after)
|
|
## CHECK-NOT: Or
|
|
.method public static $opt$noinline$orToAnd(JJ)J
|
|
.registers 8
|
|
.param p0, "a" # J
|
|
.param p2, "b" # J
|
|
|
|
.prologue
|
|
# return ~a | ~b;
|
|
not-long v0, p0
|
|
not-long v2, p2
|
|
or-long/2addr v0, v2
|
|
return-wide v0
|
|
.end method
|
|
|
|
# Test transformation of Not/Not/Or into Or/And for boolean negations.
|
|
# Note that the graph before this instruction simplification pass does not
|
|
# contain `HBooleanNot` instructions. This is because this transformation
|
|
# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
|
|
# same pass.
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>]
|
|
## CHECK-DAG: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>]
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<NotP1>>,<<NotP2>>]
|
|
## CHECK-DAG: Return [<<Or>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier (after)
|
|
## CHECK-DAG: <<Cond1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cond2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<And:i\d+>> And [<<Cond1>>,<<Cond2>>]
|
|
## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<And>>]
|
|
## CHECK-DAG: Return [<<BooleanNot>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-DAG: BooleanNot
|
|
## CHECK-NOT: BooleanNot
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAnd(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-NOT: Or
|
|
.method public static $opt$noinline$booleanOrToAnd(ZZ)Z
|
|
.registers 4
|
|
.param p0, "a" # Z
|
|
.param p1, "b" # Z
|
|
|
|
.prologue
|
|
# return !a | !b;
|
|
xor-int/lit8 v0, p0, 0x1
|
|
xor-int/lit8 v1, p1, 0x1
|
|
or-int/2addr v0, v1
|
|
return v0
|
|
.end method
|
|
|
|
# Test that the transformation copes with inputs being separated from the
|
|
# bitwise operations.
|
|
# This is a regression test. The initial logic was inserting the new bitwise
|
|
# operation incorrectly.
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
|
|
## CHECK-DAG: <<Not1:i\d+>> Not [<<AddP1>>]
|
|
## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
|
|
## CHECK-DAG: <<Not2:i\d+>> Not [<<AddP2>>]
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<Or>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
|
|
## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
|
|
## CHECK-DAG: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>]
|
|
## CHECK-DAG: <<Not:i\d+>> Not [<<And>>]
|
|
## CHECK-DAG: Return [<<Not>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: Not
|
|
## CHECK-NOT: Not
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAway(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: Or
|
|
.method public static $opt$noinline$regressInputsAway(II)I
|
|
.registers 7
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
# int a1 = a + 1;
|
|
add-int/lit8 v0, p0, 0x1
|
|
# int not_a1 = ~a1;
|
|
not-int v2, v0
|
|
# int b1 = b + 1;
|
|
add-int/lit8 v1, p1, 0x1
|
|
# int not_b1 = ~b1;
|
|
not-int v3, v1
|
|
|
|
# return not_a1 | not_b1
|
|
or-int v4, v2, v3
|
|
return v4
|
|
.end method
|
|
|
|
# Test transformation of Not/Not/Xor into Xor.
|
|
|
|
# See first note above.
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>]
|
|
## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>]
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notXorToXor(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: Not
|
|
.method public static $opt$noinline$notXorToXor(II)I
|
|
.registers 4
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
# return ~a ^ ~b;
|
|
not-int v0, p0
|
|
not-int v1, p1
|
|
xor-int/2addr v0, v1
|
|
return v0
|
|
.end method
|
|
|
|
# Test transformation of Not/Not/Xor into Xor for boolean negations.
|
|
# Note that the graph before this instruction simplification pass does not
|
|
# contain `HBooleanNot` instructions. This is because this transformation
|
|
# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
|
|
# same pass.
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<NotP1:i\d+>> Xor [<<P1>>,<<Const1>>]
|
|
## CHECK-DAG: <<NotP2:i\d+>> Xor [<<P2>>,<<Const1>>]
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<NotP1>>,<<NotP2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier (after)
|
|
## CHECK-DAG: <<Cond1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cond2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<Cond1>>,<<Cond2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXor(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-NOT: BooleanNot
|
|
.method public static $opt$noinline$booleanNotXorToXor(ZZ)Z
|
|
.registers 4
|
|
.param p0, "a" # Z
|
|
.param p1, "b" # Z
|
|
|
|
.prologue
|
|
# return !a ^ !b;
|
|
xor-int/lit8 v0, p0, 0x1
|
|
xor-int/lit8 v1, p1, 0x1
|
|
xor-int/2addr v0, v1
|
|
return v0
|
|
.end method
|
|
|
|
# Check that no transformation is done when one Not has multiple uses.
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<One:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>]
|
|
## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>]
|
|
## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>]
|
|
## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
|
|
## CHECK-DAG: Return [<<Add>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<One:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>]
|
|
## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>]
|
|
## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>]
|
|
## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
|
|
## CHECK-DAG: Return [<<Add>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUses(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: Or
|
|
.method public static $opt$noinline$notMultipleUses(II)I
|
|
.registers 5
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
# int tmp = ~b;
|
|
not-int v0, p1
|
|
# return (tmp & 0x1) + (~a & tmp);
|
|
and-int/lit8 v1, v0, 0x1
|
|
not-int v2, p0
|
|
and-int/2addr v2, v0
|
|
add-int/2addr v1, v2
|
|
return v1
|
|
.end method
|
|
|
|
|
|
# Test transformation of Not/Not/And into Or/Not.
|
|
|
|
# Note: before the instruction_simplifier pass, Xor's are used instead of
|
|
# Not's (the simplification happens during the same pass).
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1
|
|
## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
|
|
## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
|
|
## CHECK-DAG: <<And:i\d+>> And [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<And>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<P1>>,<<P2>>]
|
|
## CHECK-DAG: <<Not:i\d+>> Not [<<Or>>]
|
|
## CHECK-DAG: Return [<<Not>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: Not
|
|
## CHECK-NOT: Not
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$andToOrV2(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: And
|
|
|
|
# Original java source:
|
|
#
|
|
# public static int $opt$noinline$andToOr(int a, int b) {
|
|
# return ~a & ~b;
|
|
# }
|
|
|
|
.method public static $opt$noinline$andToOrV2(II)I
|
|
.registers 4
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
.line 85
|
|
xor-int/lit8 v0, p0, -0x1
|
|
|
|
xor-int/lit8 v1, p1, -0x1
|
|
|
|
and-int/2addr v0, v1
|
|
|
|
return v0
|
|
.end method
|
|
|
|
|
|
# Test transformation of Not/Not/And into Or/Not for boolean negations.
|
|
# Note that the graph before this instruction simplification pass does not
|
|
# contain `HBooleanNot` instructions. This is because this transformation
|
|
# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
|
|
# same pass.
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (before)
|
|
## CHECK-DAG: <<P1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
|
|
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
|
|
## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
|
|
## CHECK-DAG: <<And:i\d+>> And [<<Select1>>,<<Select2>>]
|
|
## CHECK-DAG: Return [<<And>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_gvn (after)
|
|
## CHECK-DAG: <<Cond1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cond2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<Cond1>>,<<Cond2>>]
|
|
## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<Or>>]
|
|
## CHECK-DAG: Return [<<BooleanNot>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-DAG: BooleanNot
|
|
## CHECK-NOT: BooleanNot
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanAndToOrV2(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-NOT: And
|
|
|
|
# Original java source:
|
|
#
|
|
# public static boolean $opt$noinline$booleanAndToOr(boolean a, boolean b) {
|
|
# return !a & !b;
|
|
# }
|
|
|
|
.method public static $opt$noinline$booleanAndToOrV2(ZZ)Z
|
|
.registers 5
|
|
.param p0, "a" # Z
|
|
.param p1, "b" # Z
|
|
|
|
.prologue
|
|
const/4 v0, 0x1
|
|
|
|
const/4 v1, 0x0
|
|
|
|
.line 122
|
|
if-nez p0, :cond_13
|
|
|
|
move v2, v0
|
|
|
|
:goto_f
|
|
if-nez p1, :cond_15
|
|
|
|
:goto_11
|
|
and-int/2addr v0, v2
|
|
|
|
return v0
|
|
|
|
:cond_13
|
|
move v2, v1
|
|
|
|
goto :goto_f
|
|
|
|
:cond_15
|
|
move v0, v1
|
|
|
|
goto :goto_11
|
|
.end method
|
|
|
|
|
|
# Test transformation of Not/Not/Or into And/Not.
|
|
|
|
# See note above.
|
|
# The second Xor has its arguments reversed for no obvious reason.
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<CstM1:j\d+>> LongConstant -1
|
|
## CHECK-DAG: <<Not1:j\d+>> Xor [<<P1>>,<<CstM1>>]
|
|
## CHECK-DAG: <<Not2:j\d+>> Xor [<<CstM1>>,<<P2>>]
|
|
## CHECK-DAG: <<Or:j\d+>> Or [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<Or>>]
|
|
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:j\d+>> ParameterValue
|
|
## CHECK-DAG: <<And:j\d+>> And [<<P1>>,<<P2>>]
|
|
## CHECK-DAG: <<Not:j\d+>> Not [<<And>>]
|
|
## CHECK-DAG: Return [<<Not>>]
|
|
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after)
|
|
## CHECK-DAG: Not
|
|
## CHECK-NOT: Not
|
|
|
|
## CHECK-START: long SmaliTests.$opt$noinline$orToAndV2(long, long) instruction_simplifier (after)
|
|
## CHECK-NOT: Or
|
|
|
|
# Original java source:
|
|
#
|
|
# public static long $opt$noinline$orToAnd(long a, long b) {
|
|
# return ~a | ~b;
|
|
# }
|
|
|
|
.method public static $opt$noinline$orToAndV2(JJ)J
|
|
.registers 8
|
|
.param p0, "a" # J
|
|
.param p2, "b" # J
|
|
|
|
.prologue
|
|
const-wide/16 v2, -0x1
|
|
|
|
.line 156
|
|
xor-long v0, p0, v2
|
|
|
|
xor-long/2addr v2, p2
|
|
|
|
or-long/2addr v0, v2
|
|
|
|
return-wide v0
|
|
.end method
|
|
|
|
# Test transformation of Not/Not/Or into Or/And for boolean negations.
|
|
# Note that the graph before this instruction simplification pass does not
|
|
# contain `HBooleanNot` instructions. This is because this transformation
|
|
# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
|
|
# same pass.
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (before)
|
|
## CHECK-DAG: <<P1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
|
|
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
|
|
## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<Select1>>,<<Select2>>]
|
|
## CHECK-DAG: Return [<<Or>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_gvn (after)
|
|
## CHECK-DAG: <<Cond1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cond2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<And:i\d+>> And [<<Cond1>>,<<Cond2>>]
|
|
## CHECK-DAG: <<BooleanNot:z\d+>> BooleanNot [<<And>>]
|
|
## CHECK-DAG: Return [<<BooleanNot>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-DAG: BooleanNot
|
|
## CHECK-NOT: BooleanNot
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanOrToAndV2(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-NOT: Or
|
|
|
|
# Original java source:
|
|
#
|
|
# public static boolean $opt$noinline$booleanOrToAnd(boolean a, boolean b) {
|
|
# return !a | !b;
|
|
# }
|
|
|
|
.method public static $opt$noinline$booleanOrToAndV2(ZZ)Z
|
|
.registers 5
|
|
.param p0, "a" # Z
|
|
.param p1, "b" # Z
|
|
|
|
.prologue
|
|
const/4 v0, 0x1
|
|
|
|
const/4 v1, 0x0
|
|
|
|
.line 193
|
|
if-nez p0, :cond_13
|
|
|
|
move v2, v0
|
|
|
|
:goto_f
|
|
if-nez p1, :cond_15
|
|
|
|
:goto_11
|
|
or-int/2addr v0, v2
|
|
|
|
return v0
|
|
|
|
:cond_13
|
|
move v2, v1
|
|
|
|
goto :goto_f
|
|
|
|
:cond_15
|
|
move v0, v1
|
|
|
|
goto :goto_11
|
|
.end method
|
|
|
|
|
|
# Test that the transformation copes with inputs being separated from the
|
|
# bitwise operations.
|
|
# This is a regression test. The initial logic was inserting the new bitwise
|
|
# operation incorrectly.
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1
|
|
## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
|
|
## CHECK-DAG: <<Not1:i\d+>> Xor [<<AddP1>>,<<CstM1>>]
|
|
## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
|
|
## CHECK-DAG: <<Not2:i\d+>> Xor [<<AddP2>>,<<CstM1>>]
|
|
## CHECK-DAG: <<Or:i\d+>> Or [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<Or>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<AddP1:i\d+>> Add [<<P1>>,<<Cst1>>]
|
|
## CHECK-DAG: <<AddP2:i\d+>> Add [<<P2>>,<<Cst1>>]
|
|
## CHECK-DAG: <<And:i\d+>> And [<<AddP1>>,<<AddP2>>]
|
|
## CHECK-DAG: <<Not:i\d+>> Not [<<And>>]
|
|
## CHECK-DAG: Return [<<Not>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: Not
|
|
## CHECK-NOT: Not
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$regressInputsAwayV2(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: Or
|
|
|
|
# Original java source:
|
|
#
|
|
# public static int $opt$noinline$regressInputsAway(int a, int b) {
|
|
# int a1 = a + 1;
|
|
# int not_a1 = ~a1;
|
|
# int b1 = b + 1;
|
|
# int not_b1 = ~b1;
|
|
# return not_a1 | not_b1;
|
|
# }
|
|
|
|
.method public static $opt$noinline$regressInputsAwayV2(II)I
|
|
.registers 7
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
.line 234
|
|
add-int/lit8 v0, p0, 0x1
|
|
|
|
.line 236
|
|
.local v0, "a1":I
|
|
xor-int/lit8 v2, v0, -0x1
|
|
|
|
.line 237
|
|
.local v2, "not_a1":I
|
|
add-int/lit8 v1, p1, 0x1
|
|
|
|
.line 238
|
|
.local v1, "b1":I
|
|
xor-int/lit8 v3, v1, -0x1
|
|
|
|
.line 239
|
|
.local v3, "not_b1":I
|
|
or-int v4, v2, v3
|
|
|
|
return v4
|
|
.end method
|
|
|
|
|
|
# Test transformation of Not/Not/Xor into Xor.
|
|
|
|
# See first note above.
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1
|
|
## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
|
|
## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<P1>>,<<P2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notXorToXorV2(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: Not
|
|
|
|
# Original java source:
|
|
#
|
|
# public static int $opt$noinline$notXorToXor(int a, int b) {
|
|
# return ~a ^ ~b;
|
|
# }
|
|
|
|
.method public static $opt$noinline$notXorToXorV2(II)I
|
|
.registers 4
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
.line 266
|
|
xor-int/lit8 v0, p0, -0x1
|
|
|
|
xor-int/lit8 v1, p1, -0x1
|
|
|
|
xor-int/2addr v0, v1
|
|
|
|
return v0
|
|
.end method
|
|
|
|
|
|
# Test transformation of Not/Not/Xor into Xor for boolean negations.
|
|
# Note that the graph before this instruction simplification pass does not
|
|
# contain `HBooleanNot` instructions. This is because this transformation
|
|
# follows the optimization of `HSelect` to `HBooleanNot` occurring in the
|
|
# same pass.
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (before)
|
|
## CHECK-DAG: <<P1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
|
|
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Select1:i\d+>> Select [<<Const1>>,<<Const0>>,<<P1>>]
|
|
## CHECK-DAG: <<Select2:i\d+>> Select [<<Const1>>,<<Const0>>,<<P2>>]
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<Select1>>,<<Select2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_gvn (after)
|
|
## CHECK-DAG: <<Cond1:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Cond2:z\d+>> ParameterValue
|
|
## CHECK-DAG: <<Xor:i\d+>> Xor [<<Cond1>>,<<Cond2>>]
|
|
## CHECK-DAG: Return [<<Xor>>]
|
|
|
|
## CHECK-START: boolean SmaliTests.$opt$noinline$booleanNotXorToXorV2(boolean, boolean) instruction_simplifier$after_bce (after)
|
|
## CHECK-NOT: BooleanNot
|
|
|
|
# Original java source:
|
|
#
|
|
# public static boolean $opt$noinline$booleanNotXorToXor(boolean a, boolean b) {
|
|
# return !a ^ !b;
|
|
# }
|
|
|
|
.method public static $opt$noinline$booleanNotXorToXorV2(ZZ)Z
|
|
.registers 5
|
|
.param p0, "a" # Z
|
|
.param p1, "b" # Z
|
|
|
|
.prologue
|
|
const/4 v0, 0x1
|
|
|
|
const/4 v1, 0x0
|
|
|
|
.line 298
|
|
if-nez p0, :cond_13
|
|
|
|
move v2, v0
|
|
|
|
:goto_f
|
|
if-nez p1, :cond_15
|
|
|
|
:goto_11
|
|
xor-int/2addr v0, v2
|
|
|
|
return v0
|
|
|
|
:cond_13
|
|
move v2, v1
|
|
|
|
goto :goto_f
|
|
|
|
:cond_15
|
|
move v0, v1
|
|
|
|
goto :goto_11
|
|
.end method
|
|
|
|
|
|
# Check that no transformation is done when one Not has multiple uses.
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (before)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<CstM1:i\d+>> IntConstant -1
|
|
## CHECK-DAG: <<One:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Not2:i\d+>> Xor [<<P2>>,<<CstM1>>]
|
|
## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>]
|
|
## CHECK-DAG: <<Not1:i\d+>> Xor [<<P1>>,<<CstM1>>]
|
|
## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
|
|
## CHECK-DAG: Return [<<Add>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after)
|
|
## CHECK-DAG: <<P1:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<P2:i\d+>> ParameterValue
|
|
## CHECK-DAG: <<One:i\d+>> IntConstant 1
|
|
## CHECK-DAG: <<Not2:i\d+>> Not [<<P2>>]
|
|
## CHECK-DAG: <<And2:i\d+>> And [<<Not2>>,<<One>>]
|
|
## CHECK-DAG: <<Not1:i\d+>> Not [<<P1>>]
|
|
## CHECK-DAG: <<And1:i\d+>> And [<<Not1>>,<<Not2>>]
|
|
## CHECK-DAG: <<Add:i\d+>> Add [<<And2>>,<<And1>>]
|
|
## CHECK-DAG: Return [<<Add>>]
|
|
|
|
## CHECK-START: int SmaliTests.$opt$noinline$notMultipleUsesV2(int, int) instruction_simplifier (after)
|
|
## CHECK-NOT: Or
|
|
|
|
# Original java source:
|
|
#
|
|
# public static int $opt$noinline$notMultipleUses(int a, int b) {
|
|
# int tmp = ~b;
|
|
# return (tmp & 0x1) + (~a & tmp);
|
|
# }
|
|
|
|
.method public static $opt$noinline$notMultipleUsesV2(II)I
|
|
.registers 5
|
|
.param p0, "a" # I
|
|
.param p1, "b" # I
|
|
|
|
.prologue
|
|
.line 333
|
|
xor-int/lit8 v0, p1, -0x1
|
|
|
|
.line 335
|
|
.local v0, "tmp":I
|
|
and-int/lit8 v1, v0, 0x1
|
|
|
|
xor-int/lit8 v2, p0, -0x1
|
|
|
|
and-int/2addr v2, v0
|
|
|
|
add-int/2addr v1, v2
|
|
|
|
return v1
|
|
.end method
|