Search in sources :

Example 11 with ControlSplitNode

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

the class BytecodeParser method createTarget.

@SuppressWarnings("try")
private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
    assert block != null && state != null;
    assert !block.isExceptionEntry || state.stackSize() == 1;
    try (DebugCloseable context = openNodeContext(state, block.startBci)) {
        if (getFirstInstruction(block) == null) {
            /*
                 * This is the first time we see this block as a branch target. Create and return a
                 * placeholder that later can be replaced with a MergeNode when we see this block
                 * again.
                 */
            FixedNode targetNode;
            if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
                setFirstInstruction(block, lastInstr);
                lastInstr = null;
            } else {
                setFirstInstruction(block, graph.add(new BeginNode()));
            }
            targetNode = getFirstInstruction(block);
            Target target = checkLoopExit(targetNode, block, state);
            FixedNode result = target.fixed;
            FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
            setEntryState(block, currentEntryState);
            currentEntryState.clearNonLiveLocals(block, liveness, true);
            debug.log("createTarget %s: first visit, result: %s", block, targetNode);
            return result;
        }
        // We already saw this block before, so we have to merge states.
        if (!getEntryState(block).isCompatibleWith(state)) {
            throw bailout("stacks do not match; bytecodes would not verify");
        }
        if (getFirstInstruction(block) instanceof LoopBeginNode) {
            assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
            /*
                 * Backward loop edge. We need to create a special LoopEndNode and merge with the
                 * loop begin node created before.
                 */
            LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
            LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
            Target target = checkLoopExit(loopEnd, block, state);
            FixedNode result = target.fixed;
            getEntryState(block).merge(loopBegin, target.state);
            debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
            return result;
        }
        assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
        assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
        if (getFirstInstruction(block) instanceof AbstractBeginNode && !(getFirstInstruction(block) instanceof AbstractMergeNode)) {
            /*
                 * This is the second time we see this block. Create the actual MergeNode and the
                 * End Node for the already existing edge.
                 */
            AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block);
            // The EndNode for the already existing edge.
            EndNode end = graph.add(new EndNode());
            // The MergeNode that replaces the placeholder.
            AbstractMergeNode mergeNode = graph.add(new MergeNode());
            FixedNode next = beginNode.next();
            if (beginNode.predecessor() instanceof ControlSplitNode) {
                beginNode.setNext(end);
            } else {
                beginNode.replaceAtPredecessor(end);
                beginNode.safeDelete();
            }
            mergeNode.addForwardEnd(end);
            mergeNode.setNext(next);
            setFirstInstruction(block, mergeNode);
        }
        AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block);
        // The EndNode for the newly merged edge.
        EndNode newEnd = graph.add(new EndNode());
        Target target = checkLoopExit(newEnd, block, state);
        FixedNode result = target.fixed;
        getEntryState(block).merge(mergeNode, target.state);
        mergeNode.addForwardEnd(newEnd);
        debug.log("createTarget %s: merging state, result: %s", block, result);
        return result;
    }
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 12 with ControlSplitNode

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

the class ConvertDeoptimizeToGuardPhase method propagateFixed.

@SuppressWarnings("try")
private void propagateFixed(FixedNode from, StaticDeoptimizingNode deopt, LoweringProvider loweringProvider) {
    Node current = from;
    while (current != null) {
        if (GraalOptions.GuardPriorities.getValue(from.getOptions()) && current instanceof FixedGuardNode) {
            FixedGuardNode otherGuard = (FixedGuardNode) current;
            if (otherGuard.computePriority().isHigherPriorityThan(deopt.computePriority())) {
                moveAsDeoptAfter(otherGuard, deopt);
                return;
            }
        } else if (current instanceof AbstractBeginNode) {
            if (current instanceof AbstractMergeNode) {
                AbstractMergeNode mergeNode = (AbstractMergeNode) current;
                FixedNode next = mergeNode.next();
                while (mergeNode.isAlive()) {
                    AbstractEndNode end = mergeNode.forwardEnds().first();
                    propagateFixed(end, deopt, loweringProvider);
                }
                assert next.isAlive();
                propagateFixed(next, deopt, loweringProvider);
                return;
            } else if (current.predecessor() instanceof IfNode) {
                IfNode ifNode = (IfNode) current.predecessor();
                // Prioritize the source position of the IfNode
                try (DebugCloseable closable = ifNode.withNodeSourcePosition()) {
                    StructuredGraph graph = ifNode.graph();
                    LogicNode conditionNode = ifNode.condition();
                    boolean negateGuardCondition = current == ifNode.trueSuccessor();
                    FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.getReason(), deopt.getAction(), deopt.getSpeculation(), negateGuardCondition));
                    FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
                    AbstractBeginNode survivingSuccessor;
                    if (negateGuardCondition) {
                        survivingSuccessor = ifNode.falseSuccessor();
                    } else {
                        survivingSuccessor = ifNode.trueSuccessor();
                    }
                    graph.removeSplitPropagate(ifNode, survivingSuccessor);
                    Node newGuard = guard;
                    if (survivingSuccessor instanceof LoopExitNode) {
                        newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph);
                    }
                    survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard);
                    graph.getDebug().log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", negateGuardCondition, ifNode, survivingSuccessor);
                    FixedNode next = pred.next();
                    pred.setNext(guard);
                    guard.setNext(next);
                    SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider);
                    survivingSuccessor.simplify(simplifierTool);
                    return;
                }
            } else if (current.predecessor() == null || current.predecessor() instanceof ControlSplitNode) {
                assert current.predecessor() != null || (current instanceof StartNode && current == ((AbstractBeginNode) current).graph().start());
                moveAsDeoptAfter((AbstractBeginNode) current, deopt);
                return;
            }
        }
        current = current.predecessor();
    }
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) StartNode(org.graalvm.compiler.nodes.StartNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StartNode(org.graalvm.compiler.nodes.StartNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) StaticDeoptimizingNode(org.graalvm.compiler.nodes.StaticDeoptimizingNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) SimplifierTool(org.graalvm.compiler.graph.spi.SimplifierTool) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable)

