Search in sources :

Example 1 with MemoryKill

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

the class FloatingReadPhase method mergeMemoryMaps.

public static MemoryMapImpl mergeMemoryMaps(AbstractMergeNode merge, List<? extends MemoryMap> states) {
    MemoryMapImpl newState = new MemoryMapImpl();
    EconomicSet<LocationIdentity> keys = EconomicSet.create(Equivalence.DEFAULT);
    for (MemoryMap other : states) {
        keys.addAll(other.getLocations());
    }
    assert checkNoImmutableLocations(keys);
    for (LocationIdentity key : keys) {
        int mergedStatesCount = 0;
        boolean isPhi = false;
        MemoryKill merged = null;
        for (MemoryMap state : states) {
            MemoryKill last = state.getLastLocationAccess(key);
            if (isPhi) {
                // Fortify: Suppress Null Deference false positive (`isPhi == true` implies
                // `merged != null`)
                ((MemoryPhiNode) merged).addInput(ValueNodeUtil.asNode(last));
            } else {
                if (merged == last) {
                // nothing to do
                } else if (merged == null) {
                    merged = last;
                } else {
                    MemoryPhiNode phi = merge.graph().addWithoutUnique(new MemoryPhiNode(merge, key));
                    for (int j = 0; j < mergedStatesCount; j++) {
                        phi.addInput(ValueNodeUtil.asNode(merged));
                    }
                    phi.addInput(ValueNodeUtil.asNode(last));
                    merged = phi;
                    isPhi = true;
                }
            }
            mergedStatesCount++;
        }
        newState.getMap().put(key, merged);
    }
    return newState;
}
Also used : MemoryMap(org.graalvm.compiler.nodes.memory.MemoryMap) SingleMemoryKill(org.graalvm.compiler.nodes.memory.SingleMemoryKill) MultiMemoryKill(org.graalvm.compiler.nodes.memory.MultiMemoryKill) MemoryKill(org.graalvm.compiler.nodes.memory.MemoryKill) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) LocationIdentity(org.graalvm.word.LocationIdentity)

Example 2 with MemoryKill

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

the class ScheduleVerification 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);
            }
        }
    }
    if (beginNode instanceof LoopExitNode) {
        LoopExitNode loopExitNode = (LoopExitNode) beginNode;
        for (ProxyNode proxy : loopExitNode.proxies()) {
            if (proxy instanceof MemoryProxyNode) {
                MemoryProxyNode memoryProxyNode = (MemoryProxyNode) proxy;
                addFloatingReadUsages(currentState, memoryProxyNode);
            }
        }
    }
    for (Node n : blockToNodesMap.get(block)) {
        if (n instanceof MemoryKill) {
            if (n instanceof SingleMemoryKill) {
                SingleMemoryKill single = (SingleMemoryKill) n;
                processLocation(n, single.getKilledLocationIdentity(), currentState);
            } else if (n instanceof MultiMemoryKill) {
                MultiMemoryKill multi = (MultiMemoryKill) n;
                for (LocationIdentity location : multi.getKilledLocationIdentities()) {
                    processLocation(n, location, currentState);
                }
            }
            addFloatingReadUsages(currentState, n);
        } else if (n instanceof MemoryAccess) {
            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));
                }
            }
        }
        assert nodeMap.get(n) == block;
        if (graph.isBeforeStage(StageFlag.VALUE_PROXY_REMOVAL) && block.getLoop() != null && !(n instanceof VirtualState)) {
            for (Node usage : n.usages()) {
                Node usageNode = usage;
                if (usageNode instanceof PhiNode) {
                    PhiNode phiNode = (PhiNode) usage;
                    usageNode = phiNode.merge();
                }
                if (usageNode instanceof LoopExitNode) {
                    LoopExitNode loopExitNode = (LoopExitNode) usageNode;
                    if (loopExitNode.loopBegin() == n || loopExitNode.stateAfter() == n) {
                        continue;
                    }
                }
                Block usageBlock = nodeMap.get(usageNode);
                if (usageBlock == null) {
                    if (usage instanceof FloatingNode || usage instanceof VirtualState || usage instanceof CallTargetNode) {
                        if (!(usage instanceof GuardNode)) {
                            /*
                                 * We do not want to run the schedule behind the verification with
                                 * dead code elimination, i.e., floating nodes without usages are
                                 * not removed, thus we must handle the case that a floating node
                                 * without a usage occurs here.
                                 */
                            if (nonFixedNodeTreeWithoutUsages(usage)) {
                                continue;
                            }
                        }
                    }
                }
                assert usageBlock != null || usage instanceof ProxyNode : "Usage " + usageNode + " of node " + n + " has no block";
                Loop<Block> usageLoop = null;
                if (usageNode instanceof ProxyNode) {
                    ProxyNode proxyNode = (ProxyNode) usageNode;
                    usageLoop = nodeMap.get(proxyNode.proxyPoint().loopBegin()).getLoop();
                } else {
                    if (usageBlock.getBeginNode() instanceof LoopExitNode) {
                        // For nodes in the loop exit node block, we don't know for sure
                        // whether they are "in the loop" or not. It depends on whether
                        // one of their transient usages is a loop proxy node.
                        // For now, let's just assume those nodes are OK, i.e., "in the loop".
                        LoopExitNode loopExitNode = (LoopExitNode) usageBlock.getBeginNode();
                        usageLoop = nodeMap.get(loopExitNode.loopBegin()).getLoop();
                    } else {
                        usageLoop = usageBlock.getLoop();
                    }
                }
                assert usageLoop != null : n + ", " + nodeMap.get(n) + " / " + usageNode + ", " + nodeMap.get(usageNode);
                while (usageLoop != block.getLoop() && usageLoop != null) {
                    usageLoop = usageLoop.getParent();
                }
                assert usageLoop != null : n + ", " + usageNode + ", " + usageBlock + ", " + usageBlock.getLoop() + ", " + block + ", " + block.getLoop();
            }
        }
    }
    return currentState;
}
Also used : MemoryProxyNode(org.graalvm.compiler.nodes.MemoryProxyNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) SingleMemoryKill(org.graalvm.compiler.nodes.memory.SingleMemoryKill) MultiMemoryKill(org.graalvm.compiler.nodes.memory.MultiMemoryKill) MemoryKill(org.graalvm.compiler.nodes.memory.MemoryKill) MemoryProxyNode(org.graalvm.compiler.nodes.MemoryProxyNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) CallTargetNode(org.graalvm.compiler.nodes.CallTargetNode) MemoryProxyNode(org.graalvm.compiler.nodes.MemoryProxyNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) VirtualState(org.graalvm.compiler.nodes.VirtualState) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) MultiMemoryKill(org.graalvm.compiler.nodes.memory.MultiMemoryKill) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) LocationIdentity(org.graalvm.word.LocationIdentity) Block(org.graalvm.compiler.nodes.cfg.Block) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) MemoryAccess(org.graalvm.compiler.nodes.memory.MemoryAccess) SingleMemoryKill(org.graalvm.compiler.nodes.memory.SingleMemoryKill) CallTargetNode(org.graalvm.compiler.nodes.CallTargetNode)

