Search in sources :

Example 11 with MergeNode

use of org.graalvm.compiler.nodes.MergeNode in project graal by oracle.

the class DefaultLoopPolicies method shouldUnswitch.

@Override
public boolean shouldUnswitch(LoopEx loop, List<ControlSplitNode> controlSplits) {
    int phis = 0;
    StructuredGraph graph = loop.loopBegin().graph();
    DebugContext debug = graph.getDebug();
    NodeBitMap branchNodes = graph.createNodeBitMap();
    for (ControlSplitNode controlSplit : controlSplits) {
        for (Node successor : controlSplit.successors()) {
            AbstractBeginNode branch = (AbstractBeginNode) successor;
            // this may count twice because of fall-through in switches
            loop.nodesInLoopBranch(branchNodes, branch);
        }
        Block postDomBlock = loop.loopsData().getCFG().blockFor(controlSplit).getPostdominator();
        if (postDomBlock != null) {
            IsolatedInitialization.UNSWITCH_SPLIT_WITH_PHIS.increment(debug);
            phis += ((MergeNode) postDomBlock.getBeginNode()).phis().count();
        }
    }
    int inBranchTotal = branchNodes.count();
    CountingClosure stateNodesCount = new CountingClosure();
    double loopFrequency = loop.loopBegin().loopFrequency();
    OptionValues options = loop.loopBegin().getOptions();
    int maxDiff = Options.LoopUnswitchTrivial.getValue(options) + (int) (Options.LoopUnswitchFrequencyBoost.getValue(options) * (loopFrequency - 1.0 + phis));
    maxDiff = Math.min(maxDiff, Options.LoopUnswitchMaxIncrease.getValue(options));
    int remainingGraphSpace = MaximumDesiredSize.getValue(options) - graph.getNodeCount();
    maxDiff = Math.min(maxDiff, remainingGraphSpace);
    loop.loopBegin().stateAfter().applyToVirtual(stateNodesCount);
    int loopTotal = loop.size() - loop.loopBegin().phis().count() - stateNodesCount.count - 1;
    int actualDiff = (loopTotal - inBranchTotal);
    ControlSplitNode firstSplit = controlSplits.get(0);
    if (firstSplit instanceof TypeSwitchNode) {
        int copies = firstSplit.successors().count() - 1;
        for (Node succ : firstSplit.successors()) {
            FixedNode current = (FixedNode) succ;
            while (current instanceof FixedWithNextNode) {
                current = ((FixedWithNextNode) current).next();
            }
            if (current instanceof DeoptimizeNode) {
                copies--;
            }
        }
        actualDiff = actualDiff * copies;
    }
    debug.log("shouldUnswitch(%s, %s) : delta=%d (%.2f%% inside of branches), max=%d, f=%.2f, phis=%d -> %b", loop, controlSplits, actualDiff, (double) (inBranchTotal) / loopTotal * 100, maxDiff, loopFrequency, phis, actualDiff <= maxDiff);
    if (actualDiff <= maxDiff) {
        // check whether we're allowed to unswitch this loop
        return loop.canDuplicateLoop();
    } else {
        return false;
    }
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) OptionValues(org.graalvm.compiler.options.OptionValues) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) ControlFlowAnchorNode(org.graalvm.compiler.nodes.debug.ControlFlowAnchorNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) InvokeNode(org.graalvm.compiler.nodes.InvokeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) TypeSwitchNode(org.graalvm.compiler.nodes.java.TypeSwitchNode) DebugContext(org.graalvm.compiler.debug.DebugContext) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) TypeSwitchNode(org.graalvm.compiler.nodes.java.TypeSwitchNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) Block(org.graalvm.compiler.nodes.cfg.Block) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode)

Example 12 with MergeNode

use of org.graalvm.compiler.nodes.MergeNode in project graal by oracle.

the class LoopFragment method mergeEarlyExits.

