< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java

Print this page

        

@@ -54,10 +54,11 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.ValuePhiNode;
 import org.graalvm.compiler.nodes.ValueProxyNode;
 import org.graalvm.compiler.nodes.VirtualState;
 import org.graalvm.compiler.nodes.cfg.Block;
+import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
 import org.graalvm.compiler.nodes.java.MonitorEnterNode;
 import org.graalvm.compiler.nodes.spi.NodeWithState;
 import org.graalvm.compiler.nodes.virtual.CommitAllocationNode;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 

@@ -142,11 +143,22 @@
 
     protected abstract DuplicationReplacement getDuplicationReplacement();
 
     protected abstract void beforeDuplication();
 
-    protected abstract void finishDuplication();
+    protected void finishDuplication() {
+        LoopEx originalLoopEx = original().loop();
+        ControlFlowGraph cfg = originalLoopEx.loopsData().getCFG();
+        for (LoopExitNode exit : originalLoopEx.loopBegin().loopExits().snapshot()) {
+            if (!originalLoopEx.loop().isLoopExit(cfg.blockFor(exit))) {
+                // this LoopExitNode is too low, we need to remove it otherwise it will be below
+                // merged exits
+                exit.removeExit();
+            }
+        }
+
+    }
 
     protected void patchNodes(final DuplicationReplacement dataFix) {
         if (isDuplicate() && !nodesReady) {
             assert !original.isDuplicate();
             final DuplicationReplacement cfgFix = original().getDuplicationReplacement();

@@ -386,133 +398,103 @@
             }
 
         };
     }
 
