Search in sources :

Example 26 with FixedNode

use of org.graalvm.compiler.nodes.FixedNode 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 27 with FixedNode

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

the class PostOrderNodeIterator method apply.

public void apply() {
    FixedNode current = start;
    do {
        if (current instanceof InvokeWithExceptionNode) {
            invoke((Invoke) current);
            queueSuccessors(current, null);
            current = nextQueuedNode();
        } else if (current instanceof LoopBeginNode) {
            state.loopBegin((LoopBeginNode) current);
            nodeStates.put(current, state);
            state = state.clone();
            loopBegin((LoopBeginNode) current);
            current = ((LoopBeginNode) current).next();
            assert current != null;
        } else if (current instanceof LoopEndNode) {
            loopEnd((LoopEndNode) current);
            finishLoopEnds((LoopEndNode) current);
            current = nextQueuedNode();
        } else if (current instanceof AbstractMergeNode) {
            merge((AbstractMergeNode) current);
            current = ((AbstractMergeNode) current).next();
            assert current != null;
        } else if (current instanceof FixedWithNextNode) {
            FixedNode next = ((FixedWithNextNode) current).next();
            assert next != null : current;
            node(current);
            current = next;
        } else if (current instanceof EndNode) {
            end((EndNode) current);
            queueMerge((EndNode) current);
            current = nextQueuedNode();
        } else if (current instanceof ControlSinkNode) {
            node(current);
            current = nextQueuedNode();
        } else if (current instanceof ControlSplitNode) {
            Set<Node> successors = controlSplit((ControlSplitNode) current);
            queueSuccessors(current, successors);
            current = nextQueuedNode();
        } else {
            assert false : current;
        }
    } while (current != null);
    finished();
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) Set(java.util.Set) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode)

Example 28 with FixedNode

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

the class ReentrantBlockIterator method processLoop.

public static <StateT> LoopInfo<StateT> processLoop(BlockIteratorClosure<StateT> closure, Loop<Block> loop, StateT initialState) {
    EconomicMap<FixedNode, StateT> blockEndStates = apply(closure, loop.getHeader(), initialState, block -> !(block.getLoop() == loop || block.isLoopHeader()));
    Block[] predecessors = loop.getHeader().getPredecessors();
    LoopInfo<StateT> info = new LoopInfo<>(predecessors.length - 1, loop.getExits().size());
    for (int i = 1; i < predecessors.length; i++) {
        StateT endState = blockEndStates.get(predecessors[i].getEndNode());
        // make sure all end states are unique objects
        info.endStates.add(closure.cloneState(endState));
    }
    for (Block loopExit : loop.getExits()) {
        assert loopExit.getPredecessorCount() == 1;
        assert blockEndStates.containsKey(loopExit.getBeginNode()) : loopExit.getBeginNode() + " " + blockEndStates;
        StateT exitState = blockEndStates.get(loopExit.getBeginNode());
        // make sure all exit states are unique objects
        info.exitStates.add(closure.cloneState(exitState));
    }
    return info;
}
Also used : Block(org.graalvm.compiler.nodes.cfg.Block) FixedNode(org.graalvm.compiler.nodes.FixedNode)

Example 29 with FixedNode

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

the class ReentrantBlockIterator method apply.

public static <StateT> EconomicMap<FixedNode, StateT> apply(BlockIteratorClosure<StateT> closure, Block start, StateT initialState, Predicate<Block> stopAtBlock) {
    Deque<Block> blockQueue = new ArrayDeque<>();
    /*
         * States are stored on EndNodes before merges, and on BeginNodes after ControlSplitNodes.
         */
    EconomicMap<FixedNode, StateT> states = EconomicMap.create(Equivalence.IDENTITY);
    StateT state = initialState;
    Block current = start;
    StructuredGraph graph = start.getBeginNode().graph();
    CompilationAlarm compilationAlarm = CompilationAlarm.current();
    while (true) {
        if (compilationAlarm.hasExpired()) {
            int period = CompilationAlarm.Options.CompilationExpirationPeriod.getValue(graph.getOptions());
            if (period > 120) {
                throw new PermanentBailoutException("Compilation exceeded %d seconds during CFG traversal", period);
            } else {
                throw new RetryableBailoutException("Compilation exceeded %d seconds during CFG traversal", period);
            }
        }
        Block next = null;
        if (stopAtBlock != null && stopAtBlock.test(current)) {
            states.put(current.getBeginNode(), state);
        } else {
            state = closure.processBlock(current, state);
            Block[] successors = current.getSuccessors();
            if (successors.length == 0) {
            // nothing to do...
            } else if (successors.length == 1) {
                Block successor = successors[0];
                if (successor.isLoopHeader()) {
                    if (current.isLoopEnd()) {
                        // nothing to do... loop ends only lead to loop begins we've already
                        // visited
                        states.put(current.getEndNode(), state);
                    } else {
                        recurseIntoLoop(closure, blockQueue, states, state, successor);
                    }
                } else if (current.getEndNode() instanceof AbstractEndNode) {
                    AbstractEndNode end = (AbstractEndNode) current.getEndNode();
                    // add the end node and see if the merge is ready for processing
                    AbstractMergeNode merge = end.merge();
                    if (allEndsVisited(states, current, merge)) {
                        ArrayList<StateT> mergedStates = mergeStates(states, state, current, successor, merge);
                        state = closure.merge(successor, mergedStates);
                        next = successor;
                    } else {
                        assert !states.containsKey(end);
                        states.put(end, state);
                    }
                } else {
                    next = successor;
                }
            } else {
                next = processMultipleSuccessors(closure, blockQueue, states, state, successors);
            }
        }
        // get next queued block
        if (next != null) {
            current = next;
        } else if (blockQueue.isEmpty()) {
            return states;
        } else {
            current = blockQueue.removeFirst();
            assert current.getPredecessorCount() == 1;
            assert states.containsKey(current.getBeginNode());
            state = states.removeKey(current.getBeginNode());
        }
    }
}
Also used : CompilationAlarm(org.graalvm.compiler.core.common.util.CompilationAlarm) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ArrayDeque(java.util.ArrayDeque) RetryableBailoutException(org.graalvm.compiler.core.common.RetryableBailoutException) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) Block(org.graalvm.compiler.nodes.cfg.Block) PermanentBailoutException(org.graalvm.compiler.core.common.PermanentBailoutException)