/**
 * 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)) {
            continue;
        }
        AbstractBeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
        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);
        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));
                } else {
                    throw GraalError.shouldNotReachHere();
                }
                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)) {
                        return false;
                    }
                }
                return true;
            });
        }
    }
}
Also used : GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) VirtualState(org.graalvm.compiler.nodes.VirtualState) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) EndNode(org.graalvm.compiler.nodes.EndNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Example 13 with MergeNode

use of org.graalvm.compiler.nodes.MergeNode in project graal by oracle.

the class LoopFragmentInside method mergeEnds.

private AbstractBeginNode mergeEnds() {
    assert isDuplicate();
    List<EndNode> endsToMerge = new LinkedList<>();
    // map peel exits to the corresponding loop exits
    EconomicMap<AbstractEndNode, LoopEndNode> reverseEnds = EconomicMap.create(Equivalence.IDENTITY);
    LoopBeginNode loopBegin = original().loop().loopBegin();
    for (LoopEndNode le : loopBegin.loopEnds()) {
        AbstractEndNode duplicate = getDuplicatedNode(le);
        if (duplicate != null) {
            endsToMerge.add((EndNode) duplicate);
            reverseEnds.put(duplicate, le);
        }
    }
    mergedInitializers = EconomicMap.create(Equivalence.IDENTITY);
    AbstractBeginNode newExit;
    StructuredGraph graph = graph();
    if (endsToMerge.size() == 1) {
        AbstractEndNode end = endsToMerge.get(0);
        assert end.hasNoUsages();
        newExit = graph.add(new BeginNode());
        end.replaceAtPredecessor(newExit);
        end.safeDelete();
    } else {
        assert endsToMerge.size() > 1;
        AbstractMergeNode newExitMerge = graph.add(new MergeNode());
        newExit = newExitMerge;
        FrameState state = loopBegin.stateAfter();
        FrameState duplicateState = null;
        if (state != null) {
            duplicateState = state.duplicateWithVirtualState();
            newExitMerge.setStateAfter(duplicateState);
        }
        for (EndNode end : endsToMerge) {
            newExitMerge.addForwardEnd(end);
        }
        for (final PhiNode phi : loopBegin.phis().snapshot()) {
            if (phi.hasNoUsages()) {
                continue;
            }
            final PhiNode firstPhi = patchPhi(graph, phi, newExitMerge);
            for (AbstractEndNode end : newExitMerge.forwardEnds()) {
                LoopEndNode loopEnd = reverseEnds.get(end);
                ValueNode prim = prim(phi.valueAt(loopEnd));
                assert prim != null;
                firstPhi.addInput(prim);
            }
            ValueNode initializer = firstPhi;
            if (duplicateState != null) {
                // fix the merge's state after
                duplicateState.applyToNonVirtual(new NodeClosure<ValueNode>() {

                    @Override
                    public void apply(Node from, ValueNode node) {
                        if (node == phi) {
                            from.replaceFirstInput(phi, firstPhi);
                        }
                    }
                });
            }
            mergedInitializers.put(phi, initializer);
        }
    }
    return newExit;
}
Also used : ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AddNode(org.graalvm.compiler.nodes.calc.AddNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) SubNode(org.graalvm.compiler.nodes.calc.SubNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) SafepointNode(org.graalvm.compiler.nodes.SafepointNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FrameState(org.graalvm.compiler.nodes.FrameState) LinkedList(java.util.LinkedList) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) BeginNode(org.graalvm.compiler.nodes.BeginNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Example 14 with MergeNode

use of org.graalvm.compiler.nodes.MergeNode in project graal by oracle.

the class GraphKit method endIf.

/**
 * Ends an if block started with {@link #startIf(LogicNode, double)}.
 *
 * @return the created merge node, or {@code null} if no merge node was required (for example,
 *         when one part ended with a control sink).
 */
