Search in sources :

Example 21 with Block

use of org.graalvm.compiler.nodes.cfg.Block 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 22 with Block

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

the class NodeCostUtil method computeGraphCycles.

@SuppressWarnings("try")
public static double computeGraphCycles(StructuredGraph graph, boolean fullSchedule) {
    Function<Block, Iterable<? extends Node>> blockToNodes;
    ControlFlowGraph cfg;
    if (fullSchedule) {
        SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS, true);
        schedule.apply(graph);
        cfg = graph.getLastSchedule().getCFG();
        blockToNodes = b -> graph.getLastSchedule().getBlockToNodesMap().get(b);
    } else {
        cfg = ControlFlowGraph.compute(graph, true, true, false, false);
        BlockMap<List<FixedNode>> nodes = new BlockMap<>(cfg);
        for (Block b : cfg.getBlocks()) {
            ArrayList<FixedNode> curNodes = new ArrayList<>();
            for (FixedNode node : b.getNodes()) {
                curNodes.add(node);
            }
            nodes.put(b, curNodes);
        }
        blockToNodes = b -> nodes.get(b);
    }
    double weightedCycles = 0D;
    DebugContext debug = graph.getDebug();
    try (DebugContext.Scope s = debug.scope("NodeCostSummary")) {
        for (Block block : cfg.getBlocks()) {
            for (Node n : blockToNodes.apply(block)) {
                double probWeighted = n.estimatedNodeCycles().value * block.probability();
                assert Double.isFinite(probWeighted);
                weightedCycles += probWeighted;
                if (debug.isLogEnabled()) {
                    debug.log("Node %s contributes cycles:%f size:%d to graph %s [block prob:%f]", n, n.estimatedNodeCycles().value * block.probability(), n.estimatedNodeSize().value, graph, block.probability());
                }
            }
        }
    }
    assert weightedCycles >= 0D;
    assert Double.isFinite(weightedCycles);
    return weightedCycles;
}
Also used : SchedulePhase(org.graalvm.compiler.phases.schedule.SchedulePhase) FixedNode(org.graalvm.compiler.nodes.FixedNode) Node(org.graalvm.compiler.graph.Node) ArrayList(java.util.ArrayList) FixedNode(org.graalvm.compiler.nodes.FixedNode) DebugContext(org.graalvm.compiler.debug.DebugContext) BlockMap(org.graalvm.compiler.core.common.cfg.BlockMap) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) Block(org.graalvm.compiler.nodes.cfg.Block) ArrayList(java.util.ArrayList) List(java.util.List)

Example 23 with Block

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

the class GraphScheduleTest method assertOrderedAfterSchedule.

protected void assertOrderedAfterSchedule(ScheduleResult ibp, Node a, Node b) {
    NodeMap<Block> nodeToBlock = ibp.getCFG().getNodeToBlock();
    Block bBlock = nodeToBlock.get(b);
    Block aBlock = nodeToBlock.get(a);
    if (bBlock == aBlock) {
        List<Node> instructions = ibp.nodesFor(bBlock);
        Assert.assertTrue(a + " should be before " + b, instructions.indexOf(b) > instructions.indexOf(a));
    } else {
        Block block = bBlock;
        while (block != null) {
            if (block == aBlock) {
                return;
            }
            block = block.getDominator();
        }
        Assert.fail("block of A doesn't dominate the block of B");
    }
}
Also used : Node(org.graalvm.compiler.graph.Node) Block(org.graalvm.compiler.nodes.cfg.Block)

Example 24 with Block

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

the class GraalCompilerState method preLIRGeneration.

/**
 * Sets up {@link LIR} generation.
 */
protected final void preLIRGeneration() {
    assert request.graph.isFrozen() : "Graph not frozen.";
    Object stub = null;
    schedule = request.graph.getLastSchedule();
    ControlFlowGraph cfg = deepCopy(schedule.getCFG());
    Block[] blocks = cfg.getBlocks();
    Block startBlock = cfg.getStartBlock();
    assert startBlock != null;
    assert startBlock.getPredecessorCount() == 0;
    codeEmittingOrder = ComputeBlockOrder.computeCodeEmittingOrder(blocks.length, startBlock);
    linearScanOrder = ComputeBlockOrder.computeLinearScanOrder(blocks.length, startBlock);
    LIR lir = new LIR(cfg, linearScanOrder, codeEmittingOrder, getGraphOptions(), getGraphDebug());
    FrameMapBuilder frameMapBuilder = request.backend.newFrameMapBuilder(registerConfig);
    lirGenRes = request.backend.newLIRGenerationResult(graph.compilationId(), lir, frameMapBuilder, request.graph, stub);
    lirGenTool = request.backend.newLIRGenerator(lirGenRes);
    nodeLirGen = request.backend.newNodeLIRBuilder(request.graph, lirGenTool);
}
Also used : LIR(org.graalvm.compiler.lir.LIR) ControlFlowGraph(org.graalvm.compiler.nodes.cfg.ControlFlowGraph) FrameMapBuilder(org.graalvm.compiler.lir.framemap.FrameMapBuilder) Block(org.graalvm.compiler.nodes.cfg.Block)