-    public static NodeIterable<AbstractBeginNode> toHirExits(final Iterable<Block> blocks) {
-        return new NodeIterable<AbstractBeginNode>() {
-
-            @Override
-            public Iterator<AbstractBeginNode> iterator() {
-                final Iterator<Block> it = blocks.iterator();
-                return new Iterator<AbstractBeginNode>() {
-
-                    @Override
-                    public void remove() {
-                        throw new UnsupportedOperationException();
-                    }
-
-                    /**
-                     * Return the true LoopExitNode for this loop or the BeginNode for the block.
-                     */
-                    @Override
-                    public AbstractBeginNode next() {
-                        Block next = it.next();
-                        LoopExitNode exit = next.getLoopExit();
-                        if (exit != null) {
-                            return exit;
-                        }
-                        return next.getBeginNode();
-                    }
-
-                    @Override
-                    public boolean hasNext() {
-                        return it.hasNext();
-                    }
-                };
-            }
-
-        };
-    }
-
     /**
      * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
      * the original fragment's exits.
      */
     protected void mergeEarlyExits() {
         assert isDuplicate();
         StructuredGraph graph = graph();
-        for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) {
-            LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
-            FixedNode next = loopEarlyExit.next();
-            if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
+        for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getLoopExits())) {
+            FixedNode next = earlyExit.next();
+            if (earlyExit.isDeleted() || !this.original().contains(earlyExit)) {
                 continue;
             }
-            AbstractBeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
+            AbstractBeginNode newEarlyExit = getDuplicatedNode(earlyExit);
             if (newEarlyExit == null) {
                 continue;
             }
             MergeNode merge = graph.add(new MergeNode());
             EndNode originalEnd = graph.add(new EndNode());
             EndNode newEnd = graph.add(new EndNode());
             merge.addForwardEnd(originalEnd);
             merge.addForwardEnd(newEnd);
-            loopEarlyExit.setNext(originalEnd);
+            earlyExit.setNext(originalEnd);
             newEarlyExit.setNext(newEnd);
             merge.setNext(next);
 
-            FrameState exitState = loopEarlyExit.stateAfter();
-            if (exitState != null) {
-                FrameState originalExitState = exitState;
-                exitState = exitState.duplicateWithVirtualState();
-                loopEarlyExit.setStateAfter(exitState);
-                merge.setStateAfter(originalExitState);
-                /*
-                 * Using the old exit's state as the merge's state is necessary because some of the
-                 * VirtualState nodes contained in the old exit's state may be shared by other
-                 * dominated VirtualStates. Those dominated virtual states need to see the
-                 * proxy->phi update that are applied below.
-                 *
-                 * We now update the original fragment's nodes accordingly:
-                 */
-                originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node));
-                exitState.applyToVirtual(node -> original.nodes.markAndGrow(node));
-            }
-            FrameState finalExitState = exitState;
-
-            for (Node anchored : loopEarlyExit.anchored().snapshot()) {
-                anchored.replaceFirstInput(loopEarlyExit, merge);
-            }
-
-            boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
-            for (ProxyNode vpn : loopEarlyExit.proxies().snapshot()) {
-                if (vpn.hasNoUsages()) {
-                    continue;
-                }
-                if (vpn.value() == null) {
-                    assert vpn instanceof GuardProxyNode;
-                    vpn.replaceAtUsages(null);
-                    continue;
-                }
-                final ValueNode replaceWith;
-                ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
-                if (newVpn != null) {
-                    PhiNode phi;
-                    if (vpn instanceof ValueProxyNode) {
-                        phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge));
-                    } else if (vpn instanceof GuardProxyNode) {
-                        phi = graph.addWithoutUnique(new GuardPhiNode(merge));
+            FrameState exitState = null;
+            if (earlyExit instanceof LoopExitNode) {
+                LoopExitNode earlyLoopExit = (LoopExitNode) earlyExit;
+                exitState = earlyLoopExit.stateAfter();
+                if (exitState != null) {
+                    FrameState originalExitState = exitState;
+                    exitState = exitState.duplicateWithVirtualState();
+                    earlyLoopExit.setStateAfter(exitState);
+                    merge.setStateAfter(originalExitState);
+                    /*
+                     * Using the old exit's state as the merge's state is necessary because some of
+                     * the VirtualState nodes contained in the old exit's state may be shared by
+                     * other dominated VirtualStates. Those dominated virtual states need to see the
+                     * proxy->phi update that are applied below.
+                     *
+                     * We now update the original fragment's nodes accordingly:
+                     */
+                    originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node));
+                    exitState.applyToVirtual(node -> original.nodes.markAndGrow(node));
+                }
+            }
+
+            for (Node anchored : earlyExit.anchored().snapshot()) {
+                anchored.replaceFirstInput(earlyExit, merge);
+            }
+
+            if (earlyExit instanceof LoopExitNode) {
+                LoopExitNode earlyLoopExit = (LoopExitNode) earlyExit;
+                FrameState finalExitState = exitState;
+                boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
+                for (ProxyNode vpn : earlyLoopExit.proxies().snapshot()) {
+                    if (vpn.hasNoUsages()) {
+                        continue;
+                    }
+                    if (vpn.value() == null) {
+                        assert vpn instanceof GuardProxyNode;
+                        vpn.replaceAtUsages(null);
+                        continue;
+                    }
+                    final ValueNode replaceWith;
+                    ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
+                    if (newVpn != null) {
+                        PhiNode phi;
+                        if (vpn instanceof ValueProxyNode) {
+                            phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge));
+                        } else if (vpn instanceof GuardProxyNode) {
+                            phi = graph.addWithoutUnique(new GuardPhiNode(merge));
+                        } else {
+                            throw GraalError.shouldNotReachHere();
+                        }
+                        phi.addInput(vpn);
+                        phi.addInput(newVpn);
+                        replaceWith = phi;
                     } else {
-                        throw GraalError.shouldNotReachHere();
+                        replaceWith = vpn.value();
                     }
-                    phi.addInput(vpn);
-                    phi.addInput(newVpn);
-                    replaceWith = phi;
-                } else {
-                    replaceWith = vpn.value();
-                }
-                vpn.replaceAtMatchingUsages(replaceWith, usage -> {
-                    if (merge.isPhiAtMerge(usage)) {
-                        return false;
-                    }
-                    if (usage instanceof VirtualState) {
-                        VirtualState stateUsage = (VirtualState) usage;
-                        if (finalExitState != null && finalExitState.isPartOfThisState(stateUsage)) {
+                    vpn.replaceAtMatchingUsages(replaceWith, usage -> {
+                        if (merge.isPhiAtMerge(usage)) {
                             return false;
                         }
-                    }
-                    return true;
-                });
+                        if (usage instanceof VirtualState) {
+                            VirtualState stateUsage = (VirtualState) usage;
+                            if (finalExitState != null && finalExitState.isPartOfThisState(stateUsage)) {
+                                return false;
+                            }
+                        }
+                        return true;
+                    });
+                }
             }
         }
     }
 }
< prev index next >