Example 3 with MemoryKill

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

the class PlaceholderLogicNode method verifyWithExceptionNode.

/**
 * Verifies that a {@link WithExceptionNode} has only memory usages via the
 * {@link WithExceptionNode#next()} edge. On the {@link WithExceptionNode#exceptionEdge()} there
 * must be a {@link MemoryKill} (or an {@link UnreachableBeginNode}), otherwise we would not
 * know from which edge a memory usage is coming from.
 */
private static void verifyWithExceptionNode(ValueNode node) {
    if (node instanceof WithExceptionNode && node instanceof MemoryKill) {
        WithExceptionNode withExceptionNode = (WithExceptionNode) node;
        AbstractBeginNode exceptionEdge = withExceptionNode.exceptionEdge();
        if (exceptionEdge instanceof UnreachableBeginNode) {
            // exception edge is unreachable - we are good
            return;
        }
        GraalError.guarantee(exceptionEdge instanceof MemoryKill, "The exception edge of %s is not a memory kill %s", node, exceptionEdge);
        if (exceptionEdge instanceof SingleMemoryKill) {
            SingleMemoryKill exceptionEdgeKill = (SingleMemoryKill) exceptionEdge;
            if (exceptionEdgeKill.getKilledLocationIdentity().isAny()) {
                // exception edge kills any - we are good
                return;
            }
            // if the exception edge does not kill any, it must kill the same location
            GraalError.guarantee(withExceptionNode instanceof SingleMemoryKill, "Not a single memory kill: %s", withExceptionNode);
            SingleMemoryKill withExceptionKill = (SingleMemoryKill) withExceptionNode;
            GraalError.guarantee(withExceptionKill.getKilledLocationIdentity().equals(exceptionEdgeKill.getKilledLocationIdentity()), "Kill locations do not match: %s (%s) vs %s (%s)", withExceptionKill, withExceptionKill.getKilledLocationIdentity(), exceptionEdgeKill, exceptionEdgeKill.getKilledLocationIdentity());
        } else if (exceptionEdge instanceof MultiMemoryKill) {
            // for multi memory kills the locations must match
            MultiMemoryKill exceptionEdgeKill = (MultiMemoryKill) exceptionEdge;
            GraalError.guarantee(withExceptionNode instanceof MultiMemoryKill, "Not a single memory kill: %s", withExceptionNode);
            MultiMemoryKill withExceptionKill = (MultiMemoryKill) withExceptionNode;
            GraalError.guarantee(Arrays.equals(withExceptionKill.getKilledLocationIdentities(), exceptionEdgeKill.getKilledLocationIdentities()), "Kill locations do not match: %s (%s) vs %s (%s)", withExceptionKill, withExceptionKill.getKilledLocationIdentities(), exceptionEdgeKill, exceptionEdgeKill.getKilledLocationIdentities());
        } else {
            GraalError.shouldNotReachHere("Unexpected exception edge: " + exceptionEdge);
        }
    }
}
Also used : SingleMemoryKill(org.graalvm.compiler.nodes.memory.SingleMemoryKill) MultiMemoryKill(org.graalvm.compiler.nodes.memory.MultiMemoryKill) MemoryKill(org.graalvm.compiler.nodes.memory.MemoryKill) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) FallbackInvokeWithExceptionNode(org.graalvm.compiler.replacements.nodes.FallbackInvokeWithExceptionNode) MacroWithExceptionNode(org.graalvm.compiler.replacements.nodes.MacroWithExceptionNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) MultiMemoryKill(org.graalvm.compiler.nodes.memory.MultiMemoryKill) UnreachableBeginNode(org.graalvm.compiler.nodes.UnreachableBeginNode) SingleMemoryKill(org.graalvm.compiler.nodes.memory.SingleMemoryKill) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 4 with MemoryKill

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