Example 30 with FixedNode

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

the class ReentrantNodeIterator method apply.

private static <StateT> EconomicMap<FixedNode, StateT> apply(NodeIteratorClosure<StateT> closure, FixedNode start, StateT initialState, LoopBeginNode boundary) {
    assert start != null;
    Deque<AbstractBeginNode> nodeQueue = new ArrayDeque<>();
    EconomicMap<FixedNode, StateT> blockEndStates = EconomicMap.create(Equivalence.IDENTITY);
    StateT state = initialState;
    FixedNode current = start;
    do {
        while (current instanceof FixedWithNextNode) {
            if (boundary != null && current instanceof LoopExitNode && ((LoopExitNode) current).loopBegin() == boundary) {
                blockEndStates.put(current, state);
                current = null;
            } else {
                FixedNode next = ((FixedWithNextNode) current).next();
                state = closure.processNode(current, state);
                current = closure.continueIteration(state) ? next : null;
            }
        }
        if (current != null) {
            state = closure.processNode(current, state);
            if (closure.continueIteration(state)) {
                Iterator<Node> successors = current.successors().iterator();
                if (!successors.hasNext()) {
                    if (current instanceof LoopEndNode) {
                        blockEndStates.put(current, state);
                    } else if (current instanceof EndNode) {
                        // add the end node and see if the merge is ready for processing
                        AbstractMergeNode merge = ((EndNode) current).merge();
                        if (merge instanceof LoopBeginNode) {
                            EconomicMap<LoopExitNode, StateT> loopExitState = closure.processLoop((LoopBeginNode) merge, state);
                            MapCursor<LoopExitNode, StateT> entry = loopExitState.getEntries();
                            while (entry.advance()) {
                                blockEndStates.put(entry.getKey(), entry.getValue());
                                nodeQueue.add(entry.getKey());
                            }
                        } else {
                            boolean endsVisited = true;
                            for (AbstractEndNode forwardEnd : merge.forwardEnds()) {
                                if (forwardEnd != current && !blockEndStates.containsKey(forwardEnd)) {
                                    endsVisited = false;
                                    break;
                                }
                            }
                            if (endsVisited) {
                                ArrayList<StateT> states = new ArrayList<>(merge.forwardEndCount());
                                for (int i = 0; i < merge.forwardEndCount(); i++) {
                                    AbstractEndNode forwardEnd = merge.forwardEndAt(i);
                                    assert forwardEnd == current || blockEndStates.containsKey(forwardEnd);
                                    StateT other = forwardEnd == current ? state : blockEndStates.removeKey(forwardEnd);
                                    states.add(other);
                                }
                                state = closure.merge(merge, states);
                                current = closure.continueIteration(state) ? merge : null;
                                continue;
                            } else {
                                assert !blockEndStates.containsKey(current);
                                blockEndStates.put(current, state);
                            }
                        }
                    }
                } else {
                    FixedNode firstSuccessor = (FixedNode) successors.next();
                    if (!successors.hasNext()) {
                        current = firstSuccessor;
                        continue;
                    } else {
                        do {
                            AbstractBeginNode successor = (AbstractBeginNode) successors.next();
                            StateT successorState = closure.afterSplit(successor, state);
                            if (closure.continueIteration(successorState)) {
                                blockEndStates.put(successor, successorState);
                                nodeQueue.add(successor);
                            }
                        } while (successors.hasNext());
                        state = closure.afterSplit((AbstractBeginNode) firstSuccessor, state);
                        current = closure.continueIteration(state) ? firstSuccessor : null;
                        continue;
                    }
                }
            }
        }
        // get next queued block
        if (nodeQueue.isEmpty()) {
            return blockEndStates;
        } else {
            current = nodeQueue.removeFirst();
            assert blockEndStates.containsKey(current);
            state = blockEndStates.removeKey(current);
            assert !(current instanceof AbstractMergeNode) && current instanceof AbstractBeginNode;
        }
    } while (true);
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) EconomicMap(org.graalvm.collections.EconomicMap) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ArrayList(java.util.ArrayList) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ArrayDeque(java.util.ArrayDeque) MapCursor(org.graalvm.collections.MapCursor) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode)

Aggregations

FixedNode (org.graalvm.compiler.nodes.FixedNode)87 Node (org.graalvm.compiler.graph.Node)41 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)41 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)39 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)39 ValueNode (org.graalvm.compiler.nodes.ValueNode)34 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)33 EndNode (org.graalvm.compiler.nodes.EndNode)27 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)25 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)23 PhiNode (org.graalvm.compiler.nodes.PhiNode)22 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)21 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)21 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)20 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)17 MergeNode (org.graalvm.compiler.nodes.MergeNode)17 StartNode (org.graalvm.compiler.nodes.StartNode)17 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)16 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)13 ProxyNode (org.graalvm.compiler.nodes.ProxyNode)13