ART: Implement HSelect
This patch adds a new HIR instruction to Optimizing. HSelect returns
one of two inputs based on the outcome of a condition.
This is only initial implementation which:
- defines the new instruction,
- repurposes BooleanSimplifier to emit it,
- extends InstructionSimplifier to statically resolve it,
- updates existing code and tests accordingly.
Code generators currently emit fallback if/then/else code and will be
updated in follow-up CLs to use platform-specific conditional moves
when possible.
Change-Id: Ib61b17146487ebe6b55350c2b589f0b971dcaaee
diff --git a/test/442-checker-constant-folding/src/Main.java b/test/442-checker-constant-folding/src/Main.java
index 0e07f47..5479818 100644
--- a/test/442-checker-constant-folding/src/Main.java
+++ b/test/442-checker-constant-folding/src/Main.java
@@ -666,11 +666,11 @@
/// CHECK-START: int Main.StaticConditionNulls() constant_folding_after_inlining (before)
/// CHECK-DAG: <<Null:l\d+>> NullConstant
/// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<Null>>,<<Null>>]
- /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Cond>>]
/// CHECK-START: int Main.StaticConditionNulls() constant_folding_after_inlining (after)
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: If [<<Const0>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Const0>>]
/// CHECK-START: int Main.StaticConditionNulls() constant_folding_after_inlining (after)
/// CHECK-NOT: NotEqual
diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java
index 92cf807..d48b30e 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -275,23 +275,6 @@
}
}
- /// CHECK-START: void Main.testNotInstanceOf_Inlined(java.lang.Object) inliner (after)
- /// CHECK-DAG: <<IOf:z\d+>> InstanceOf
- /// CHECK-DAG: <<Not:z\d+>> BooleanNot [<<IOf>>]
- /// CHECK-DAG: If [<<Not>>]
-
- /// CHECK-START: void Main.testNotInstanceOf_Inlined(java.lang.Object) instruction_simplifier_after_bce (before)
- /// CHECK: CheckCast
- /// CHECK-NOT: CheckCast
-
- /// CHECK-START: void Main.testNotInstanceOf_Inlined(java.lang.Object) instruction_simplifier_after_bce (after)
- /// CHECK-NOT: CheckCast
- public void testNotInstanceOf_Inlined(Object o) {
- if ($inline$InstanceofSubclassC(o)) {
- ((SubclassC)o).$noinline$g();
- }
- }
-
/// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (before)
/// CHECK: CheckCast
/// CHECK: CheckCast
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index 0fd7801..3c8abeb 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -969,6 +969,13 @@
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
/// CHECK-DAG: If [<<Arg>>]
+ /// CHECK-START: int Main.EqualTrueRhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
public static int EqualTrueRhs(boolean arg) {
return (arg != true) ? 3 : 5;
}
@@ -983,6 +990,13 @@
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
/// CHECK-DAG: If [<<Arg>>]
+ /// CHECK-START: int Main.EqualTrueLhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
public static int EqualTrueLhs(boolean arg) {
return (true != arg) ? 3 : 5;
}
@@ -995,8 +1009,14 @@
/// CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<NotArg:z\d+>> BooleanNot [<<Arg>>]
- /// CHECK-DAG: If [<<NotArg>>]
+ /// CHECK-DAG: If [<<Arg>>]
+
+ /// CHECK-START: int Main.EqualFalseRhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int EqualFalseRhs(boolean arg) {
return (arg != false) ? 3 : 5;
@@ -1010,8 +1030,14 @@
/// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<NotArg:z\d+>> BooleanNot [<<Arg>>]
- /// CHECK-DAG: If [<<NotArg>>]
+ /// CHECK-DAG: If [<<Arg>>]
+
+ /// CHECK-START: int Main.EqualFalseLhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int EqualFalseLhs(boolean arg) {
return (false != arg) ? 3 : 5;
@@ -1025,8 +1051,14 @@
/// CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<NotArg:z\d+>> BooleanNot [<<Arg>>]
- /// CHECK-DAG: If [<<NotArg>>]
+ /// CHECK-DAG: If [<<Arg>>]
+
+ /// CHECK-START: int Main.NotEqualTrueRhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int NotEqualTrueRhs(boolean arg) {
return (arg == true) ? 3 : 5;
@@ -1040,8 +1072,14 @@
/// CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<NotArg:z\d+>> BooleanNot [<<Arg>>]
- /// CHECK-DAG: If [<<NotArg>>]
+ /// CHECK-DAG: If [<<Arg>>]
+
+ /// CHECK-START: int Main.NotEqualTrueLhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const5>>,<<Const3>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int NotEqualTrueLhs(boolean arg) {
return (true == arg) ? 3 : 5;
@@ -1057,6 +1095,13 @@
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
/// CHECK-DAG: If [<<Arg>>]
+ /// CHECK-START: int Main.NotEqualFalseRhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
public static int NotEqualFalseRhs(boolean arg) {
return (arg == false) ? 3 : 5;
}
@@ -1071,38 +1116,51 @@
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
/// CHECK-DAG: If [<<Arg>>]
+ /// CHECK-START: int Main.NotEqualFalseLhs(boolean) instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const3>>,<<Const5>>,<<Arg>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
public static int NotEqualFalseLhs(boolean arg) {
return (false == arg) ? 3 : 5;
}
/// CHECK-START: boolean Main.EqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
- /// CHECK-DAG: <<BoolNot:z\d+>> BooleanNot [<<Arg>>]
- /// CHECK-DAG: <<Cond:z\d+>> Equal [<<BoolNot>>,<<Const2>>]
- /// CHECK-DAG: Return [<<Cond>>]
+ /// CHECK-DAG: <<NotArg:i\d+>> Select [<<Const1>>,<<Const0>>,<<Arg>>]
+ /// CHECK-DAG: <<Cond:z\d+>> Equal [<<NotArg>>,<<Const2>>]
+ /// CHECK-DAG: <<NotCond:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>]
+ /// CHECK-DAG: Return [<<NotCond>>]
/// CHECK-START: boolean Main.EqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (after)
- /// CHECK-DAG: <<False:i\d+>> IntConstant 0
- /// CHECK-DAG: Return [<<False>>]
+ /// CHECK-DAG: <<True:i\d+>> IntConstant 1
+ /// CHECK-DAG: Return [<<True>>]
public static boolean EqualBoolVsIntConst(boolean arg) {
- return (arg ? 0 : 1) == 2;
+ return (arg ? 0 : 1) != 2;
}
/// CHECK-START: boolean Main.NotEqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
- /// CHECK-DAG: <<BoolNot:z\d+>> BooleanNot [<<Arg>>]
- /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<BoolNot>>,<<Const2>>]
- /// CHECK-DAG: Return [<<Cond>>]
+ /// CHECK-DAG: <<NotArg:i\d+>> Select [<<Const1>>,<<Const0>>,<<Arg>>]
+ /// CHECK-DAG: <<Cond:z\d+>> NotEqual [<<NotArg>>,<<Const2>>]
+ /// CHECK-DAG: <<NotCond:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>]
+ /// CHECK-DAG: Return [<<NotCond>>]
/// CHECK-START: boolean Main.NotEqualBoolVsIntConst(boolean) instruction_simplifier_after_bce (after)
- /// CHECK-DAG: <<True:i\d+>> IntConstant 1
- /// CHECK-DAG: Return [<<True>>]
+ /// CHECK-DAG: <<False:i\d+>> IntConstant 0
+ /// CHECK-DAG: Return [<<False>>]
public static boolean NotEqualBoolVsIntConst(boolean arg) {
- return (arg ? 0 : 1) != 2;
+ return (arg ? 0 : 1) == 2;
}
/*
@@ -1113,19 +1171,16 @@
/// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: <<NotArg:z\d+>> BooleanNot [<<Arg>>]
- /// CHECK-DAG: <<NotNotArg:z\d+>> BooleanNot [<<NotArg>>]
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<NotArg:i\d+>> Select [<<Const1>>,<<Const0>>,<<Arg>>]
+ /// CHECK-DAG: <<NotNotArg:i\d+>> Select [<<Const1>>,<<Const0>>,<<NotArg>>]
/// CHECK-DAG: Return [<<NotNotArg>>]
/// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_bce (after)
/// CHECK-DAG: <<Arg:z\d+>> ParameterValue
- /// CHECK-DAG: BooleanNot [<<Arg>>]
/// CHECK-DAG: Return [<<Arg>>]
- /// CHECK-START: boolean Main.NotNotBool(boolean) instruction_simplifier_after_bce (after)
- /// CHECK: BooleanNot
- /// CHECK-NOT: BooleanNot
-
public static boolean NegateValue(boolean arg) {
return !arg;
}
@@ -1254,8 +1309,14 @@
/// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier (after)
/// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
- /// CHECK-DAG: <<Not:z\d+>> BooleanNot [<<Field>>]
- /// CHECK-DAG: If [<<Not>>]
+ /// CHECK-DAG: If [<<Field>>]
+
+ /// CHECK-START: int Main.booleanFieldNotEqualOne() instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const54>>,<<Const13>>,<<Field>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int booleanFieldNotEqualOne() {
return (booleanField == true) ? 13 : 54;
@@ -1269,8 +1330,14 @@
/// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier (after)
/// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
- /// CHECK-DAG: <<Not:z\d+>> BooleanNot [<<Field>>]
- /// CHECK-DAG: If [<<Not>>]
+ /// CHECK-DAG: If [<<Field>>]
+
+ /// CHECK-START: int Main.booleanFieldEqualZero() instruction_simplifier_before_codegen (after)
+ /// CHECK-DAG: <<Field:z\d+>> StaticFieldGet
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const54>>,<<Const13>>,<<Field>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int booleanFieldEqualZero() {
return (booleanField != false) ? 13 : 54;
@@ -1278,18 +1345,27 @@
/// CHECK-START: int Main.intConditionNotEqualOne(int) instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Arg:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<GT:z\d+>> GreaterThan [<<Arg>>,<<Const42>>]
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Arg>>,<<Const42>>]
+ /// CHECK-DAG: <<GT:i\d+>> Select [<<Const1>>,<<Const0>>,<<LE>>]
/// CHECK-DAG: <<NE:z\d+>> NotEqual [<<GT>>,<<Const1>>]
- /// CHECK-DAG: If [<<NE>>]
+ /// CHECK-DAG: <<Result:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>]
+ /// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.intConditionNotEqualOne(int) instruction_simplifier_after_bce (after)
/// CHECK-DAG: <<Arg:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: If [<<LE:z\d+>>]
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<Result:i\d+>> Select [<<Const13>>,<<Const54>>,<<LE:z\d+>>]
/// CHECK-DAG: <<LE>> LessThanOrEqual [<<Arg>>,<<Const42>>]
- // Note that we match `LE` from If because there are two identical LessThanOrEqual instructions.
+ /// CHECK-DAG: Return [<<Result>>]
+ // Note that we match `LE` from Select because there are two identical
+ // LessThanOrEqual instructions.
public static int intConditionNotEqualOne(int i) {
return ((i > 42) == true) ? 13 : 54;
@@ -1298,17 +1374,26 @@
/// CHECK-START: int Main.intConditionEqualZero(int) instruction_simplifier_after_bce (before)
/// CHECK-DAG: <<Arg:i\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<GT:z\d+>> GreaterThan [<<Arg>>,<<Const42>>]
- /// CHECK-DAG: <<EQ:z\d+>> Equal [<<GT>>,<<Const0>>]
- /// CHECK-DAG: If [<<EQ>>]
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Arg>>,<<Const42>>]
+ /// CHECK-DAG: <<GT:i\d+>> Select [<<Const1>>,<<Const0>>,<<LE>>]
+ /// CHECK-DAG: <<NE:z\d+>> Equal [<<GT>>,<<Const0>>]
+ /// CHECK-DAG: <<Result:i\d+>> Select [<<Const13>>,<<Const54>>,<<NE>>]
+ /// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.intConditionEqualZero(int) instruction_simplifier_after_bce (after)
/// CHECK-DAG: <<Arg:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: If [<<LE:z\d+>>]
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<Result:i\d+>> Select [<<Const13>>,<<Const54>>,<<LE:z\d+>>]
/// CHECK-DAG: <<LE>> LessThanOrEqual [<<Arg>>,<<Const42>>]
- // Note that we match `LE` from If because there are two identical LessThanOrEqual instructions.
+ /// CHECK-DAG: Return [<<Result>>]
+ // Note that we match `LE` from Select because there are two identical
+ // LessThanOrEqual instructions.
public static int intConditionEqualZero(int i) {
return ((i > 42) != false) ? 13 : 54;
@@ -1316,17 +1401,33 @@
// Test that conditions on float/double are not flipped.
+ /// CHECK-START: int Main.floatConditionNotEqualOne(float) ssa_builder (after)
+ /// CHECK: LessThanOrEqual
+
/// CHECK-START: int Main.floatConditionNotEqualOne(float) register (before)
- /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: NotEqual [{{i\d+}},<<Const1>>]
+ /// CHECK-DAG: <<Arg:f\d+>> ParameterValue
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<Const42:f\d+>> FloatConstant 42
+ /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Arg>>,<<Const42>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<LE>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int floatConditionNotEqualOne(float f) {
return ((f > 42.0f) == true) ? 13 : 54;
}
+ /// CHECK-START: int Main.doubleConditionEqualZero(double) ssa_builder (after)
+ /// CHECK: LessThanOrEqual
+
/// CHECK-START: int Main.doubleConditionEqualZero(double) register (before)
- /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: Equal [{{i\d+}},<<Const0>>]
+ /// CHECK-DAG: <<Arg:d\d+>> ParameterValue
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const54:i\d+>> IntConstant 54
+ /// CHECK-DAG: <<Const42:d\d+>> DoubleConstant 42
+ /// CHECK-DAG: <<LE:z\d+>> LessThanOrEqual [<<Arg>>,<<Const42>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const13>>,<<Const54>>,<<LE>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static int doubleConditionEqualZero(double d) {
return ((d > 42.0) != false) ? 13 : 54;
@@ -1374,6 +1475,10 @@
assertIntEquals(NotEqualTrueLhs(true), 3);
assertIntEquals(NotEqualFalseRhs(true), 5);
assertIntEquals(NotEqualFalseLhs(true), 5);
+ assertBooleanEquals(EqualBoolVsIntConst(true), true);
+ assertBooleanEquals(EqualBoolVsIntConst(true), true);
+ assertBooleanEquals(NotEqualBoolVsIntConst(false), false);
+ assertBooleanEquals(NotEqualBoolVsIntConst(false), false);
assertBooleanEquals(NotNotBool(true), true);
assertBooleanEquals(NotNotBool(false), false);
assertFloatEquals(Div2(100.0f), 50.0f);
diff --git a/test/463-checker-boolean-simplifier/src/Main.java b/test/463-checker-boolean-simplifier/src/Main.java
index 61510d8..682f126 100644
--- a/test/463-checker-boolean-simplifier/src/Main.java
+++ b/test/463-checker-boolean-simplifier/src/Main.java
@@ -37,7 +37,7 @@
* empty branches removed.
*/
- /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
+ /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (before)
/// CHECK-DAG: <<Param:z\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
@@ -45,23 +45,24 @@
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
/// CHECK-DAG: Return [<<Phi>>]
- /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (before)
+ /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (before)
/// CHECK: Goto
/// CHECK: Goto
/// CHECK: Goto
/// CHECK-NOT: Goto
- /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (after)
/// CHECK-DAG: <<Param:z\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
- /// CHECK-DAG: <<NotParam:z\d+>> BooleanNot [<<Param>>]
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<NotParam:i\d+>> Select [<<Const1>>,<<Const0>>,<<Param>>]
/// CHECK-DAG: Return [<<NotParam>>]
- /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (after)
/// CHECK-NOT: If
/// CHECK-NOT: Phi
- /// CHECK-START: boolean Main.BooleanNot(boolean) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.BooleanNot(boolean) select_generator (after)
/// CHECK: Goto
/// CHECK-NOT: Goto
@@ -74,7 +75,7 @@
* and 0 when False.
*/
- /// CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (before)
+ /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (before)
/// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
@@ -84,13 +85,14 @@
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const0>>,<<Const1>>]
/// CHECK-DAG: Return [<<Phi>>]
- /// CHECK-START: boolean Main.GreaterThan(int, int) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.GreaterThan(int, int) select_generator (after)
/// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Cond:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: Return [<<Cond>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const0>>,<<Const1>>,<<Cond>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static boolean GreaterThan(int x, int y) {
return (x <= y) ? false : true;
@@ -101,7 +103,7 @@
* and 1 when False.
*/
- /// CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (before)
+ /// CHECK-START: boolean Main.LessThan(int, int) select_generator (before)
/// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
@@ -111,13 +113,14 @@
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
/// CHECK-DAG: Return [<<Phi>>]
- /// CHECK-START: boolean Main.LessThan(int, int) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.LessThan(int, int) select_generator (after)
/// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
/// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
- /// CHECK-DAG: <<Cond:z\d+>> LessThan [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: Return [<<Cond>>]
+ /// CHECK-DAG: <<Cond:z\d+>> GreaterThanOrEqual [<<ParamX>>,<<ParamY>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const1>>,<<Const0>>,<<Cond>>]
+ /// CHECK-DAG: Return [<<Select>>]
public static boolean LessThan(int x, int y) {
return (x < y) ? true : false;
@@ -128,7 +131,7 @@
* Note that Phis are discovered retrospectively.
*/
- /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (before)
+ /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) select_generator (before)
/// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
@@ -145,29 +148,25 @@
/// CHECK-DAG: <<PhiYZ>> Phi [<<Const1>>,<<Const0>>]
/// CHECK-DAG: <<PhiXYZ>> Phi [<<Const1>>,<<Const0>>]
- /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.ValuesOrdered(int, int, int) select_generator (after)
/// CHECK-DAG: <<ParamX:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
/// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
- /// CHECK-DAG: <<CmpXY:z\d+>> LessThanOrEqual [<<ParamX>>,<<ParamY>>]
- /// CHECK-DAG: <<CmpYZ:z\d+>> LessThanOrEqual [<<ParamY>>,<<ParamZ>>]
- /// CHECK-DAG: <<CmpXYZ:z\d+>> Equal [<<CmpXY>>,<<CmpYZ>>]
- /// CHECK-DAG: Return [<<CmpXYZ>>]
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<CmpXY:z\d+>> GreaterThan [<<ParamX>>,<<ParamY>>]
+ /// CHECK-DAG: <<SelXY:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpXY>>]
+ /// CHECK-DAG: <<CmpYZ:z\d+>> GreaterThan [<<ParamY>>,<<ParamZ>>]
+ /// CHECK-DAG: <<SelYZ:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpYZ>>]
+ /// CHECK-DAG: <<CmpXYZ:z\d+>> NotEqual [<<SelXY>>,<<SelYZ>>]
+ /// CHECK-DAG: <<SelXYZ:i\d+>> Select [<<Const1>>,<<Const0>>,<<CmpXYZ>>]
+ /// CHECK-DAG: Return [<<SelXYZ>>]
public static boolean ValuesOrdered(int x, int y, int z) {
return (x <= y) == (y <= z);
}
- /// CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (before)
- /// CHECK-DAG: <<Param:z\d+>> ParameterValue
- /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
- /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
- /// CHECK-DAG: <<NotParam:z\d+>> BooleanNot [<<Param>>]
- /// CHECK-DAG: If [<<NotParam>>]
- /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const42>>,<<Const43>>]
- /// CHECK-DAG: Return [<<Phi>>]
-
- /// CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (after)
+ /// CHECK-START: int Main.NegatedCondition(boolean) select_generator (before)
/// CHECK-DAG: <<Param:z\d+>> ParameterValue
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
/// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
@@ -175,9 +174,14 @@
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Const42>>,<<Const43>>]
/// CHECK-DAG: Return [<<Phi>>]
- // Note: The fact that branches are swapped is verified by running the test.
+ /// CHECK-START: int Main.NegatedCondition(boolean) select_generator (after)
+ /// CHECK-DAG: <<Param:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const43>>,<<Const42>>,<<Param>>]
+ /// CHECK-DAG: Return [<<Select>>]
- /// CHECK-START: int Main.NegatedCondition(boolean) boolean_simplifier (after)
+ /// CHECK-START: int Main.NegatedCondition(boolean) select_generator (after)
/// CHECK-NOT: BooleanNot
public static int NegatedCondition(boolean x) {
@@ -188,6 +192,179 @@
}
}
+ /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const42>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const43>>,<<Add>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: int Main.SimpleTrueBlock(boolean, int) select_generator (after)
+ /// CHECK-NOT: If
+
+ public static int SimpleTrueBlock(boolean x, int y) {
+ return x ? y + 42 : 43;
+ }
+
+ /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<ParamY>>,<<Const43>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Add>>,<<Const42>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: int Main.SimpleFalseBlock(boolean, int) select_generator (after)
+ /// CHECK-NOT: If
+
+ public static int SimpleFalseBlock(boolean x, int y) {
+ return x ? 42 : y + 43;
+ }
+
+ /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:i\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamZ:i\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: <<AddTrue:i\d+>> Add [<<ParamY>>,<<Const42>>]
+ /// CHECK-DAG: <<AddFalse:i\d+>> Add [<<ParamZ>>,<<Const43>>]
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<AddFalse>>,<<AddTrue>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select>>]
+
+ /// CHECK-START: int Main.SimpleBothBlocks(boolean, int, int) select_generator (after)
+ /// CHECK-NOT: If
+
+ public static int SimpleBothBlocks(boolean x, int y, int z) {
+ return x ? y + 42 : z + 43;
+ }
+
+ /// CHECK-START: int Main.ThreeBlocks(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<ParamX:z\d+>> ParameterValue
+ /// CHECK-DAG: <<ParamY:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Select23:i\d+>> Select [<<Const3>>,<<Const2>>,<<ParamY>>]
+ /// CHECK-DAG: <<Select123:i\d+>> Select [<<Select23>>,<<Const1>>,<<ParamX>>]
+ /// CHECK-DAG: Return [<<Select123>>]
+
+ public static int ThreeBlocks(boolean x, boolean y) {
+ if (x) {
+ return 1;
+ } else if (y) {
+ return 2;
+ } else {
+ return 3;
+ }
+ }
+
+ /// CHECK-START: int Main.MultiplePhis() select_generator (before)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<PhiX:i\d+>> Phi [<<Const0>>,<<Const13>>,<<Const42>>]
+ /// CHECK-DAG: <<PhiY:i\d+>> Phi [<<Const1>>,<<Add:i\d+>>,<<Add>>]
+ /// CHECK-DAG: <<Add>> Add [<<PhiY>>,<<Const1>>]
+ /// CHECK-DAG: <<Cond:z\d+>> LessThanOrEqual [<<Add>>,<<Const1>>]
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: Return [<<PhiX>>]
+
+ /// CHECK-START: int Main.MultiplePhis() select_generator (after)
+ /// CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+ /// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
+ /// CHECK-DAG: <<Const13:i\d+>> IntConstant 13
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<PhiX:i\d+>> Phi [<<Const0>>,<<Select:i\d+>>]
+ /// CHECK-DAG: <<PhiY:i\d+>> Phi [<<Const1>>,<<Add:i\d+>>]
+ /// CHECK-DAG: <<Add>> Add [<<PhiY>>,<<Const1>>]
+ /// CHECK-DAG: <<Cond:z\d+>> LessThanOrEqual [<<Add>>,<<Const1>>]
+ /// CHECK-DAG: <<Select>> Select [<<Const13>>,<<Const42>>,<<Cond>>]
+ /// CHECK-DAG: Return [<<PhiX>>]
+
+ public static int MultiplePhis() {
+ int x = 0;
+ int y = 1;
+ while (y++ < 10) {
+ if (y > 1) {
+ x = 13;
+ } else {
+ x = 42;
+ }
+ }
+ return x;
+ }
+
+ /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const2:i\d+>> IntConstant 2
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const2>>]
+ /// CHECK-DAG: Phi [<<Add>>,<<Const43>>]
+
+ /// CHECK-START: int Main.TrueBlockWithTooManyInstructions(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int TrueBlockWithTooManyInstructions(boolean x) {
+ return x ? (read_field + 2) : 43;
+ }
+
+ /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: <<Iget:i\d+>> InstanceFieldGet [<<This>>]
+ /// CHECK-DAG: <<Add:i\d+>> Add [<<Iget>>,<<Const3>>]
+ /// CHECK-DAG: Phi [<<Const42>>,<<Add>>]
+
+ /// CHECK-START: int Main.FalseBlockWithTooManyInstructions(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int FalseBlockWithTooManyInstructions(boolean x) {
+ return x ? 42 : (read_field + 3);
+ }
+
+ /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const42>>]
+ /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
+
+ /// CHECK-START: int Main.TrueBlockWithSideEffects(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int TrueBlockWithSideEffects(boolean x) {
+ return x ? (write_field = 42) : 43;
+ }
+
+ /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (before)
+ /// CHECK-DAG: <<This:l\d+>> ParameterValue
+ /// CHECK-DAG: <<Cond:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
+ /// CHECK-DAG: <<Const43:i\d+>> IntConstant 43
+ /// CHECK-DAG: If [<<Cond>>]
+ /// CHECK-DAG: InstanceFieldSet [<<This>>,<<Const43>>]
+ /// CHECK-DAG: Phi [<<Const42>>,<<Const43>>]
+
+ /// CHECK-START: int Main.FalseBlockWithSideEffects(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+
+ public int FalseBlockWithSideEffects(boolean x) {
+ return x ? 42 : (write_field = 43);
+ }
+
public static void main(String[] args) {
assertBoolEquals(false, BooleanNot(true));
assertBoolEquals(true, BooleanNot(false));
@@ -206,5 +383,30 @@
assertBoolEquals(false, ValuesOrdered(5, 5, 3));
assertIntEquals(42, NegatedCondition(true));
assertIntEquals(43, NegatedCondition(false));
+ assertIntEquals(46, SimpleTrueBlock(true, 4));
+ assertIntEquals(43, SimpleTrueBlock(false, 4));
+ assertIntEquals(42, SimpleFalseBlock(true, 7));
+ assertIntEquals(50, SimpleFalseBlock(false, 7));
+ assertIntEquals(48, SimpleBothBlocks(true, 6, 2));
+ assertIntEquals(45, SimpleBothBlocks(false, 6, 2));
+ assertIntEquals(1, ThreeBlocks(true, true));
+ assertIntEquals(1, ThreeBlocks(true, false));
+ assertIntEquals(2, ThreeBlocks(false, true));
+ assertIntEquals(3, ThreeBlocks(false, false));
+ assertIntEquals(13, MultiplePhis());
+
+ Main m = new Main();
+ assertIntEquals(42, m.TrueBlockWithTooManyInstructions(true));
+ assertIntEquals(43, m.TrueBlockWithTooManyInstructions(false));
+ assertIntEquals(42, m.FalseBlockWithTooManyInstructions(true));
+ assertIntEquals(43, m.FalseBlockWithTooManyInstructions(false));
+ assertIntEquals(42, m.TrueBlockWithSideEffects(true));
+ assertIntEquals(43, m.TrueBlockWithSideEffects(false));
+ assertIntEquals(42, m.FalseBlockWithSideEffects(true));
+ assertIntEquals(43, m.FalseBlockWithSideEffects(false));
}
+
+ // These need to be instance fields so as to not generate a LoadClass for iget/iput.
+ public int read_field = 40;
+ public int write_field = 42;
}
diff --git a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
index da1c5ec..87ad21e 100644
--- a/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
+++ b/test/468-checker-bool-simplifier-regression/smali/TestCase.smali
@@ -18,7 +18,7 @@
.field public static value:Z
-## CHECK-START: boolean TestCase.testCase() boolean_simplifier (before)
+## CHECK-START: boolean TestCase.testCase() select_generator (before)
## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
## CHECK-DAG: <<Value:z\d+>> StaticFieldGet
@@ -26,10 +26,12 @@
## CHECK-DAG: <<Phi:i\d+>> Phi [<<Const1>>,<<Const0>>]
## CHECK-DAG: Return [<<Phi>>]
-## CHECK-START: boolean TestCase.testCase() boolean_simplifier (after)
+## CHECK-START: boolean TestCase.testCase() select_generator (after)
+## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
+## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
## CHECK-DAG: <<Value:z\d+>> StaticFieldGet
-## CHECK-DAG: <<Not:z\d+>> BooleanNot [<<Value>>]
-## CHECK-DAG: Return [<<Not>>]
+## CHECK-DAG: <<Select:i\d+>> Select [<<Const1>>,<<Const0>>,<<Value>>]
+## CHECK-DAG: Return [<<Select>>]
.method public static testCase()Z
.registers 2
diff --git a/test/474-checker-boolean-input/src/Main.java b/test/474-checker-boolean-input/src/Main.java
index a2b219d..fbc28d8 100644
--- a/test/474-checker-boolean-input/src/Main.java
+++ b/test/474-checker-boolean-input/src/Main.java
@@ -27,9 +27,9 @@
* we implement a suitable type analysis.
*/
- /// CHECK-START: boolean Main.TestPhiAsBoolean(int) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.TestPhiAsBoolean(int) select_generator (after)
/// CHECK-DAG: <<Phi:i\d+>> Phi
- /// CHECK-DAG: BooleanNot [<<Phi>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Phi>>]
public static boolean f1;
public static boolean f2;
@@ -47,9 +47,9 @@
* we implement a suitable type analysis.
*/
- /// CHECK-START: boolean Main.TestAndAsBoolean(boolean, boolean) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.TestAndAsBoolean(boolean, boolean) select_generator (after)
/// CHECK-DAG: <<And:i\d+>> And
- /// CHECK-DAG: BooleanNot [<<And>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<And>>]
public static boolean InlineAnd(boolean x, boolean y) {
return x & y;
@@ -64,9 +64,9 @@
* we implement a suitable type analysis.
*/
- /// CHECK-START: boolean Main.TestOrAsBoolean(boolean, boolean) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.TestOrAsBoolean(boolean, boolean) select_generator (after)
/// CHECK-DAG: <<Or:i\d+>> Or
- /// CHECK-DAG: BooleanNot [<<Or>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Or>>]
public static boolean InlineOr(boolean x, boolean y) {
return x | y;
@@ -81,9 +81,9 @@
* we implement a suitable type analysis.
*/
- /// CHECK-START: boolean Main.TestXorAsBoolean(boolean, boolean) boolean_simplifier (after)
+ /// CHECK-START: boolean Main.TestXorAsBoolean(boolean, boolean) select_generator (after)
/// CHECK-DAG: <<Xor:i\d+>> Xor
- /// CHECK-DAG: BooleanNot [<<Xor>>]
+ /// CHECK-DAG: Select [{{i\d+}},{{i\d+}},<<Xor>>]
public static boolean InlineXor(boolean x, boolean y) {
return x ^ y;
diff --git a/test/480-checker-dead-blocks/src/Main.java b/test/480-checker-dead-blocks/src/Main.java
index 5adafaf..e5171f0 100644
--- a/test/480-checker-dead-blocks/src/Main.java
+++ b/test/480-checker-dead-blocks/src/Main.java
@@ -56,6 +56,8 @@
z = x + y;
} else {
z = x - y;
+ // Prevent HSelect simplification by having a branch with multiple instructions.
+ System.nanoTime();
}
return z;
}
@@ -86,6 +88,8 @@
z = x + y;
} else {
z = x - y;
+ // Prevent HSelect simplification by having a branch with multiple instructions.
+ System.nanoTime();
}
return z;
}
diff --git a/test/485-checker-dce-loop-update/smali/TestCase.smali b/test/485-checker-dce-loop-update/smali/TestCase.smali
index 1de0bae..056f22c 100644
--- a/test/485-checker-dce-loop-update/smali/TestCase.smali
+++ b/test/485-checker-dce-loop-update/smali/TestCase.smali
@@ -137,15 +137,14 @@
## CHECK-DAG: <<Cst5:i\d+>> IntConstant 5
## CHECK-DAG: <<Cst7:i\d+>> IntConstant 7
## CHECK-DAG: <<Cst11:i\d+>> IntConstant 11
-## CHECK-DAG: <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+## CHECK-DAG: <<PhiX:i\d+>> Phi [<<ArgX>>,<<Add5:i\d+>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
## CHECK-DAG: If [<<ArgY>>] loop:<<HeaderY>>
-## CHECK-DAG: If [<<ArgZ>>] loop:<<HeaderY>>
-## CHECK-DAG: <<Mul9:i\d+>> Mul [<<PhiX1>>,<<Cst11>>] loop:<<HeaderY>>
-## CHECK-DAG: <<PhiX2:i\d+>> Phi [<<PhiX1>>,<<Mul9>>] loop:<<HeaderY>>
+## CHECK-DAG: <<Mul9:i\d+>> Mul [<<PhiX>>,<<Cst11>>] loop:<<HeaderY>>
+## CHECK-DAG: <<SelX:i\d+>> Select [<<PhiX>>,<<Mul9>>,<<ArgZ>>] loop:<<HeaderY>>
## CHECK-DAG: If [<<Cst1>>] loop:<<HeaderY>>
-## CHECK-DAG: <<Add5>> Add [<<PhiX2>>,<<Cst5>>] loop:<<HeaderY>>
-## CHECK-DAG: <<Add7>> Add [<<PhiX1>>,<<Cst7>>] loop:<<HeaderY>>
-## CHECK-DAG: Return [<<PhiX2>>] loop:none
+## CHECK-DAG: <<Add5>> Add [<<SelX>>,<<Cst5>>] loop:<<HeaderY>>
+## CHECK-DAG: <<Add7>> Add [<<PhiX>>,<<Cst7>>] loop:<<HeaderY>>
+## CHECK-DAG: Return [<<SelX>>] loop:none
## CHECK-START: int TestCase.testExitPredecessors(int, boolean, boolean) dead_code_elimination_final (after)
## CHECK-DAG: <<ArgX:i\d+>> ParameterValue
@@ -153,13 +152,12 @@
## CHECK-DAG: <<ArgZ:z\d+>> ParameterValue
## CHECK-DAG: <<Cst7:i\d+>> IntConstant 7
## CHECK-DAG: <<Cst11:i\d+>> IntConstant 11
-## CHECK-DAG: <<PhiX1:i\d+>> Phi [<<ArgX>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
+## CHECK-DAG: <<PhiX:i\d+>> Phi [<<ArgX>>,<<Add7:i\d+>>] loop:<<HeaderY:B\d+>>
## CHECK-DAG: If [<<ArgY>>] loop:<<HeaderY>>
-## CHECK-DAG: <<Add7>> Add [<<PhiX1>>,<<Cst7>>] loop:<<HeaderY>>
-## CHECK-DAG: If [<<ArgZ>>] loop:none
-## CHECK-DAG: <<Mul9:i\d+>> Mul [<<PhiX1>>,<<Cst11>>] loop:none
-## CHECK-DAG: <<PhiX2:i\d+>> Phi [<<PhiX1>>,<<Mul9>>] loop:none
-## CHECK-DAG: Return [<<PhiX2>>] loop:none
+## CHECK-DAG: <<Add7>> Add [<<PhiX>>,<<Cst7>>] loop:<<HeaderY>>
+## CHECK-DAG: <<Mul9:i\d+>> Mul [<<PhiX>>,<<Cst11>>] loop:none
+## CHECK-DAG: <<SelX:i\d+>> Select [<<PhiX>>,<<Mul9>>,<<ArgZ>>] loop:none
+## CHECK-DAG: Return [<<SelX>>] loop:none
.method public static testExitPredecessors(IZZ)I
.registers 4
diff --git a/test/530-checker-lse/src/Main.java b/test/530-checker-lse/src/Main.java
index baee7b3..f87326c 100644
--- a/test/530-checker-lse/src/Main.java
+++ b/test/530-checker-lse/src/Main.java
@@ -595,19 +595,16 @@
/// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<True>>]
/// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>]
/// CHECK-DAG: <<GetTest:z\d+>> InstanceFieldGet [<<Obj>>]
- /// CHECK-DAG: If [<<GetTest>>]
/// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>]
- /// CHECK-DAG: <<Phi:f\d+>> Phi [<<Float42>>,<<GetField>>]
- /// CHECK-DAG: Return [<<Phi>>]
+ /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<GetField>>,<<GetTest>>]
+ /// CHECK-DAG: Return [<<Select>>]
/// CHECK-START: float Main.test24() load_store_elimination (after)
/// CHECK-DAG: <<True:i\d+>> IntConstant 1
/// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8
/// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42
- /// CHECK-DAG: <<Obj:l\d+>> NewInstance
- /// CHECK-DAG: If [<<True>>]
- /// CHECK-DAG: <<Phi:f\d+>> Phi [<<Float42>>,<<Float8>>]
- /// CHECK-DAG: Return [<<Phi>>]
+ /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<Float8>>,<<True>>]
+ /// CHECK-DAG: Return [<<Select>>]
static float test24() {
float a = 42.0f;
diff --git a/test/543-checker-dce-trycatch/smali/TestCase.smali b/test/543-checker-dce-trycatch/smali/TestCase.smali
index 1756fa4..62511df 100644
--- a/test/543-checker-dce-trycatch/smali/TestCase.smali
+++ b/test/543-checker-dce-trycatch/smali/TestCase.smali
@@ -15,6 +15,8 @@
.class public LTestCase;
.super Ljava/lang/Object;
+.field public static sField:I
+
.method private static $inline$False()Z
.registers 1
const/4 v0, 0x0
@@ -240,24 +242,25 @@
shr-int/2addr p2, p3
:try_start
- const v1, 0xa # dead catch phi input, defined in entry block (HInstruction)
- add-int v2, p0, p1 # dead catch phi input, defined in the dead block (HInstruction)
+ const v1, 0xa # dead catch phi input, defined in entry block (HInstruction)
+ add-int v2, p0, p1 # dead catch phi input, defined in the dead block (HInstruction)
move v3, v2
if-eqz v3, :define_phi
+ sput v3, LTestCase;->sField:I # beat HSelect simplification (has side-effects, does not throw)
const v3, 0xf
:define_phi
- # v3 = Phi [Add, 0xf] # dead catch phi input, defined in the dead block (HPhi)
+ # v3 = Phi [Add, 0xf] # dead catch phi input, defined in the dead block (HPhi)
div-int/2addr p0, v2
:else
- const v1, 0xb # live catch phi input
- const v2, 0xc # live catch phi input
- const v3, 0x10 # live catch phi input
+ const v1, 0xb # live catch phi input
+ const v2, 0xc # live catch phi input
+ const v3, 0x10 # live catch phi input
div-int/2addr p0, p3
- const v1, 0xd # live catch phi input
- const v2, 0xe # live catch phi input
- const v3, 0x11 # live catch phi input
+ const v1, 0xd # live catch phi input
+ const v2, 0xe # live catch phi input
+ const v3, 0x11 # live catch phi input
div-int/2addr p0, p1
:try_end
.catchall {:try_start .. :try_end} :catch_all
diff --git a/test/566-checker-codegen-select/expected.txt b/test/566-checker-codegen-select/expected.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/566-checker-codegen-select/expected.txt
diff --git a/test/566-checker-codegen-select/info.txt b/test/566-checker-codegen-select/info.txt
new file mode 100644
index 0000000..67b6ceb
--- /dev/null
+++ b/test/566-checker-codegen-select/info.txt
@@ -0,0 +1 @@
+Test the use positions of inputs of non-materialized conditions.
\ No newline at end of file
diff --git a/test/566-checker-codegen-select/src/Main.java b/test/566-checker-codegen-select/src/Main.java
new file mode 100644
index 0000000..edb31e6
--- /dev/null
+++ b/test/566-checker-codegen-select/src/Main.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+
+public class Main {
+
+ /// CHECK-START: long Main.$noinline$longSelect(long) register (before)
+ /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{j\d+}},{{j\d+}}]
+ /// CHECK-NEXT: Select [{{j\d+}},{{j\d+}},<<Cond>>]
+
+ // Condition must be materialized on X86 because it would need too many
+ // registers otherwise.
+ /// CHECK-START-X86: long Main.$noinline$longSelect(long) disassembly (after)
+ /// CHECK: LessThanOrEqual
+ /// CHECK-NEXT: cmp
+ /// CHECK: Select
+
+ public long $noinline$longSelect(long param) {
+ if (doThrow) { throw new Error(); }
+ long val_true = longB;
+ long val_false = longC;
+ return (param > longA) ? val_true : val_false;
+ }
+
+ /// CHECK-START: long Main.$noinline$longSelect_Constant(long) register (before)
+ /// CHECK: <<Const:j\d+>> LongConstant
+ /// CHECK: <<Cond:z\d+>> LessThanOrEqual [{{j\d+}},<<Const>>]
+ /// CHECK-NEXT: Select [{{j\d+}},{{j\d+}},<<Cond>>]
+
+ // Condition can be non-materialized on X86 because the condition does not
+ // request 4 registers any more.
+ /// CHECK-START-X86: long Main.$noinline$longSelect_Constant(long) disassembly (after)
+ /// CHECK: LessThanOrEqual
+ /// CHECK-NEXT: Select
+
+ public long $noinline$longSelect_Constant(long param) {
+ if (doThrow) { throw new Error(); }
+ long val_true = longB;
+ long val_false = longC;
+ return (param > 3L) ? val_true : val_false;
+ }
+
+ public static void main(String[] args) {
+ Main m = new Main();
+ assertLongEquals(5L, m.$noinline$longSelect(4L));
+ assertLongEquals(7L, m.$noinline$longSelect(2L));
+ assertLongEquals(5L, m.$noinline$longSelect_Constant(4L));
+ assertLongEquals(7L, m.$noinline$longSelect_Constant(2L));
+ }
+
+ public static void assertLongEquals(long expected, long actual) {
+ if (expected != actual) {
+ throw new Error(expected + " != " + actual);
+ }
+ }
+
+ public boolean doThrow = false;
+
+ public long longA = 3L;
+ public long longB = 5L;
+ public long longC = 7L;
+}