Search in sources :

Example 26 with FixedWithNextNode

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

the class EffectsClosure method applyEffects.

@Override
public void applyEffects() {
    final StructuredGraph graph = cfg.graph;
    final ArrayList<Node> obsoleteNodes = new ArrayList<>(0);
    final ArrayList<GraphEffectList> effectList = new ArrayList<>();
    /*
         * Effects are applied during a ordered iteration over the blocks to apply them in the
         * correct order, e.g., apply the effect that adds a node to the graph before the node is
         * used.
         */
    BlockIteratorClosure<Void> closure = new BlockIteratorClosure<Void>() {

        @Override
        protected Void getInitialState() {
            return null;
        }

        private void apply(GraphEffectList effects) {
            if (effects != null && !effects.isEmpty()) {
                effectList.add(effects);
            }
        }

        @Override
        protected Void processBlock(Block block, Void currentState) {
            apply(blockEffects.get(block));
            return currentState;
        }

        @Override
        protected Void merge(Block merge, List<Void> states) {
            return null;
        }

        @Override
        protected Void cloneState(Void oldState) {
            return oldState;
        }

        @Override
        protected List<Void> processLoop(Loop<Block> loop, Void initialState) {
            LoopInfo<Void> info = ReentrantBlockIterator.processLoop(this, loop, initialState);
            apply(loopMergeEffects.get(loop));
            return info.exitStates;
        }
    };
    ReentrantBlockIterator.apply(closure, cfg.getStartBlock());
    for (GraphEffectList effects : effectList) {
        effects.apply(graph, obsoleteNodes, false);
    }
    /*
         * Effects that modify the cfg (e.g., removing a branch for an if that got a constant
         * condition) need to be performed after all other effects, because they change phi value
         * indexes.
         */
    for (GraphEffectList effects : effectList) {
        effects.apply(graph, obsoleteNodes, true);
    }
    debug.dump(DebugContext.DETAILED_LEVEL, graph, "After applying effects");
    assert VirtualUtil.assertNonReachable(graph, obsoleteNodes);
    for (Node node : obsoleteNodes) {
        if (node.isAlive() && node.hasNoUsages()) {
            if (node instanceof FixedWithNextNode) {
                assert ((FixedWithNextNode) node).next() == null;
            }
            node.replaceAtUsages(null);
            GraphUtil.killWithUnusedFloatingInputs(node);
        }
    }
}
Also used : Loop(org.graalvm.compiler.core.common.cfg.Loop) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) BlockIteratorClosure(org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) AllocatedObjectNode(org.graalvm.compiler.nodes.virtual.AllocatedObjectNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) BoxNode(org.graalvm.compiler.nodes.extended.BoxNode) IfNode(org.graalvm.compiler.nodes.IfNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) 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) ArrayList(java.util.ArrayList) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) Block(org.graalvm.compiler.nodes.cfg.Block) ArrayList(java.util.ArrayList) List(java.util.List)

Example 27 with FixedWithNextNode

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

the class EffectsClosure method processBlock.

@Override
protected BlockT processBlock(Block block, BlockT state) {
    if (!state.isDead()) {
        GraphEffectList effects = blockEffects.get(block);
        /*
             * If we enter an if branch that is known to be unreachable, we mark it as dead and
             * cease to do any more analysis on it. At merges, these dead branches will be ignored.
             */
        if (block.getBeginNode().predecessor() instanceof IfNode) {
            IfNode ifNode = (IfNode) block.getBeginNode().predecessor();
            LogicNode condition = ifNode.condition();
            Node alias = getScalarAlias(condition);
            if (alias instanceof LogicConstantNode) {
                LogicConstantNode constant = (LogicConstantNode) alias;
                boolean isTrueSuccessor = block.getBeginNode() == ifNode.trueSuccessor();
                if (constant.getValue() != isTrueSuccessor) {
                    state.markAsDead();
                    effects.killIfBranch(ifNode, constant.getValue());
                    return state;
                }
            }
        }
        OptionValues options = block.getBeginNode().getOptions();
        VirtualUtil.trace(options, debug, "\nBlock: %s, preds: %s, succ: %s (", block, block.getPredecessors(), block.getSuccessors());
        // a lastFixedNode is needed in case we want to insert fixed nodes
        FixedWithNextNode lastFixedNode = null;
        Iterable<? extends Node> nodes = schedule != null ? schedule.getBlockToNodesMap().get(block) : block.getNodes();
        for (Node node : nodes) {
            // reset the aliases (may be non-null due to iterative loop processing)
            aliases.set(node, null);
            if (node instanceof LoopExitNode) {
                LoopExitNode loopExit = (LoopExitNode) node;
                for (ProxyNode proxy : loopExit.proxies()) {
                    aliases.set(proxy, null);
                    changed |= processNode(proxy, state, effects, lastFixedNode) && isSignificantNode(node);
                }
                processLoopExit(loopExit, loopEntryStates.get(loopExit.loopBegin()), state, blockEffects.get(block));
            }
            changed |= processNode(node, state, effects, lastFixedNode) && isSignificantNode(node);
            if (node instanceof FixedWithNextNode) {
                lastFixedNode = (FixedWithNextNode) node;
            }
            if (state.isDead()) {
                break;
            }
        }
        VirtualUtil.trace(options, debug, ")\n    end state: %s\n", state);
    }
    return state;
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) OptionValues(org.graalvm.compiler.options.OptionValues) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) AllocatedObjectNode(org.graalvm.compiler.nodes.virtual.AllocatedObjectNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) BoxNode(org.graalvm.compiler.nodes.extended.BoxNode) IfNode(org.graalvm.compiler.nodes.IfNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) 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) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) IfNode(org.graalvm.compiler.nodes.IfNode)

