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));
   }
 }