Example 13 with ControlSplitNode

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

the class LoopTransformations method findUnswitchable.

public static List<ControlSplitNode> findUnswitchable(LoopEx loop) {
    List<ControlSplitNode> controls = null;
    ValueNode invariantValue = null;
    for (IfNode ifNode : loop.whole().nodes().filter(IfNode.class)) {
        if (loop.isOutsideLoop(ifNode.condition())) {
            if (controls == null) {
                invariantValue = ifNode.condition();
                controls = new ArrayList<>();
                controls.add(ifNode);
            } else if (ifNode.condition() == invariantValue) {
                controls.add(ifNode);
            }
        }
    }
    if (controls == null) {
        SwitchNode firstSwitch = null;
        for (SwitchNode switchNode : loop.whole().nodes().filter(SwitchNode.class)) {
            if (switchNode.successors().count() > 1 && loop.isOutsideLoop(switchNode.value())) {
                if (controls == null) {
                    firstSwitch = switchNode;
                    invariantValue = switchNode.value();
                    controls = new ArrayList<>();
                    controls.add(switchNode);
                } else if (switchNode.value() == invariantValue && firstSwitch.structureEquals(switchNode)) {
                    // Only collect switches which test the same values in the same order
                    controls.add(switchNode);
                }
            }
        }
    }
    return controls;
}
Also used : ValueNode(org.graalvm.compiler.nodes.ValueNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) IfNode(org.graalvm.compiler.nodes.IfNode) SwitchNode(org.graalvm.compiler.nodes.extended.SwitchNode)

Example 14 with ControlSplitNode

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

the class LoopUnswitchingPhase method logUnswitch.

private static void logUnswitch(LoopEx loop, List<ControlSplitNode> controlSplits) {
    StringBuilder sb = new StringBuilder("Unswitching ");
    sb.append(loop).append(" at ");
    for (ControlSplitNode controlSplit : controlSplits) {
        sb.append(controlSplit).append(" [");
        Iterator<Node> it = controlSplit.successors().iterator();
        while (it.hasNext()) {
            sb.append(controlSplit.probability((AbstractBeginNode) it.next()));
            if (it.hasNext()) {
                sb.append(", ");
            }
        }
        sb.append("]");
    }
    loop.entryPoint().getDebug().log("%s", sb);
}
Also used : ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Node(org.graalvm.compiler.graph.Node) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 15 with ControlSplitNode

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

the class LoopUnswitchingPhase method run.

@Override
protected void run(StructuredGraph graph) {
    DebugContext debug = graph.getDebug();
    if (graph.hasLoops()) {
        boolean unswitched;
        do {
            unswitched = false;
            final LoopsData dataUnswitch = new LoopsData(graph);
            for (LoopEx loop : dataUnswitch.outerFirst()) {
                if (getPolicies().shouldTryUnswitch(loop)) {
                    List<ControlSplitNode> controlSplits = LoopTransformations.findUnswitchable(loop);
                    if (controlSplits != null) {
                        UNSWITCH_CANDIDATES.increment(debug);
                        if (getPolicies().shouldUnswitch(loop, controlSplits)) {
                            if (debug.isLogEnabled()) {
                                logUnswitch(loop, controlSplits);
                            }
                            LoopTransformations.unswitch(loop, controlSplits);
                            debug.dump(DebugContext.DETAILED_LEVEL, graph, "After unswitch %s", controlSplits);
                            UNSWITCHED.increment(debug);
                            unswitched = true;
                            break;
                        }
                    }
                } else {
                    UNSWITCH_EARLY_REJECTS.increment(debug);
                }
            }
        } while (unswitched);
    }
}
Also used : LoopsData(org.graalvm.compiler.loop.LoopsData) LoopEx(org.graalvm.compiler.loop.LoopEx) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DebugContext(org.graalvm.compiler.debug.DebugContext)

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