Example 28 with FixedWithNextNode

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

the class HostedBytecodeParser method finishInstruction.

/**
 * Insert deopt entries after all state splits.
 */
@Override
protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder stateBuilder) {
    if (getMethod().compilationInfo.isDeoptTarget() && !parsingIntrinsic()) {
        FrameState stateAfter = null;
        if (instr instanceof StateSplit && !(instr instanceof DeoptEntryNode)) {
            /*
                 * The regular case: the instruction is a state split and we insert a DeoptEntryNode
                 * right after it.
                 */
            StateSplit stateSplit = (StateSplit) instr;
            stateAfter = stateSplit.stateAfter();
        } else if (instr instanceof AbstractBeginNode) {
            /*
                 * We are at a block begin. If the block predecessor is a LoopExitNode or an
                 * InvokeWithException (both are state splits), we didn't inserted a deopt entry
                 * yet. So we do it at the begin of a block.
                 *
                 * Note that this only happens if the LoopExitNode/InvokeWithException is the
                 * _single_ predcessor of this block. In case of multiple predecessors, the block
                 * starts with a MergeNode and this is handled like a regular case.
                 */
            Node predecessor = instr.predecessor();
            if (predecessor instanceof KillingBeginNode) {
                /*
                     * This is between an InvokeWithException and the BlockPlaceholderNode.
                     */
                predecessor = predecessor.predecessor();
            }
            if (predecessor instanceof StateSplit && !(predecessor instanceof DeoptEntryNode)) {
                stateAfter = ((StateSplit) predecessor).stateAfter();
            }
        }
        boolean needsDeoptEntry = false;
        boolean needsProxies = false;
        if (stateAfter != null) {
            if (getMethod().compilationInfo.isDeoptEntry(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException())) {
                needsDeoptEntry = true;
                needsProxies = true;
            } else if (instr.predecessor() instanceof Invoke && getMethod().compilationInfo.isDeoptEntry(((Invoke) instr.predecessor()).bci(), true, false)) {
                /*
                     * Invoke nodes can be implicit deoptimization entry points. But we cannot
                     * anchor proxy nodes on invocations: The invoke has two successors (normal and
                     * exception handler), and we need to proxy values at the beginning of both.
                     */
                needsProxies = true;
            } else if (instr instanceof ExceptionObjectNode && getMethod().compilationInfo.isDeoptEntry(((ExceptionObjectNode) instr).stateAfter().bci, true, false)) {
                /*
                     * The predecessor of the ExceptionObjectNode will be an Invoke, but the Invoke
                     * has not been created yet. So the check above for the predecessor does not
                     * trigger.
                     */
                needsProxies = true;
            }
        }
        if (needsProxies) {
            long encodedBci = FrameInfoEncoder.encodeBci(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException());
            DeoptProxyAnchorNode existingDeoptEntry = deoptEntries.get(encodedBci);
            if (existingDeoptEntry != STICKY_DEOPT_ENTRY) {
                if (existingDeoptEntry != null) {
                    /*
                         * Some state splits (i.e. MergeNode and DispatchBeginNode) do not have a
                         * correspondent byte code. Therefore there can be a previously added deopt
                         * entry with the same BCI. For MergeNodes we replace the previous entry
                         * because the new frame state has less live locals.
                         */
                    existingDeoptEntry.replaceAtUsages(null);
                    graph.removeFixed(existingDeoptEntry);
                    deoptEntries.remove(encodedBci);
                    if (existingDeoptEntry instanceof DeoptEntryNode) {
                        /*
                             * We already had a DeoptEntryNode registered earlier for some reason,
                             * so be conservative and create one again (and not just a
                             * DeoptProxyAnchorNode).
                             */
                        needsDeoptEntry = true;
                    }
                }
                assert !deoptEntries.containsKey(encodedBci) : "duplicate deopt entry for encoded BCI " + encodedBci;
                DeoptProxyAnchorNode deoptEntry = createDeoptEntry(stateBuilder, stateAfter, !needsDeoptEntry);
                if (instr instanceof LoopBeginNode) {
                    /*
                         * Loop headers to not have their own bci. Never move a deopt entry for the
                         * loop header down, e.g., into a loop end (that might then end up to be
                         * dead code).
                         */
                    deoptEntries.put(encodedBci, STICKY_DEOPT_ENTRY);
                } else {
                    deoptEntries.put(encodedBci, deoptEntry);
                }
                assert instr.next() == null : "cannot append instruction to instruction which isn't end (" + instr + "->" + instr.next() + ")";
                instr.setNext(deoptEntry);
                return deoptEntry;
            }
        }
    }
    return super.finishInstruction(instr, stateBuilder);
}
Also used : DeoptProxyAnchorNode(com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) DeoptEntryNode(com.oracle.svm.core.graal.nodes.DeoptEntryNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) SubstrateMethodCallTargetNode(com.oracle.svm.hosted.nodes.SubstrateMethodCallTargetNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) DeoptEntryNode(com.oracle.svm.core.graal.nodes.DeoptEntryNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) DeoptProxyAnchorNode(com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) DeoptProxyNode(com.oracle.svm.hosted.nodes.DeoptProxyNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) FrameState(org.graalvm.compiler.nodes.FrameState) StateSplit(org.graalvm.compiler.nodes.StateSplit) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke)

