< 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 >