Search in sources :

Example 1 with VirtualState

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

the class BinaryGraphPrinter method nodeProperties.

@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public void nodeProperties(GraphInfo info, Node node, Map<String, Object> props) {
    node.getDebugProperties((Map) props);
    Graph graph = info.graph;
    ControlFlowGraph cfg = info.cfg;
    NodeMap<Block> nodeToBlocks = info.nodeToBlocks;
    if (cfg != null && DebugOptions.PrintGraphProbabilities.getValue(graph.getOptions()) && node instanceof FixedNode) {
        try {
            props.put("probability", cfg.blockFor(node).probability());
        } catch (Throwable t) {
            props.put("probability", 0.0);
            props.put("probability-exception", t);
        }
    }
    try {
        props.put("NodeCost-Size", node.estimatedNodeSize());
        props.put("NodeCost-Cycles", node.estimatedNodeCycles());
    } catch (Throwable t) {
        props.put("node-cost-exception", t.getMessage());
    }
    if (nodeToBlocks != null) {
        Object block = getBlockForNode(node, nodeToBlocks);
        if (block != null) {
            props.put("node-to-block", block);
        }
    }
    if (node instanceof ControlSinkNode) {
        props.put("category", "controlSink");
    } else if (node instanceof ControlSplitNode) {
        props.put("category", "controlSplit");
    } else if (node instanceof AbstractMergeNode) {
        props.put("category", "merge");
    } else if (node instanceof AbstractBeginNode) {
        props.put("category", "begin");
    } else if (node instanceof AbstractEndNode) {
        props.put("category", "end");
    } else if (node instanceof FixedNode) {
        props.put("category", "fixed");
    } else if (node instanceof VirtualState) {
        props.put("category", "state");
    } else if (node instanceof PhiNode) {
        props.put("category", "phi");
    } else if (node instanceof ProxyNode) {
        props.put("category", "proxy");
    } else {
        if (node instanceof ConstantNode) {
            ConstantNode cn = (ConstantNode) node;
            updateStringPropertiesForConstant((Map) props, cn);
        }
        props.put("category", "floating");
    }
    if (getSnippetReflectionProvider() != null) {
        for (Map.Entry<String, Object> prop : props.entrySet()) {
            if (prop.getValue() instanceof JavaConstantFormattable) {
                props.put(prop.getKey(), ((JavaConstantFormattable) prop.getValue()).format(this));
            }
        }
    }
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) VirtualState(org.graalvm.compiler.nodes.VirtualState) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Graph(org.graalvm.compiler.graph.Graph) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) CachedGraph(org.graalvm.compiler.graph.CachedGraph) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) Block(org.graalvm.compiler.nodes.cfg.Block) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) Map(java.util.Map) NodeMap(org.graalvm.compiler.graph.NodeMap) BlockMap(org.graalvm.compiler.core.common.cfg.BlockMap) JavaConstantFormattable(org.graalvm.compiler.nodes.util.JavaConstantFormattable)

Example 2 with VirtualState

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

the class GraphOrder method assertSchedulableGraph.

/**
 * This method schedules the graph and makes sure that, for every node, all inputs are available
 * at the position where it is scheduled. This is a very expensive assertion.
 */