Example 29 with FixedWithNextNode

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

the class SnippetTemplate method instantiate.

/**
 * Replaces a given floating node with this specialized snippet.
 *
 * @param metaAccess
 * @param replacee the node that will be replaced
 * @param replacer object that replaces the usages of {@code replacee}
 * @param tool lowering tool used to insert the snippet into the control-flow
 * @param args the arguments to be bound to the flattened positional parameters of the snippet
 */
@SuppressWarnings("try")
public void instantiate(MetaAccessProvider metaAccess, FloatingNode replacee, UsageReplacer replacer, LoweringTool tool, Arguments args) {
    DebugContext debug = replacee.getDebug();
    assert assertSnippetKills(replacee);
    try (DebugCloseable a = args.info.instantiationTimer.start(debug)) {
        args.info.instantiationCounter.increment(debug);
        // Inline the snippet nodes, replacing parameters with the given args in the process
        StartNode entryPointNode = snippet.start();
        FixedNode firstCFGNode = entryPointNode.next();
        StructuredGraph replaceeGraph = replacee.graph();
        EconomicMap<Node, Node> replacements = bind(replaceeGraph, metaAccess, args);
        replacements.put(entryPointNode, tool.getCurrentGuardAnchor().asNode());
        UnmodifiableEconomicMap<Node, Node> duplicates = inlineSnippet(replacee, debug, replaceeGraph, replacements);
        FixedWithNextNode lastFixedNode = tool.lastFixedNode();
        assert lastFixedNode != null && lastFixedNode.isAlive() : replaceeGraph + " lastFixed=" + lastFixedNode;
        FixedNode next = lastFixedNode.next();
        lastFixedNode.setNext(null);
        FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
        replaceeGraph.addAfterFixed(lastFixedNode, firstCFGNodeDuplicate);
        rewireFrameStates(replacee, duplicates);
        updateStamps(replacee, duplicates);
        rewireMemoryGraph(replacee, duplicates);
        // Replace all usages of the replacee with the value returned by the snippet
        ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
        ValueNode returnValue = returnDuplicate.result();
        assert returnValue != null || replacee.hasNoUsages();
        replacer.replace(replacee, returnValue);
        if (returnDuplicate.isAlive()) {
            returnDuplicate.replaceAndDelete(next);
        }
        debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
    }
}
Also used : StartNode(org.graalvm.compiler.nodes.StartNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) MemoryNode(org.graalvm.compiler.nodes.memory.MemoryNode) MemoryAnchorNode(org.graalvm.compiler.nodes.memory.MemoryAnchorNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) ExplodeLoopNode(org.graalvm.compiler.replacements.nodes.ExplodeLoopNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) LoadSnippetVarargParameterNode(org.graalvm.compiler.replacements.nodes.LoadSnippetVarargParameterNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoadIndexedNode(org.graalvm.compiler.nodes.java.LoadIndexedNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) DeoptimizingNode(org.graalvm.compiler.nodes.DeoptimizingNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) StartNode(org.graalvm.compiler.nodes.StartNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) StoreIndexedNode(org.graalvm.compiler.nodes.java.StoreIndexedNode) MemoryMapNode(org.graalvm.compiler.nodes.memory.MemoryMapNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) DebugContext(org.graalvm.compiler.debug.DebugContext) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable) FixedNode(org.graalvm.compiler.nodes.FixedNode)

Example 30 with FixedWithNextNode

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

Aggregations

FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)57 FixedNode (org.graalvm.compiler.nodes.FixedNode)33 ValueNode (org.graalvm.compiler.nodes.ValueNode)29 Node (org.graalvm.compiler.graph.Node)26 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)22 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)21 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)20 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)13 EndNode (org.graalvm.compiler.nodes.EndNode)12 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)12 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)10 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)9 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)9 Invoke (org.graalvm.compiler.nodes.Invoke)9 LogicNode (org.graalvm.compiler.nodes.LogicNode)9 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)9 PhiNode (org.graalvm.compiler.nodes.PhiNode)9 IfNode (org.graalvm.compiler.nodes.IfNode)8 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)7 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)7