Search in sources :

Example 1 with MemoryAnchorNode

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

the class SnippetTemplate method instantiate.

/**
 * Replaces a given floating node with this specialized snippet.
 *
 * This snippet must be pure data-flow
 *
 * @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
 */
@SuppressWarnings("try")
public void instantiate(MetaAccessProvider metaAccess, FloatingNode replacee, UsageReplacer replacer, 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();
        assert entryPointNode.next() == (memoryAnchor == null ? returnNode : memoryAnchor) : entryPointNode.next();
        StructuredGraph replaceeGraph = replacee.graph();
        EconomicMap<Node, Node> replacements = bind(replaceeGraph, metaAccess, args);
        MemoryAnchorNode anchorDuplicate = null;
        if (memoryAnchor != null) {
            anchorDuplicate = replaceeGraph.add(new MemoryAnchorNode());
            replacements.put(memoryAnchor, anchorDuplicate);
        }
        List<Node> floatingNodes = new ArrayList<>(nodes.size() - 2);
        for (Node n : nodes) {
            if (n != entryPointNode && n != returnNode) {
                floatingNodes.add(n);
            }
        }
        UnmodifiableEconomicMap<Node, Node> duplicates = inlineSnippet(replacee, debug, replaceeGraph, replacements);
        rewireFrameStates(replacee, duplicates);
        updateStamps(replacee, duplicates);
        rewireMemoryGraph(replacee, duplicates);
        assert anchorDuplicate == null || anchorDuplicate.isDeleted();
        // Replace all usages of the replacee with the value returned by the snippet
        ValueNode returnValue = (ValueNode) duplicates.get(returnNode.result());
        replacer.replace(replacee, returnValue);
        debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After lowering %s with %s", replacee, this);
    }
}
Also used : StartNode(org.graalvm.compiler.nodes.StartNode) 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) ArrayList(java.util.ArrayList) ValueNode(org.graalvm.compiler.nodes.ValueNode) MemoryAnchorNode(org.graalvm.compiler.nodes.memory.MemoryAnchorNode) DebugContext(org.graalvm.compiler.debug.DebugContext) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable)

Example 2 with MemoryAnchorNode

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

the class SnippetTemplate method rewireMemoryGraph.

private void rewireMemoryGraph(ValueNode replacee, UnmodifiableEconomicMap<Node, Node> duplicates) {
    if (replacee.graph().isAfterFloatingReadPhase()) {
        // rewire outgoing memory edges
        replaceMemoryUsages(replacee, new MemoryOutputMap(replacee, duplicates));
        if (returnNode != null) {
            ReturnNode ret = (ReturnNode) duplicates.get(returnNode);
            if (ret != null) {
                MemoryMapNode memoryMap = ret.getMemoryMap();
                if (memoryMap != null) {
                    ret.setMemoryMap(null);
                    memoryMap.safeDelete();
                }
            }
        }
        if (memoryAnchor != null) {
            // rewire incoming memory edges
            MemoryAnchorNode memoryDuplicate = (MemoryAnchorNode) duplicates.get(memoryAnchor);
            replaceMemoryUsages(memoryDuplicate, new MemoryInputMap(replacee));
            if (memoryDuplicate.hasNoUsages()) {
                if (memoryDuplicate.next() != null) {
                    memoryDuplicate.graph().removeFixed(memoryDuplicate);
                } else {
                    // this was a dummy memory node used when instantiating pure data-flow
                    // snippets: it was not attached to the control flow.
                    memoryDuplicate.safeDelete();
                }
            }
        }
    }
}
Also used : ReturnNode(org.graalvm.compiler.nodes.ReturnNode) MemoryMapNode(org.graalvm.compiler.nodes.memory.MemoryMapNode) MemoryAnchorNode(org.graalvm.compiler.nodes.memory.MemoryAnchorNode)

Example 3 with MemoryAnchorNode

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