public AbstractMergeNode endIf() {
    IfStructure s = saveLastIfNode();
    FixedWithNextNode thenPart = s.thenPart instanceof FixedWithNextNode ? (FixedWithNextNode) s.thenPart : null;
    FixedWithNextNode elsePart = s.elsePart instanceof FixedWithNextNode ? (FixedWithNextNode) s.elsePart : null;
    AbstractMergeNode merge = null;
    if (thenPart != null && elsePart != null) {
        /* Both parts are alive, we need a real merge. */
        EndNode thenEnd = graph.add(new EndNode());
        graph.addAfterFixed(thenPart, thenEnd);
        EndNode elseEnd = graph.add(new EndNode());
        graph.addAfterFixed(elsePart, elseEnd);
        merge = graph.add(new MergeNode());
        merge.addForwardEnd(thenEnd);
        merge.addForwardEnd(elseEnd);
        lastFixedNode = merge;
    } else if (thenPart != null) {
        /* elsePart ended with a control sink, so we can continue with thenPart. */
        lastFixedNode = thenPart;
    } else if (elsePart != null) {
        /* thenPart ended with a control sink, so we can continue with elsePart. */
        lastFixedNode = elsePart;
    } else {
        /* Both parts ended with a control sink, so no nodes can be added after the if. */
        assert lastFixedNode == null;
    }
    s.state = IfState.FINISHED;
    popStructure();
    return merge;
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) EndNode(org.graalvm.compiler.nodes.EndNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode)

Example 15 with MergeNode

use of org.graalvm.compiler.nodes.MergeNode in project graal by oracle.

the class GraphKit method endInvokeWithException.

/**
 * Finishes a control flow started with {@link #startInvokeWithException}. If necessary, creates
 * a merge of the non-exception and exception edges. The merge node is returned and the
 * non-exception edge is the first forward end of the merge, the exception edge is the second
 * forward end (relevant for phi nodes).
 */
public AbstractMergeNode endInvokeWithException() {
    InvokeWithExceptionStructure s = saveLastInvokeWithExceptionNode();
    FixedWithNextNode noExceptionEdge = s.noExceptionEdge instanceof FixedWithNextNode ? (FixedWithNextNode) s.noExceptionEdge : null;
    FixedWithNextNode exceptionEdge = s.exceptionEdge instanceof FixedWithNextNode ? (FixedWithNextNode) s.exceptionEdge : null;
    AbstractMergeNode merge = null;
    if (noExceptionEdge != null && exceptionEdge != null) {
        EndNode noExceptionEnd = graph.add(new EndNode());
        graph.addAfterFixed(noExceptionEdge, noExceptionEnd);
        EndNode exceptionEnd = graph.add(new EndNode());
        graph.addAfterFixed(exceptionEdge, exceptionEnd);
        merge = graph.add(new MergeNode());
        merge.addForwardEnd(noExceptionEnd);
        merge.addForwardEnd(exceptionEnd);
        lastFixedNode = merge;
    } else if (noExceptionEdge != null) {
        lastFixedNode = noExceptionEdge;
    } else if (exceptionEdge != null) {
        lastFixedNode = exceptionEdge;
    } else {
        assert lastFixedNode == null;
    }
    s.state = InvokeWithExceptionStructure.State.FINISHED;
    popStructure();
    return merge;
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) EndNode(org.graalvm.compiler.nodes.EndNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode)

Aggregations

MergeNode (org.graalvm.compiler.nodes.MergeNode)20 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)16 EndNode (org.graalvm.compiler.nodes.EndNode)14 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)13 FixedNode (org.graalvm.compiler.nodes.FixedNode)13 Node (org.graalvm.compiler.graph.Node)11 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)10 ValueNode (org.graalvm.compiler.nodes.ValueNode)9 BeginNode (org.graalvm.compiler.nodes.BeginNode)8 FrameState (org.graalvm.compiler.nodes.FrameState)7 IfNode (org.graalvm.compiler.nodes.IfNode)7 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)7 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)7 PhiNode (org.graalvm.compiler.nodes.PhiNode)6 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)5 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)5 InvokeNode (org.graalvm.compiler.nodes.InvokeNode)5 PiNode (org.graalvm.compiler.nodes.PiNode)5 ReturnNode (org.graalvm.compiler.nodes.ReturnNode)5 ArrayList (java.util.ArrayList)4