the class GraphEffectList method deleteNode.

/**
 * Removes the given fixed node from the control flow and deletes it.
 *
 * @param node The fixed node that should be deleted.
 */
public void deleteNode(Node node) {
    add("delete fixed node", new Effect() {

        @Override
        public void apply(StructuredGraph graph, ArrayList<Node> obsoleteNodes) {
            if (node instanceof FixedWithNextNode) {
                GraphUtil.unlinkFixedNode((FixedWithNextNode) node);
            } else if (node instanceof WithExceptionNode && node.isAlive()) {
                WithExceptionNode withExceptionNode = (WithExceptionNode) node;
                AbstractBeginNode next = withExceptionNode.next();
                GraphUtil.unlinkAndKillExceptionEdge(withExceptionNode);
                if (next.hasNoUsages() && next instanceof MemoryKill) {
                    // This is a killing begin which is no longer needed.
                    graph.replaceFixedWithFixed(next, graph.add(new BeginNode()));
                }
                obsoleteNodes.add(withExceptionNode);
            }
            obsoleteNodes.add(node);
        }

        @Override
        public boolean isCfgKill() {
            return node instanceof WithExceptionNode;
        }
    });
}
Also used : MemoryKill(org.graalvm.compiler.nodes.memory.MemoryKill) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) BeginNode(org.graalvm.compiler.nodes.BeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) WeakCounterNode(org.graalvm.compiler.nodes.debug.WeakCounterNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) PiNode(org.graalvm.compiler.nodes.PiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) WithExceptionNode(org.graalvm.compiler.nodes.WithExceptionNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) DynamicCounterNode(org.graalvm.compiler.nodes.debug.DynamicCounterNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 5 with MemoryKill

use of org.graalvm.compiler.nodes.memory.MemoryKill 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.isAfterStage(StageFlag.FLOATING_READS) && n instanceof MemoryKill && !(node instanceof MemoryKill) && !(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 SingleMemoryKill) {
                isAny = ((SingleMemoryKill) n).getKilledLocationIdentity().isAny();
            } else if (n instanceof MultiMemoryKill) {
                for (LocationIdentity ident : ((MultiMemoryKill) n).getKilledLocationIdentities()) {
                    if (ident.isAny()) {
                        isAny = true;
                    }
                }
            } else {
                throw GraalError.shouldNotReachHere("Unknown type of memory kill " + n);
            }
            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 : SingleMemoryKill(org.graalvm.compiler.nodes.memory.SingleMemoryKill) MultiMemoryKill(org.graalvm.compiler.nodes.memory.MultiMemoryKill) MemoryKill(org.graalvm.compiler.nodes.memory.MemoryKill) 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) MultiMemoryKill(org.graalvm.compiler.nodes.memory.MultiMemoryKill) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) LocationIdentity(org.graalvm.word.LocationIdentity) Lowerable(org.graalvm.compiler.nodes.spi.Lowerable) SingleMemoryKill(org.graalvm.compiler.nodes.memory.SingleMemoryKill)

Aggregations

MemoryKill (org.graalvm.compiler.nodes.memory.MemoryKill)6 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)5 MultiMemoryKill (org.graalvm.compiler.nodes.memory.MultiMemoryKill)5 SingleMemoryKill (org.graalvm.compiler.nodes.memory.SingleMemoryKill)5 Node (org.graalvm.compiler.graph.Node)4 PhiNode (org.graalvm.compiler.nodes.PhiNode)4 FloatingNode (org.graalvm.compiler.nodes.calc.FloatingNode)4 LocationIdentity (org.graalvm.word.LocationIdentity)4 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)3 FixedNode (org.graalvm.compiler.nodes.FixedNode)3 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)3 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)3 ValueNode (org.graalvm.compiler.nodes.ValueNode)3 Mark (org.graalvm.compiler.graph.Graph.Mark)2 LogicNode (org.graalvm.compiler.nodes.LogicNode)2 WithExceptionNode (org.graalvm.compiler.nodes.WithExceptionNode)2 GuardedNode (org.graalvm.compiler.nodes.extended.GuardedNode)2 MemoryPhiNode (org.graalvm.compiler.nodes.memory.MemoryPhiNode)2 Array (java.lang.reflect.Array)1 Method (java.lang.reflect.Method)1