Search in sources :

Example 1 with MemoryCheckpoint

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

the class SnippetTemplate method instantiate.

/**
 * Replaces a given fixed 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 args the arguments to be bound to the flattened positional parameters of the snippet
 * @param killReplacee is true, the replacee node is deleted
 * @return the map of duplicated nodes (original -> duplicate)
 */
@SuppressWarnings("try")
public UnmodifiableEconomicMap<Node, Node> instantiate(MetaAccessProvider metaAccess, FixedNode replacee, UsageReplacer replacer, Arguments args, boolean killReplacee) {
    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, AbstractBeginNode.prevBegin(replacee));
        UnmodifiableEconomicMap<Node, Node> duplicates = inlineSnippet(replacee, debug, replaceeGraph, replacements);
        // Re-wire the control flow graph around the replacee
        FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
        replacee.replaceAtPredecessor(firstCFGNodeDuplicate);
        rewireFrameStates(replacee, duplicates);
        if (replacee instanceof DeoptimizingNode) {
            DeoptimizingNode replaceeDeopt = (DeoptimizingNode) replacee;
            FrameState stateBefore = null;
            FrameState stateDuring = null;
            FrameState stateAfter = null;
            if (replaceeDeopt.canDeoptimize()) {
                if (replaceeDeopt instanceof DeoptimizingNode.DeoptBefore) {
                    stateBefore = ((DeoptimizingNode.DeoptBefore) replaceeDeopt).stateBefore();
                }
                if (replaceeDeopt instanceof DeoptimizingNode.DeoptDuring) {
                    stateDuring = ((DeoptimizingNode.DeoptDuring) replaceeDeopt).stateDuring();
                }
                if (replaceeDeopt instanceof DeoptimizingNode.DeoptAfter) {
                    stateAfter = ((DeoptimizingNode.DeoptAfter) replaceeDeopt).stateAfter();
                }
            }
            for (DeoptimizingNode deoptNode : deoptNodes) {
                DeoptimizingNode deoptDup = (DeoptimizingNode) duplicates.get(deoptNode.asNode());
                if (deoptDup.canDeoptimize()) {
                    if (deoptDup instanceof DeoptimizingNode.DeoptBefore) {
                        ((DeoptimizingNode.DeoptBefore) deoptDup).setStateBefore(stateBefore);
                    }
                    if (deoptDup instanceof DeoptimizingNode.DeoptDuring) {
                        DeoptimizingNode.DeoptDuring deoptDupDuring = (DeoptimizingNode.DeoptDuring) deoptDup;
                        if (stateDuring != null) {
                            deoptDupDuring.setStateDuring(stateDuring);
                        } else if (stateAfter != null) {
                            deoptDupDuring.computeStateDuring(stateAfter);
                        } else if (stateBefore != null) {
                            assert !deoptDupDuring.hasSideEffect() : "can't use stateBefore as stateDuring for state split " + deoptDupDuring;
                            deoptDupDuring.setStateDuring(stateBefore);
                        }
                    }
                    if (deoptDup instanceof DeoptimizingNode.DeoptAfter) {
                        DeoptimizingNode.DeoptAfter deoptDupAfter = (DeoptimizingNode.DeoptAfter) deoptDup;
                        if (stateAfter != null) {
                            deoptDupAfter.setStateAfter(stateAfter);
                        } else {
                            assert !deoptDupAfter.hasSideEffect() : "can't use stateBefore as stateAfter for state split " + deoptDupAfter;
                            deoptDupAfter.setStateAfter(stateBefore);
                        }
                    }
                }
            }
        }
        updateStamps(replacee, duplicates);
        rewireMemoryGraph(replacee, duplicates);
        // Replace all usages of the replacee with the value returned by the snippet
        ValueNode returnValue = null;
        if (returnNode != null && !(replacee instanceof ControlSinkNode)) {
            ReturnNode returnDuplicate = (ReturnNode) duplicates.get(returnNode);
            returnValue = returnDuplicate.result();
            if (returnValue == null && replacee.usages().isNotEmpty() && replacee instanceof MemoryCheckpoint) {
                replacer.replace(replacee, null);
            } else {
                assert returnValue != null || replacee.hasNoUsages();
                replacer.replace(replacee, returnValue);
            }
            if (returnDuplicate.isAlive()) {
                FixedNode next = null;
                if (replacee instanceof FixedWithNextNode) {
                    FixedWithNextNode fwn = (FixedWithNextNode) replacee;
                    next = fwn.next();
                    fwn.setNext(null);
                }
                returnDuplicate.replaceAndDelete(next);
            }
        }
        if (killReplacee) {
            // Remove the replacee from its graph
            GraphUtil.killCFG(replacee);
        }
        debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
        return duplicates;
    }
}
Also used : StartNode(org.graalvm.compiler.nodes.StartNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) 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) DebugContext(org.graalvm.compiler.debug.DebugContext) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) DeoptimizingNode(org.graalvm.compiler.nodes.DeoptimizingNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) ValueNode(org.graalvm.compiler.nodes.ValueNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable)