public static boolean assertSchedulableGraph(final StructuredGraph graph) {
    assert graph.getGuardsStage() != GuardsStage.AFTER_FSA : "Cannot use the BlockIteratorClosure after FrameState Assignment, HIR Loop Data Structures are no longer valid.";
    try {
        final SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
        final EconomicMap<LoopBeginNode, NodeBitMap> loopEntryStates = EconomicMap.create(Equivalence.IDENTITY);
        schedulePhase.apply(graph, false);
        final ScheduleResult schedule = graph.getLastSchedule();
        BlockIteratorClosure<NodeBitMap> closure = new BlockIteratorClosure<NodeBitMap>() {

            @Override
            protected List<NodeBitMap> processLoop(Loop<Block> loop, NodeBitMap initialState) {
                return ReentrantBlockIterator.processLoop(this, loop, initialState).exitStates;
            }

            @Override
            protected NodeBitMap processBlock(final Block block, final NodeBitMap currentState) {
                final List<Node> list = graph.getLastSchedule().getBlockToNodesMap().get(block);
                /*
                     * A stateAfter is not valid directly after its associated state split, but
                     * right before the next fixed node. Therefore a pending stateAfter is kept that
                     * will be checked at the correct position.
                     */
                FrameState pendingStateAfter = null;
                for (final Node node : list) {
                    if (node instanceof ValueNode) {
                        FrameState stateAfter = node instanceof StateSplit ? ((StateSplit) node).stateAfter() : null;
                        if (node instanceof FullInfopointNode) {
                            stateAfter = ((FullInfopointNode) node).getState();
                        }
                        if (pendingStateAfter != null && node instanceof FixedNode) {
                            pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {

                                @Override
                                public void apply(Node usage, Node nonVirtualNode) {
                                    assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " before " + node + " in block " + block + " \n" + list;
                                }
                            });
                            pendingStateAfter = null;
                        }
                        if (node instanceof AbstractMergeNode) {
                            // phis aren't scheduled, so they need to be added explicitly
                            currentState.markAll(((AbstractMergeNode) node).phis());
                            if (node instanceof LoopBeginNode) {
                                // remember the state at the loop entry, it's restored at exits
                                loopEntryStates.put((LoopBeginNode) node, currentState.copy());
                            }
                        } else if (node instanceof ProxyNode) {
                            assert false : "proxy nodes should not be in the schedule";
                        } else if (node instanceof LoopExitNode) {
                            if (graph.hasValueProxies()) {
                                for (ProxyNode proxy : ((LoopExitNode) node).proxies()) {
                                    for (Node input : proxy.inputs()) {
                                        if (input != proxy.proxyPoint()) {
                                            assert currentState.isMarked(input) : input + " not available at " + proxy + " in block " + block + "\n" + list;
                                        }
                                    }
                                }
                                // loop contents are only accessible via proxies at the exit
                                currentState.clearAll();
                                currentState.markAll(loopEntryStates.get(((LoopExitNode) node).loopBegin()));
                            }
                            // Loop proxies aren't scheduled, so they need to be added
                            // explicitly
                            currentState.markAll(((LoopExitNode) node).proxies());
                        } else {
                            for (Node input : node.inputs()) {
                                if (input != stateAfter) {
                                    if (input instanceof FrameState) {
                                        ((FrameState) input).applyToNonVirtual(new VirtualState.NodeClosure<Node>() {

                                            @Override
                                            public void apply(Node usage, Node nonVirtual) {
                                                assert currentState.isMarked(nonVirtual) : nonVirtual + " not available at " + node + " in block " + block + "\n" + list;
                                            }
                                        });
                                    } else {
                                        assert currentState.isMarked(input) || input instanceof VirtualObjectNode || input instanceof ConstantNode : input + " not available at " + node + " in block " + block + "\n" + list;
                                    }
                                }
                            }
                        }
                        if (node instanceof AbstractEndNode) {
                            AbstractMergeNode merge = ((AbstractEndNode) node).merge();
                            for (PhiNode phi : merge.phis()) {
                                ValueNode phiValue = phi.valueAt((AbstractEndNode) node);
                                assert phiValue == null || currentState.isMarked(phiValue) || phiValue instanceof ConstantNode : phiValue + " not available at phi " + phi + " / end " + node + " in block " + block;
                            }
                        }
                        if (stateAfter != null) {
                            assert pendingStateAfter == null;
                            pendingStateAfter = stateAfter;
                        }
                        currentState.mark(node);
                    }
                }
                if (pendingStateAfter != null) {
                    pendingStateAfter.applyToNonVirtual(new NodeClosure<Node>() {

                        @Override
                        public void apply(Node usage, Node nonVirtualNode) {
                            assert currentState.isMarked(nonVirtualNode) || nonVirtualNode instanceof VirtualObjectNode || nonVirtualNode instanceof ConstantNode : nonVirtualNode + " not available at virtualstate " + usage + " at end of block " + block + " \n" + list;
                        }
                    });
                }
                return currentState;
            }

            @Override
            protected NodeBitMap merge(Block merge, List<NodeBitMap> states) {
                NodeBitMap result = states.get(0);
                for (int i = 1; i < states.size(); i++) {
                    result.intersect(states.get(i));
                }
                return result;
            }

            @Override
            protected NodeBitMap getInitialState() {
                NodeBitMap ret = graph.createNodeBitMap();
                ret.markAll(graph.getNodes().filter(ConstantNode.class));
                return ret;
            }

            @Override
            protected NodeBitMap cloneState(NodeBitMap oldState) {
                return oldState.copy();
            }
        };
        ReentrantBlockIterator.apply(closure, schedule.getCFG().getStartBlock());
    } catch (Throwable t) {
        graph.getDebug().handle(t);
    }
    return true;
}
Also used : VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) SchedulePhase(org.graalvm.compiler.phases.schedule.SchedulePhase) ScheduleResult(org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FullInfopointNode(org.graalvm.compiler.nodes.FullInfopointNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) VirtualState(org.graalvm.compiler.nodes.VirtualState) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) ArrayList(java.util.ArrayList) List(java.util.List) Loop(org.graalvm.compiler.core.common.cfg.Loop) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) BlockIteratorClosure(org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FullInfopointNode(org.graalvm.compiler.nodes.FullInfopointNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Block(org.graalvm.compiler.nodes.cfg.Block) StateSplit(org.graalvm.compiler.nodes.StateSplit)

Example 3 with VirtualState

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

the class LoopFragment method mergeEarlyExits.

/**
 * Merges the early exits (i.e. loop exits) that were duplicated as part of this fragment, with
 * the original fragment's exits.
 */
protected void mergeEarlyExits() {
    assert isDuplicate();
    StructuredGraph graph = graph();
    for (AbstractBeginNode earlyExit : LoopFragment.toHirBlocks(original().loop().loop().getExits())) {
        LoopExitNode loopEarlyExit = (LoopExitNode) earlyExit;
        FixedNode next = loopEarlyExit.next();
        if (loopEarlyExit.isDeleted() || !this.original().contains(loopEarlyExit)) {
            continue;
        }
        AbstractBeginNode newEarlyExit = getDuplicatedNode(loopEarlyExit);
        if (newEarlyExit == null) {
            continue;
        }
        MergeNode merge = graph.add(new MergeNode());
        EndNode originalEnd = graph.add(new EndNode());
        EndNode newEnd = graph.add(new EndNode());
        merge.addForwardEnd(originalEnd);
        merge.addForwardEnd(newEnd);
        loopEarlyExit.setNext(originalEnd);
        newEarlyExit.setNext(newEnd);
        merge.setNext(next);
        FrameState exitState = loopEarlyExit.stateAfter();
        if (exitState != null) {
            FrameState originalExitState = exitState;
            exitState = exitState.duplicateWithVirtualState();
            loopEarlyExit.setStateAfter(exitState);
            merge.setStateAfter(originalExitState);
            /*
                 * Using the old exit's state as the merge's state is necessary because some of the
                 * VirtualState nodes contained in the old exit's state may be shared by other
                 * dominated VirtualStates. Those dominated virtual states need to see the
                 * proxy->phi update that are applied below.
                 *
                 * We now update the original fragment's nodes accordingly:
                 */
            originalExitState.applyToVirtual(node -> original.nodes.clearAndGrow(node));
            exitState.applyToVirtual(node -> original.nodes.markAndGrow(node));
        }
        FrameState finalExitState = exitState;
        for (Node anchored : loopEarlyExit.anchored().snapshot()) {
            anchored.replaceFirstInput(loopEarlyExit, merge);
        }
        boolean newEarlyExitIsLoopExit = newEarlyExit instanceof LoopExitNode;
        for (ProxyNode vpn : loopEarlyExit.proxies().snapshot()) {
            if (vpn.hasNoUsages()) {
                continue;
            }
            if (vpn.value() == null) {
                assert vpn instanceof GuardProxyNode;
                vpn.replaceAtUsages(null);
                continue;
            }
            final ValueNode replaceWith;
            ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
            if (newVpn != null) {
                PhiNode phi;
                if (vpn instanceof ValueProxyNode) {
                    phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge));
                } else if (vpn instanceof GuardProxyNode) {
                    phi = graph.addWithoutUnique(new GuardPhiNode(merge));
                } else {
                    throw GraalError.shouldNotReachHere();
                }
                phi.addInput(vpn);
                phi.addInput(newVpn);
                replaceWith = phi;
            } else {
                replaceWith = vpn.value();
            }
            vpn.replaceAtMatchingUsages(replaceWith, usage -> {
                if (merge.isPhiAtMerge(usage)) {
                    return false;
                }
                if (usage instanceof VirtualState) {
                    VirtualState stateUsage = (VirtualState) usage;
                    if (finalExitState != null && finalExitState.isPartOfThisState(stateUsage)) {
                        return false;
                    }
                }
                return true;
            });
        }
    }
}
Also used : GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) FrameState(org.graalvm.compiler.nodes.FrameState) VirtualState(org.graalvm.compiler.nodes.VirtualState) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) EndNode(org.graalvm.compiler.nodes.EndNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Aggregations

AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)3 FixedNode (org.graalvm.compiler.nodes.FixedNode)3 PhiNode (org.graalvm.compiler.nodes.PhiNode)3 ProxyNode (org.graalvm.compiler.nodes.ProxyNode)3 VirtualState (org.graalvm.compiler.nodes.VirtualState)3 Node (org.graalvm.compiler.graph.Node)2 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)2 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)2 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)2 EndNode (org.graalvm.compiler.nodes.EndNode)2 FrameState (org.graalvm.compiler.nodes.FrameState)2 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)2 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)2 ValueNode (org.graalvm.compiler.nodes.ValueNode)2 Block (org.graalvm.compiler.nodes.cfg.Block)2 VirtualObjectNode (org.graalvm.compiler.nodes.virtual.VirtualObjectNode)2 ArrayList (java.util.ArrayList)1 List (java.util.List)1 Map (java.util.Map)1 BlockMap (org.graalvm.compiler.core.common.cfg.BlockMap)1