Example 25 with Block

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

the class EffectsClosure method processLoop.

@Override
@SuppressWarnings("try")
protected final List<BlockT> processLoop(Loop<Block> loop, BlockT initialState) {
    if (initialState.isDead()) {
        ArrayList<BlockT> states = new ArrayList<>();
        for (int i = 0; i < loop.getExits().size(); i++) {
            states.add(initialState);
        }
        return states;
    }
    /*
         * Special case nested loops: To avoid an exponential runtime for nested loops we try to
         * only process them as little times as possible.
         *
         * In the first iteration of an outer most loop we go into the inner most loop(s). We run
         * the first iteration of the inner most loop and then, if necessary, a second iteration.
         *
         * We return from the recursion and finish the first iteration of the outermost loop. If we
         * have to do a second iteration in the outer most loop we go again into the inner most
         * loop(s) but this time we already know all states that are killed by the loop so inside
         * the loop we will only have those changes that propagate from the first iteration of the
         * outer most loop into the current loop. We strip the initial loop state for the inner most
         * loops and do the first iteration with the (possible) changes from outer loops. If there
         * are no changes we only have to do 1 iteration and are done.
         *
         */
    BlockT initialStateRemovedKilledLocations = stripKilledLoopLocations(loop, cloneState(initialState));
    BlockT loopEntryState = initialStateRemovedKilledLocations;
    BlockT lastMergedState = cloneState(initialStateRemovedKilledLocations);
    processInitialLoopState(loop, lastMergedState);
    MergeProcessor mergeProcessor = createMergeProcessor(loop.getHeader());
    /*
         * Iterative loop processing: we take the predecessor state as the loop's starting state,
         * processing the loop contents, merge the states of all loop ends, and check whether the
         * resulting state is equal to the starting state. If it is, the loop processing has
         * finished, if not, another iteration is needed.
         *
         * This processing converges because the merge processing always makes the starting state
         * more generic, e.g., adding phis instead of non-phi values.
         */
    for (int iteration = 0; iteration < 10; iteration++) {
        try (Indent i = debug.logAndIndent("================== Process Loop Effects Closure: block:%s begin node:%s", loop.getHeader(), loop.getHeader().getBeginNode())) {
            LoopInfo<BlockT> info = ReentrantBlockIterator.processLoop(this, loop, cloneState(lastMergedState));
            List<BlockT> states = new ArrayList<>();
            states.add(initialStateRemovedKilledLocations);
            states.addAll(info.endStates);
            doMergeWithoutDead(mergeProcessor, states);
            debug.log("MergeProcessor New State: %s", mergeProcessor.newState);
            debug.log("===== vs.");
            debug.log("Last Merged State: %s", lastMergedState);
            if (mergeProcessor.newState.equivalentTo(lastMergedState)) {
                blockEffects.get(loop.getHeader()).insertAll(mergeProcessor.mergeEffects, 0);
                loopMergeEffects.put(loop, mergeProcessor.afterMergeEffects);
                assert info.exitStates.size() == loop.getExits().size();
                loopEntryStates.put((LoopBeginNode) loop.getHeader().getBeginNode(), loopEntryState);
                assert assertExitStatesNonEmpty(loop, info);
                processKilledLoopLocations(loop, initialStateRemovedKilledLocations, mergeProcessor.newState);
                return info.exitStates;
            } else {
                lastMergedState = mergeProcessor.newState;
                for (Block block : loop.getBlocks()) {
                    blockEffects.get(block).clear();
                }
            }
        }
    }
    throw new GraalError("too many iterations at %s", loop);
}
Also used : Indent(org.graalvm.compiler.debug.Indent) GraalError(org.graalvm.compiler.debug.GraalError) ArrayList(java.util.ArrayList) Block(org.graalvm.compiler.nodes.cfg.Block)

Aggregations

Block (org.graalvm.compiler.nodes.cfg.Block)54 Node (org.graalvm.compiler.graph.Node)20 FixedNode (org.graalvm.compiler.nodes.FixedNode)17 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)14 ScheduleResult (org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult)14 ValueNode (org.graalvm.compiler.nodes.ValueNode)14 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)13 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)13 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)13 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)13 ControlFlowGraph (org.graalvm.compiler.nodes.cfg.ControlFlowGraph)12 SchedulePhase (org.graalvm.compiler.phases.schedule.SchedulePhase)11 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)9 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)9 PhiNode (org.graalvm.compiler.nodes.PhiNode)9 List (java.util.List)8 DebugContext (org.graalvm.compiler.debug.DebugContext)8 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)8 ArrayList (java.util.ArrayList)7 ReturnNode (org.graalvm.compiler.nodes.ReturnNode)7