Example 2 with MemoryCheckpoint

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

the class MemoryScheduleVerification method processBlock.

@Override
protected EconomicSet<FloatingReadNode> processBlock(Block block, EconomicSet<FloatingReadNode> currentState) {
    AbstractBeginNode beginNode = block.getBeginNode();
    if (beginNode instanceof AbstractMergeNode) {
        AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode;
        for (PhiNode phi : abstractMergeNode.phis()) {
            if (phi instanceof MemoryPhiNode) {
                MemoryPhiNode memoryPhiNode = (MemoryPhiNode) phi;
                addFloatingReadUsages(currentState, memoryPhiNode);
            }
        }
    }
    for (Node n : blockToNodesMap.get(block)) {
        if (n instanceof MemoryCheckpoint) {
            if (n instanceof MemoryCheckpoint.Single) {
                MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n;
                processLocation(n, single.getLocationIdentity(), currentState);
            } else if (n instanceof MemoryCheckpoint.Multi) {
                MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n;
                for (LocationIdentity location : multi.getLocationIdentities()) {
                    processLocation(n, location, currentState);
                }
            }
            addFloatingReadUsages(currentState, n);
        } else if (n instanceof MemoryNode) {
            addFloatingReadUsages(currentState, n);
        } else if (n instanceof FloatingReadNode) {
            FloatingReadNode floatingReadNode = (FloatingReadNode) n;
            if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) {
                if (currentState.contains(floatingReadNode)) {
                    // Floating read was found in the state.
                    currentState.remove(floatingReadNode);
                } else {
                    throw new RuntimeException("Floating read node " + n + " was not found in the state, i.e., it was killed by a memory check point before its place in the schedule. Block=" + block + ", block begin: " + block.getBeginNode() + " block loop: " + block.getLoop() + ", " + blockToNodesMap.get(block).get(0));
                }
            }
        }
    }
    return currentState;
}
Also used : MemoryNode(org.graalvm.compiler.nodes.memory.MemoryNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) MemoryNode(org.graalvm.compiler.nodes.memory.MemoryNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) Node(org.graalvm.compiler.graph.Node) PhiNode(org.graalvm.compiler.nodes.PhiNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) LocationIdentity(org.graalvm.word.LocationIdentity)

Example 3 with MemoryCheckpoint

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

the class LoweringPhase method checkPostNodeLowering.

/**
 * Checks that lowering of a given node did not introduce any new {@link Lowerable} nodes that
 * could be lowered in the current {@link LoweringPhase}. Such nodes must be recursively lowered
 * as part of lowering {@code node}.
 *
 * @param node a node that was just lowered
 * @param preLoweringMark the graph mark before {@code node} was lowered
 * @param unscheduledUsages set of {@code node}'s usages that were unscheduled before it was
 *            lowered
 * @throws AssertionError if the check fails
 */
