Remove restriction of different Phi values in SelectGenerator
The restriction was blocking select generation and there's no
good reason to have it.
Also took the opportunity to create a robust test suite for
select generation.
Bug: 245535393
Test: dex2oat compiling the app in the bug
Test: art/test/testrunner/testrunner.py --host --64 --optimizing -b
Change-Id: I4d520a0210179ffa05c4536b3936bc3a67990935
diff --git a/compiler/optimizing/select_generator.cc b/compiler/optimizing/select_generator.cc
index f3b2af7..63460db 100644
--- a/compiler/optimizing/select_generator.cc
+++ b/compiler/optimizing/select_generator.cc
@@ -69,22 +69,20 @@
return block1->GetSingleSuccessor() == block2->GetSingleSuccessor();
}
-// Returns nullptr if `block` has either no phis or there is more than one phi
-// with different inputs at `index1` and `index2`. Otherwise returns that phi.
-static HPhi* GetSingleChangedPhi(HBasicBlock* block, size_t index1, size_t index2) {
+// Returns nullptr if `block` has either no phis or there is more than one phi. Otherwise returns
+// that phi.
+static HPhi* GetSinglePhi(HBasicBlock* block, size_t index1, size_t index2) {
DCHECK_NE(index1, index2);
HPhi* select_phi = nullptr;
for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
HPhi* phi = it.Current()->AsPhi();
- if (phi->InputAt(index1) != phi->InputAt(index2)) {
- if (select_phi == nullptr) {
- // First phi with different inputs for the two indices found.
- select_phi = phi;
- } else {
- // More than one phis has different inputs for the two indices.
- return nullptr;
- }
+ if (select_phi == nullptr) {
+ // First phi found.
+ select_phi = phi;
+ } else {
+ // More than one phi found, return null.
+ return nullptr;
}
}
return select_phi;
@@ -127,7 +125,15 @@
DCHECK_NE(predecessor_index_true, predecessor_index_false);
bool both_successors_return = true_block->IsSingleReturn() && false_block->IsSingleReturn();
- HPhi* phi = GetSingleChangedPhi(merge_block, predecessor_index_true, predecessor_index_false);
+ // TODO(solanes): Extend to support multiple phis? e.g.
+ // int a, b;
+ // if (bool) {
+ // a = 0; b = 1;
+ // } else {
+ // a = 1; b = 2;
+ // }
+ // // use a and b
+ HPhi* phi = GetSinglePhi(merge_block, predecessor_index_true, predecessor_index_false);
HInstruction* true_value = nullptr;
HInstruction* false_value = nullptr;
@@ -294,6 +300,11 @@
first_merge->AddDominatedBlock(second_merge);
first_merge->MergeWith(second_merge);
+ // No need to update dominance information. There's a chance that `merges_into_second_merge`
+ // doesn't come before `first_merge` but we don't need to fix it since `merges_into_second_merge`
+ // will disappear from the graph altogether when doing the follow-up
+ // TryGenerateSelectSimpleDiamondPattern.
+
return inner_if_block;
}
diff --git a/test/463-checker-boolean-simplifier/smali/Main2.smali b/test/463-checker-boolean-simplifier/smali/Main2.smali
index 5fc553e..e8ebb23 100644
--- a/test/463-checker-boolean-simplifier/smali/Main2.smali
+++ b/test/463-checker-boolean-simplifier/smali/Main2.smali
@@ -211,6 +211,9 @@
goto :goto_4
.end method
+# This test currently checks that we don't perform select generation due to
+# having multiple phis.
+
## CHECK-START: int Main2.MultiplePhis() select_generator (before)
## CHECK-DAG: <<Const0:i\d+>> IntConstant 0
## CHECK-DAG: <<Const1:i\d+>> IntConstant 1
@@ -228,11 +231,11 @@
## 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: <<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: <<Select>> Select [<<Const13>>,<<Const42>>,<<Cond>>]
+## CHECK-DAG: If [<<Cond>>]
## CHECK-DAG: Return [<<PhiX>>]
# The original java source of this method:
diff --git a/test/663-checker-select-generator/info.txt b/test/663-checker-select-generator/info.txt
index 792779f..6a5ac27 100644
--- a/test/663-checker-select-generator/info.txt
+++ b/test/663-checker-select-generator/info.txt
@@ -1,14 +1,26 @@
Test for select generation for conditional returns.
-Tests the rewriting from:
-
+For example rewrites a simpled diamond pattern e.g.:
If [ Condition ]
/ \
false branch true branch
- return FalseValue return TrueValue
+ \ /
+ Return Phi[FalseValue, TrueValue]
to:
-
true branch
false branch
return Select [FalseValue, TrueValue, Condition]
+
+It tests:
+* Simple diamond pattern with:
+ * Same value on each branch
+ * Different value
+* Double diamond pattern (i.e. nested simple diamonds) with:
+ * Same value
+ * All different values
+ * Same value in some cases but not all
+
+For all cases it tests:
+* Branches merging with a Phi.
+* Branches returning instead of having a Phi.
\ No newline at end of file
diff --git a/test/663-checker-select-generator/smali/TestCase.smali b/test/663-checker-select-generator/smali/TestCase.smali
deleted file mode 100644
index 844a9cf..0000000
--- a/test/663-checker-select-generator/smali/TestCase.smali
+++ /dev/null
@@ -1,72 +0,0 @@
-# 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 LTestCase;
-
-.super Ljava/lang/Object;
-
-## CHECK-START: boolean TestCase.testCase(boolean) select_generator (before)
-## CHECK-DAG: <<Param:z\d+>> ParameterValue
-## CHECK-DAG: <<Int0:i\d+>> IntConstant 0
-## CHECK-DAG: <<Int1:i\d+>> IntConstant 1
-## CHECK-DAG: If [<<Param>>]
-## CHECK-DAG: Return [<<Int0>>]
-## CHECK-DAG: Return [<<Int1>>]
-
-## CHECK-START: boolean TestCase.testCase(boolean) select_generator (after)
-## CHECK-DAG: <<Param:z\d+>> ParameterValue
-## CHECK-DAG: <<Int0:i\d+>> IntConstant 0
-## CHECK-DAG: <<Int1:i\d+>> IntConstant 1
-## CHECK-DAG: <<Select:i\d+>> Select [<<Int0>>,<<Int1>>,<<Param>>]
-## CHECK-DAG: Return [<<Select>>]
-
-.method public static testCase(Z)Z
- .registers 1
-
- # The select generation will replace this with a select
- # instruction and a return.
- if-eqz v0, :else
- const v0, 0x1
- return v0
-
- :else
- const v0, 0x0
- return v0
-.end method
-
-
-## CHECK-START: java.lang.Object TestCase.referenceTypeTestCase(Main$Sub1, Main$Sub2, boolean) select_generator (before)
-## CHECK-DAG: <<Param0:l\d+>> ParameterValue
-## CHECK-DAG: <<Param1:l\d+>> ParameterValue
-## CHECK-DAG: <<Param2:z\d+>> ParameterValue
-## CHECK-DAG: If [<<Param2>>]
-## CHECK-DAG: Return [<<Param1>>]
-## CHECK-DAG: Return [<<Param0>>]
-
-## CHECK-START: java.lang.Object TestCase.referenceTypeTestCase(Main$Sub1, Main$Sub2, boolean) select_generator (after)
-## CHECK-DAG: <<Param0:l\d+>> ParameterValue
-## CHECK-DAG: <<Param1:l\d+>> ParameterValue
-## CHECK-DAG: <<Param2:z\d+>> ParameterValue
-## CHECK-DAG: <<Select:l\d+>> Select [<<Param1>>,<<Param0>>,<<Param2>>]
-## CHECK-DAG: Return [<<Select>>]
-
-.method public static referenceTypeTestCase(LMain$Sub1;LMain$Sub2;Z)Ljava/lang/Object;
- .registers 3
-
- if-eqz v2, :else
- return-object v0
-
- :else
- return-object v1
-.end method
diff --git a/test/663-checker-select-generator/src/Main.java b/test/663-checker-select-generator/src/Main.java
index c5c7a43..0ab3aef 100644
--- a/test/663-checker-select-generator/src/Main.java
+++ b/test/663-checker-select-generator/src/Main.java
@@ -14,49 +14,353 @@
* limitations under the License.
*/
-import java.lang.reflect.Method;
-
public class Main {
- public static class Super {}
- public static class Sub1 {}
- public static class Sub2 {}
+ // Check that we don't generate a select since we don't have no Phi (not even at the builder
+ // stage) since both values are the same.
- public static void assertTrue(boolean result) {
- if (!result) {
- throw new Error("Expected true");
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) builder (after)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) select_generator (before)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) select_generator (after)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValue(boolean) select_generator (after)
+ /// CHECK-NOT: Select
+ private static int $noinline$testSimpleDiamondSameValue(boolean bool_param) {
+ int return_value;
+ if (bool_param) {
+ return_value = 10;
+ } else {
+ return_value = 10;
+ }
+ return return_value;
+ }
+
+ // Check that we generate a select for a simple diamond pattern, with different values.
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValue(boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>]
+ /// CHECK-DAG: Return [<<Phi>>]
+ /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>"]) == set(["<<Const10>>","<<Const20>>"])
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValue(boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool>>]
+ /// CHECK-DAG: Return [<<Select>>]
+ private static int $noinline$testSimpleDiamondDifferentValue(boolean bool_param) {
+ int return_value;
+ if (bool_param) {
+ return_value = 10;
+ } else {
+ return_value = 20;
+ }
+ return return_value;
+ }
+
+ // Check that we don't generate a select since we don't have no Phi (not even at the builder
+ // stage) since all values are the same.
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) builder (after)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) select_generator (before)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) select_generator (after)
+ /// CHECK-NOT: Phi
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValue(boolean, boolean) select_generator (after)
+ /// CHECK-NOT: Select
+ private static int $noinline$testDoubleDiamondSameValue(boolean bool_param_1, boolean bool_param_2) {
+ int return_value;
+ if (bool_param_1) {
+ return_value = 10;
+ } else {
+ if (bool_param_2) {
+ return_value = 10;
+ } else {
+ return_value = 10;
+ }
+ }
+ return return_value;
+ }
+
+ // Check that we generate a select for a double diamond pattern, with a different value in the outer branch.
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuter(boolean, boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>]
+ /// CHECK-DAG: Return [<<Phi>>]
+ /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Const10>>","<<Const20>>","<<Const20>>"])
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuter(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const20>>,<<Bool2>>]
+ /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>]
+ /// CHECK-DAG: Return [<<Select2>>]
+ private static int $noinline$testDoubleDiamondSameValueButNotAllOuter(boolean bool_param_1, boolean bool_param_2) {
+ int return_value;
+ if (bool_param_1) {
+ return_value = 10;
+ } else {
+ if (bool_param_2) {
+ return_value = 20;
+ } else {
+ return_value = 20;
+ }
+ }
+ return return_value;
+ }
+
+ // Check that we generate a select for a double diamond pattern, with a different value in the inner branch.
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInner(boolean, boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>]
+ /// CHECK-DAG: Return [<<Phi>>]
+ /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Const10>>","<<Const20>>","<<Const20>>"])
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInner(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool2>>]
+ /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const20>>,<<Bool1>>]
+ /// CHECK-DAG: Return [<<Select2>>]
+ private static int $noinline$testDoubleDiamondSameValueButNotAllInner(boolean bool_param_1, boolean bool_param_2) {
+ int return_value;
+ if (bool_param_1) {
+ return_value = 20;
+ } else {
+ if (bool_param_2) {
+ return_value = 10;
+ } else {
+ return_value = 20;
+ }
+ }
+ return return_value;
+ }
+
+ // Check that we generate a select for a double diamond pattern, with a all different values.
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValue(boolean, boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30
+ /// CHECK-DAG: <<Phi:i\d+>> Phi [<<Arg1:i\d+>>,<<Arg2:i\d+>>,<<Arg3:i\d+>>]
+ /// CHECK-DAG: Return [<<Phi>>]
+ /// CHECK-EVAL: set(["<<Arg1>>","<<Arg2>>","<<Arg3>>"]) == set(["<<Const10>>","<<Const20>>","<<Const30>>"])
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValue(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const30>>,<<Const20>>,<<Bool2>>]
+ /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>]
+ /// CHECK-DAG: Return [<<Select2>>]
+ private static int $noinline$testDoubleDiamondDifferentValue(boolean bool_param_1, boolean bool_param_2) {
+ int return_value;
+ if (bool_param_1) {
+ return_value = 10;
+ } else {
+ if (bool_param_2) {
+ return_value = 20;
+ } else {
+ return_value = 30;
+ }
+ }
+ return return_value;
+ }
+
+ private static void assertEquals(int expected, int actual) {
+ if (expected != actual) {
+ throw new AssertionError("Expected " + expected + " got " + actual);
}
}
- public static void assertFalse(boolean result) {
- if (result) {
- throw new Error("Expected false");
+ // Check that we don't generate a select since we only have a single return.
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) builder (after)
+ /// CHECK: <<Const10:i\d+>> IntConstant 10
+ /// CHECK: Return [<<Const10>>]
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) builder (after)
+ /// CHECK: Return
+ /// CHECK-NOT: Return
+
+ private static int $noinline$testSimpleDiamondSameValueWithReturn(boolean bool_param) {
+ if (bool_param) {
+ return 10;
+ } else {
+ return 10;
}
}
- public static void assertInstanceOfSub1(Object result) {
- if (!(result instanceof Sub1)) {
- throw new Error("Expected instance of Sub1");
+ // Same as testSimpleDiamondDifferentValue, but branches return.
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValueWithReturn(boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: Return [<<Const10>>]
+ /// CHECK-DAG: Return [<<Const20>>]
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondDifferentValueWithReturn(boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool>>]
+ /// CHECK-DAG: Return [<<Select>>]
+ private static int $noinline$testSimpleDiamondDifferentValueWithReturn(boolean bool_param) {
+ if (bool_param) {
+ return 10;
+ } else {
+ return 20;
}
}
- public static void assertInstanceOfSub2(Object result) {
- if (!(result instanceof Sub2)) {
- throw new Error("Expected instance of Sub2");
+ // Check that we don't generate a select since we only have a single return.
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) builder (after)
+ /// CHECK: <<Const10:i\d+>> IntConstant 10
+ /// CHECK: Return [<<Const10>>]
+
+ /// CHECK-START: int Main.$noinline$testSimpleDiamondSameValueWithReturn(boolean) builder (after)
+ /// CHECK: Return
+ /// CHECK-NOT: Return
+ private static int $noinline$testDoubleDiamondSameValueWithReturn(boolean bool_param_1, boolean bool_param_2) {
+ if (bool_param_1) {
+ return 10;
+ } else {
+ if (bool_param_2) {
+ return 10;
+ } else {
+ return 10;
+ }
+ }
+ }
+
+ // Same as testDoubleDiamondSameValueButNotAllOuter, but branches return.
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean, boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: Return [<<Const10>>]
+ /// CHECK-DAG: Return [<<Const20>>]
+
+ // Note that we have 2 returns instead of 3 as the two `return 20;` get merged into one before `select_generator`.
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean, boolean) select_generator (before)
+ /// CHECK: Return
+ /// CHECK: Return
+ /// CHECK-NOT: Return
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Select2:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool1>>]
+ /// CHECK-DAG: Return [<<Select2>>]
+ private static int $noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(boolean bool_param_1, boolean bool_param_2) {
+ if (bool_param_1) {
+ return 10;
+ } else {
+ if (bool_param_2) {
+ return 20;
+ } else {
+ return 20;
+ }
+ }
+ }
+
+ // Same as testDoubleDiamondSameValueButNotAllInner, but branches return.
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(boolean, boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: Return [<<Const10>>]
+ /// CHECK-DAG: Return [<<Const20>>]
+ /// CHECK-DAG: Return [<<Const20>>]
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const20>>,<<Const10>>,<<Bool2>>]
+ /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const20>>,<<Bool1>>]
+ /// CHECK-DAG: Return [<<Select2>>]
+ private static int $noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(boolean bool_param_1, boolean bool_param_2) {
+ if (bool_param_1) {
+ return 20;
+ } else {
+ if (bool_param_2) {
+ return 10;
+ } else {
+ return 20;
+ }
+ }
+ }
+
+ // Same as testDoubleDiamondDifferentValue, but branches return.
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValueWithReturn(boolean, boolean) select_generator (before)
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30
+ /// CHECK-DAG: Return [<<Const10>>]
+ /// CHECK-DAG: Return [<<Const20>>]
+ /// CHECK-DAG: Return [<<Const30>>]
+
+ /// CHECK-START: int Main.$noinline$testDoubleDiamondDifferentValueWithReturn(boolean, boolean) select_generator (after)
+ /// CHECK-DAG: <<Bool1:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Bool2:z\d+>> ParameterValue
+ /// CHECK-DAG: <<Const10:i\d+>> IntConstant 10
+ /// CHECK-DAG: <<Const20:i\d+>> IntConstant 20
+ /// CHECK-DAG: <<Const30:i\d+>> IntConstant 30
+ /// CHECK-DAG: <<Select:i\d+>> Select [<<Const30>>,<<Const20>>,<<Bool2>>]
+ /// CHECK-DAG: <<Select2:i\d+>> Select [<<Select>>,<<Const10>>,<<Bool1>>]
+ /// CHECK-DAG: Return [<<Select2>>]
+ private static int $noinline$testDoubleDiamondDifferentValueWithReturn(boolean bool_param_1, boolean bool_param_2) {
+ if (bool_param_1) {
+ return 10;
+ } else {
+ if (bool_param_2) {
+ return 20;
+ } else {
+ return 30;
+ }
}
}
public static void main(String[] args) throws Throwable {
- Class<?> c = Class.forName("TestCase");
- Method m = c.getMethod("testCase", boolean.class);
- Method m2 = c.getMethod("referenceTypeTestCase", Sub1.class, Sub2.class, boolean.class);
+ // With phi
+ assertEquals(10, $noinline$testSimpleDiamondSameValue(false));
+ assertEquals(20, $noinline$testSimpleDiamondDifferentValue(false));
+ assertEquals(10, $noinline$testDoubleDiamondSameValue(false, false));
+ assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllOuter(false, false));
+ assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllInner(false, false));
+ assertEquals(30, $noinline$testDoubleDiamondDifferentValue(false, false));
- try {
- assertTrue((Boolean) m.invoke(null, true));
- assertFalse((Boolean) m.invoke(null, false));
- assertInstanceOfSub1(m2.invoke(null, new Sub1(), new Sub2(), true));
- assertInstanceOfSub2(m2.invoke(null, new Sub1(), new Sub2(), false));
- } catch (Exception e) {
- throw new Error(e);
- }
+ // With return
+ assertEquals(10, $noinline$testSimpleDiamondSameValueWithReturn(false));
+ assertEquals(20, $noinline$testSimpleDiamondDifferentValueWithReturn(false));
+ assertEquals(10, $noinline$testDoubleDiamondSameValueWithReturn(false, false));
+ assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllOuterWithReturn(false, false));
+ assertEquals(20, $noinline$testDoubleDiamondSameValueButNotAllInnerWithReturn(false, false));
+ assertEquals(30, $noinline$testDoubleDiamondDifferentValueWithReturn(false, false));
}
}