the class SnippetTemplate method assertSnippetKills.

private boolean assertSnippetKills(ValueNode replacee) {
    if (!replacee.graph().isAfterFloatingReadPhase()) {
        // no floating reads yet, ignore locations created while lowering
        return true;
    }
    if (returnNode == null) {
        // The snippet terminates control flow
        return true;
    }
    MemoryMapNode memoryMap = returnNode.getMemoryMap();
    if (memoryMap == null || memoryMap.isEmpty()) {
        // there are no kills in the snippet graph
        return true;
    }
    EconomicSet<LocationIdentity> kills = EconomicSet.create(Equivalence.DEFAULT);
    kills.addAll(memoryMap.getLocations());
    if (replacee instanceof MemoryCheckpoint.Single) {
        // check if some node in snippet graph also kills the same location
        LocationIdentity locationIdentity = ((MemoryCheckpoint.Single) replacee).getLocationIdentity();
        if (locationIdentity.isAny()) {
            assert !(memoryMap.getLastLocationAccess(any()) instanceof MemoryAnchorNode) : replacee + " kills ANY_LOCATION, but snippet does not";
            // if the replacee kills ANY_LOCATION, the snippet can kill arbitrary locations
            return true;
        }
        assert kills.contains(locationIdentity) : replacee + " kills " + locationIdentity + ", but snippet doesn't contain a kill to this location";
        kills.remove(locationIdentity);
    }
    assert !(replacee instanceof MemoryCheckpoint.Multi) : replacee + " multi not supported (yet)";
    // remove ANY_LOCATION if it's just a kill by the start node
    if (memoryMap.getLastLocationAccess(any()) instanceof MemoryAnchorNode) {
        kills.remove(any());
    }
    // node can only lower to a ANY_LOCATION kill if the replacee also kills ANY_LOCATION
    assert !kills.contains(any()) : "snippet graph contains a kill to ANY_LOCATION, but replacee (" + replacee + ") doesn't kill ANY_LOCATION.  kills: " + kills;
    /*
         * Kills to private locations are safe, since there can be no floating read to these
         * locations except reads that are introduced by the snippet itself or related snippets in
         * the same lowering round. These reads are anchored to a MemoryAnchor at the beginning of
         * their snippet, so they can not float above a kill in another instance of the same
         * snippet.
         */
    for (LocationIdentity p : this.info.privateLocations) {
        kills.remove(p);
    }
    assert kills.isEmpty() : "snippet graph kills non-private locations " + kills + " that replacee (" + replacee + ") doesn't kill";
    return true;
}
Also used : MemoryMapNode(org.graalvm.compiler.nodes.memory.MemoryMapNode) LocationIdentity(org.graalvm.word.LocationIdentity) MemoryAnchorNode(org.graalvm.compiler.nodes.memory.MemoryAnchorNode)

Aggregations

MemoryAnchorNode (org.graalvm.compiler.nodes.memory.MemoryAnchorNode)3 MemoryMapNode (org.graalvm.compiler.nodes.memory.MemoryMapNode)3 ReturnNode (org.graalvm.compiler.nodes.ReturnNode)2 ArrayList (java.util.ArrayList)1 DebugCloseable (org.graalvm.compiler.debug.DebugCloseable)1 DebugContext (org.graalvm.compiler.debug.DebugContext)1 Node (org.graalvm.compiler.graph.Node)1 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)1 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)1 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)1 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)1 DeoptimizingNode (org.graalvm.compiler.nodes.DeoptimizingNode)1 FixedNode (org.graalvm.compiler.nodes.FixedNode)1 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)1 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)1 MergeNode (org.graalvm.compiler.nodes.MergeNode)1 ParameterNode (org.graalvm.compiler.nodes.ParameterNode)1 PhiNode (org.graalvm.compiler.nodes.PhiNode)1 StartNode (org.graalvm.compiler.nodes.StartNode)1 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)1