Search in sources :

Example 1 with ControlSplitNode

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

the class ProfileNode method simplify.

@Override
public void simplify(SimplifierTool tool) {
    for (Node p = predecessor(); p != null; p = p.predecessor()) {
        // Terminate search when we hit a control split or merge.
        if (p instanceof ControlSplitNode || p instanceof AbstractMergeNode) {
            break;
        }
        if (p instanceof ProfileNode) {
            ProfileNode that = (ProfileNode) p;
            if (this.canBeMergedWith(that)) {
                that.setStep(this.getStep() + that.getStep());
                removeFixedWithUnusedInputs(this);
                tool.addToWorkList(that);
                break;
            }
        }
    }
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DeoptimizingFixedWithNextNode(org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode) Node(org.graalvm.compiler.graph.Node) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode)

Example 2 with ControlSplitNode

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

the class PropagateDeoptimizeProbabilityPhase method run.

@Override
@SuppressWarnings("try")
protected void run(final StructuredGraph graph, PhaseContext context) {
    assert !graph.hasValueProxies() : "ConvertDeoptimizeToGuardPhase always creates proxies";
    if (graph.hasNode(AbstractDeoptimizeNode.TYPE)) {
        NodeStack stack = new NodeStack();
        EconomicMap<ControlSplitNode, EconomicSet<AbstractBeginNode>> reachableSplits = EconomicMap.create();
        // Mark all control flow nodes that are post-dominated by a deoptimization.
        for (AbstractDeoptimizeNode d : graph.getNodes(AbstractDeoptimizeNode.TYPE)) {
            stack.push(AbstractBeginNode.prevBegin(d));
            while (!stack.isEmpty()) {
                AbstractBeginNode beginNode = (AbstractBeginNode) stack.pop();
                FixedNode fixedNode = (FixedNode) beginNode.predecessor();
                if (fixedNode == null) {
                // Can happen for start node.
                } else if (fixedNode instanceof AbstractMergeNode) {
                    AbstractMergeNode mergeNode = (AbstractMergeNode) fixedNode;
                    for (AbstractEndNode end : mergeNode.forwardEnds()) {
                        AbstractBeginNode newBeginNode = AbstractBeginNode.prevBegin(end);
                        stack.push(newBeginNode);
                    }
                } else if (fixedNode instanceof ControlSplitNode) {
                    ControlSplitNode controlSplitNode = (ControlSplitNode) fixedNode;
                    EconomicSet<AbstractBeginNode> reachableSuccessors = reachableSplits.get(controlSplitNode);
                    if (reachableSuccessors == null) {
                        reachableSuccessors = EconomicSet.create();
                        reachableSplits.put(controlSplitNode, reachableSuccessors);
                    }
                    if (controlSplitNode.getSuccessorCount() == reachableSuccessors.size() - 1) {
                        // All successors of this split lead to deopt, propagate reachability
                        // further upwards.
                        reachableSplits.removeKey(controlSplitNode);
                        stack.push(AbstractBeginNode.prevBegin((FixedNode) controlSplitNode.predecessor()));
                    } else {
                        reachableSuccessors.add(beginNode);
                    }
                } else {
                    stack.push(AbstractBeginNode.prevBegin(fixedNode));
                }
            }
        }
        // Make sure the probability on the path towards the deoptimization is 0.0.
        MapCursor<ControlSplitNode, EconomicSet<AbstractBeginNode>> entries = reachableSplits.getEntries();
        while (entries.advance()) {
            ControlSplitNode controlSplitNode = entries.getKey();
            EconomicSet<AbstractBeginNode> value = entries.getValue();
            for (AbstractBeginNode begin : value) {
                double probability = controlSplitNode.probability(begin);
                if (probability != 0.0) {
                    controlSplitNode.setProbability(begin, 0.0);
                }
            }
        }
    }
}
Also used : AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) NodeStack(org.graalvm.compiler.graph.NodeStack) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) EconomicSet(org.graalvm.collections.EconomicSet) AbstractDeoptimizeNode(org.graalvm.compiler.nodes.AbstractDeoptimizeNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 3 with ControlSplitNode

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

the class GraphUtil method markFixedNodes.

private static void markFixedNodes(FixedNode node, EconomicSet<Node> markedNodes, EconomicMap<AbstractMergeNode, List<AbstractEndNode>> unmarkedMerges) {
    NodeStack workStack = new NodeStack();
    workStack.push(node);
    while (!workStack.isEmpty()) {
        Node fixedNode = workStack.pop();
        markedNodes.add(fixedNode);
        if (fixedNode instanceof AbstractMergeNode) {
            unmarkedMerges.removeKey((AbstractMergeNode) fixedNode);
        }
        while (fixedNode instanceof FixedWithNextNode) {
            fixedNode = ((FixedWithNextNode) fixedNode).next();
            if (fixedNode != null) {
                markedNodes.add(fixedNode);
            }
        }
        if (fixedNode instanceof ControlSplitNode) {
            for (Node successor : fixedNode.successors()) {
                workStack.push(successor);
            }
        } else if (fixedNode instanceof AbstractEndNode) {
            AbstractEndNode end = (AbstractEndNode) fixedNode;
            AbstractMergeNode merge = end.merge();
            if (merge != null) {
                assert !markedNodes.contains(merge) || (merge instanceof LoopBeginNode && end instanceof LoopEndNode) : merge;
                if (merge instanceof LoopBeginNode) {
                    if (end == ((LoopBeginNode) merge).forwardEnd()) {
                        workStack.push(merge);
                        continue;
                    }
                    if (markedNodes.contains(merge)) {
                        continue;
                    }
                }
                List<AbstractEndNode> endsSeen = unmarkedMerges.get(merge);
                if (endsSeen == null) {
                    endsSeen = new ArrayList<>(merge.forwardEndCount());
                    unmarkedMerges.put(merge, endsSeen);
                }
                endsSeen.add(end);
                if (!(end instanceof LoopEndNode) && endsSeen.size() == merge.forwardEndCount()) {
                    assert merge.forwardEnds().filter(n -> !markedNodes.contains(n)).isEmpty();
                    // all this merge's forward ends are marked: it needs to be killed
                    workStack.push(merge);
                }
            }
        }
    }
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MonitorIdNode(org.graalvm.compiler.nodes.java.MonitorIdNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) LoadIndexedNode(org.graalvm.compiler.nodes.java.LoadIndexedNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) PiNode(org.graalvm.compiler.nodes.PiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) VirtualArrayNode(org.graalvm.compiler.nodes.virtual.VirtualArrayNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ArrayList(java.util.ArrayList) NodeStack(org.graalvm.compiler.graph.NodeStack) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) List(java.util.List) ArrayList(java.util.ArrayList) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode)

Example 4 with ControlSplitNode

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

the class OptimizeExceptionCallsPhase method setBranchProbability.

/**
 * Sets the branch probability of the guarding IfNode to a small value. The effect is that the
 * exception call block is put at the end of the method. The other block (= the regular path)
 * gets the fall-through block of the IfNode. This should give a better performance - and it
 * looks nicer in the disassembly.
 */
private static void setBranchProbability(Node endNode) {
    Node node = endNode;
    Node predecessor = node.predecessor();
    // Go "up" the graph until we find an IfNode
    while (predecessor != null) {
        if (predecessor instanceof IfNode && node instanceof BeginNode) {
            // We found an IfNode which branches to our runtime exception call
            IfNode ifNode = (IfNode) predecessor;
            ifNode.setTrueSuccessorProbability(node == ifNode.trueSuccessor() ? 0.00001 : 0.99999);
            return;
        }
        if (predecessor instanceof MergeNode || predecessor instanceof ControlSplitNode) {
            // Any other split or merge is suspicious: we abort
            return;
        }
        node = predecessor;
        predecessor = node.predecessor();
    }
}
Also used : MergeNode(org.graalvm.compiler.nodes.MergeNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) IfNode(org.graalvm.compiler.nodes.IfNode) DeadEndNode(com.oracle.svm.core.graal.nodes.DeadEndNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) Node(org.graalvm.compiler.graph.Node) MergeNode(org.graalvm.compiler.nodes.MergeNode) ForeignCallNode(org.graalvm.compiler.nodes.extended.ForeignCallNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) IfNode(org.graalvm.compiler.nodes.IfNode)

Example 5 with ControlSplitNode

use of org.graalvm.compiler.nodes.ControlSplitNode 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)

Aggregations

ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)21 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)15 FixedNode (org.graalvm.compiler.nodes.FixedNode)15 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)13 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)11 Node (org.graalvm.compiler.graph.Node)10 EndNode (org.graalvm.compiler.nodes.EndNode)10 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)10 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)9 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)8 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)7 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)5 MergeNode (org.graalvm.compiler.nodes.MergeNode)5 StartNode (org.graalvm.compiler.nodes.StartNode)5 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)4 ValueNode (org.graalvm.compiler.nodes.ValueNode)4 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)3 ProxyNode (org.graalvm.compiler.nodes.ProxyNode)3 ArrayList (java.util.ArrayList)2 DebugCloseable (org.graalvm.compiler.debug.DebugCloseable)2