src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java
changeset 48398 79afa4c434f6
parent 48190 25cfedf27edc
child 48861 47f19ff9903c
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Wed Dec 13 11:59:55 2017 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Wed Dec 13 12:28:22 2017 -0800
@@ -30,8 +30,6 @@
 import java.util.Iterator;
 import java.util.List;
 
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.ResolvedJavaType;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
@@ -67,7 +65,9 @@
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.PrimitiveConstant;
+import jdk.vm.ci.meta.ResolvedJavaType;
 
 /**
  * The {@code IfNode} represents a branch that can go one of two directions depending on the outcome
@@ -416,6 +416,7 @@
                 if (result.graph() == null) {
                     result = graph().addOrUniqueWithInputs(result);
                 }
+                result = proxyReplacement(result);
                 /*
                  * This optimization can be performed even if multiple values merge at this phi
                  * since the two inputs get simplified into one.
@@ -698,6 +699,7 @@
                     ValueNode falseValue = singlePhi.valueAt(falseEnd);
                     ValueNode conditional = canonicalizeConditionalCascade(tool, trueValue, falseValue);
                     if (conditional != null) {
+                        conditional = proxyReplacement(conditional);
                         singlePhi.setValueAt(trueEnd, conditional);
                         removeThroughFalseBranch(tool, merge);
                         return true;
@@ -729,6 +731,36 @@
         return false;
     }
 
+    private ValueNode proxyReplacement(ValueNode replacement) {
+        /*
+         * Special case: Every empty diamond we collapse to a conditional node can potentially
+         * contain loop exit nodes on both branches. See the graph below: The two loop exits
+         * (instanceof begin node) exit the same loop. The resulting phi is defined outside the
+         * loop, but the resulting conditional node will be inside the loop, so we need to proxy the
+         * resulting conditional node. Callers of this method ensure that true and false successor
+         * have no usages, therefore a and b in the graph below can never be proxies themselves.
+         */
+        // @formatter:off
+        //              +--+
+        //              |If|
+        //              +--+      +-----+ +-----+
+        //         +----+  +----+ |  a  | |  b  |
+        //         |Lex |  |Lex | +----^+ +^----+
+        //         +----+  +----+      |   |
+        //           +-------+         +---+
+        //           | Merge +---------+Phi|
+        //           +-------+         +---+
+        // @formatter:on
+        if (this.graph().hasValueProxies()) {
+            if (trueSuccessor instanceof LoopExitNode && falseSuccessor instanceof LoopExitNode) {
+                assert ((LoopExitNode) trueSuccessor).loopBegin() == ((LoopExitNode) falseSuccessor).loopBegin();
+                assert trueSuccessor.usages().isEmpty() && falseSuccessor.usages().isEmpty();
+                return this.graph().addOrUnique(new ValueProxyNode(replacement, (LoopExitNode) trueSuccessor));
+            }
+        }
+        return replacement;
+    }
+
     protected void removeThroughFalseBranch(SimplifierTool tool, AbstractMergeNode merge) {
         AbstractBeginNode trueBegin = trueSuccessor();
         LogicNode conditionNode = condition();