private static boolean checkPostNodeLowering(Node node, LoweringToolImpl loweringTool, Mark preLoweringMark, Collection<Node> unscheduledUsages) {
    StructuredGraph graph = (StructuredGraph) node.graph();
    Mark postLoweringMark = graph.getMark();
    NodeIterable<Node> newNodesAfterLowering = graph.getNewNodes(preLoweringMark);
    if (node instanceof FloatingNode) {
        if (!unscheduledUsages.isEmpty()) {
            for (Node n : newNodesAfterLowering) {
                assert !(n instanceof FixedNode) : node.graph() + ": cannot lower floatable node " + node + " as it introduces fixed node(s) but has the following unscheduled usages: " + unscheduledUsages;
            }
        }
    }
    for (Node n : newNodesAfterLowering) {
        if (n instanceof Lowerable) {
            ((Lowerable) n).lower(loweringTool);
            Mark mark = graph.getMark();
            assert postLoweringMark.equals(mark) : graph + ": lowering of " + node + " produced lowerable " + n + " that should have been recursively lowered as it introduces these new nodes: " + graph.getNewNodes(postLoweringMark).snapshot();
        }
        if (graph.isAfterFloatingReadPhase() && n instanceof MemoryCheckpoint && !(node instanceof MemoryCheckpoint) && !(node instanceof ControlSinkNode)) {
            /*
                 * The lowering introduced a MemoryCheckpoint but the current node isn't a
                 * checkpoint. This is only OK if the locations involved don't affect the memory
                 * graph or if the new kill location doesn't connect into the existing graph.
                 */
            boolean isAny = false;
            if (n instanceof MemoryCheckpoint.Single) {
                isAny = ((MemoryCheckpoint.Single) n).getLocationIdentity().isAny();
            } else {
                for (LocationIdentity ident : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) {
                    if (ident.isAny()) {
                        isAny = true;
                    }
                }
            }
            if (isAny && n instanceof FixedWithNextNode) {
                /*
                     * Check if the next kill location leads directly to a ControlSinkNode in the
                     * new part of the graph. This is a fairly conservative test that could be made
                     * more general if required.
                     */
                FixedWithNextNode cur = (FixedWithNextNode) n;
                while (cur != null && graph.isNew(preLoweringMark, cur)) {
                    if (cur.next() instanceof ControlSinkNode) {
                        isAny = false;
                        break;
                    }
                    if (cur.next() instanceof FixedWithNextNode) {
                        cur = (FixedWithNextNode) cur.next();
                    } else {
                        break;
                    }
                }
            }
            assert !isAny : node + " " + n;
        }
    }
    return true;
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) GuardedNode(org.graalvm.compiler.nodes.extended.GuardedNode) GuardingNode(org.graalvm.compiler.nodes.extended.GuardingNode) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) AnchoringNode(org.graalvm.compiler.nodes.extended.AnchoringNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) Mark(org.graalvm.compiler.graph.Graph.Mark) FixedNode(org.graalvm.compiler.nodes.FixedNode) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) LocationIdentity(org.graalvm.word.LocationIdentity) Lowerable(org.graalvm.compiler.nodes.spi.Lowerable)

Aggregations

Node (org.graalvm.compiler.graph.Node)3 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)3 PhiNode (org.graalvm.compiler.nodes.PhiNode)3 MemoryCheckpoint (org.graalvm.compiler.nodes.memory.MemoryCheckpoint)3 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)2 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)2 FixedNode (org.graalvm.compiler.nodes.FixedNode)2 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)2 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)2 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)2 ValueNode (org.graalvm.compiler.nodes.ValueNode)2 FloatingNode (org.graalvm.compiler.nodes.calc.FloatingNode)2 MemoryNode (org.graalvm.compiler.nodes.memory.MemoryNode)2 MemoryPhiNode (org.graalvm.compiler.nodes.memory.MemoryPhiNode)2 LocationIdentity (org.graalvm.word.LocationIdentity)2 DebugCloseable (org.graalvm.compiler.debug.DebugCloseable)1 DebugContext (org.graalvm.compiler.debug.DebugContext)1 Mark (org.graalvm.compiler.graph.Graph.Mark)1 BeginNode (org.graalvm.compiler.nodes.BeginNode)1 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)1