Search in sources :

Example 41 with AbstractBeginNode

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

the class BytecodeParser method createBlockTarget.

/**
 * Returns a block begin node with the specified state. If the specified probability is 0, the
 * block deoptimizes immediately.
 */
private AbstractBeginNode createBlockTarget(double probability, BciBlock block, FrameStateBuilder stateAfter) {
    FixedNode target = createTarget(probability, block, stateAfter);
    AbstractBeginNode begin = BeginNode.begin(target);
    assert !(target instanceof DeoptimizeNode && begin instanceof BeginStateSplitNode && ((BeginStateSplitNode) begin).stateAfter() != null) : "We are not allowed to set the stateAfter of the begin node," + " because we have to deoptimize to a bci _before_ the actual if, so that the interpreter can update the profiling information.";
    return begin;
}
Also used : DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) BeginStateSplitNode(org.graalvm.compiler.nodes.BeginStateSplitNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 42 with AbstractBeginNode

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

the class BytecodeParser method createTarget.

@SuppressWarnings("try")
private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
    assert block != null && state != null;
    assert !block.isExceptionEntry || state.stackSize() == 1;
    try (DebugCloseable context = openNodeContext(state, block.startBci)) {
        if (getFirstInstruction(block) == null) {
            /*
                 * This is the first time we see this block as a branch target. Create and return a
                 * placeholder that later can be replaced with a MergeNode when we see this block
                 * again.
                 */
            FixedNode targetNode;
            if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
                setFirstInstruction(block, lastInstr);
                lastInstr = null;
            } else {
                setFirstInstruction(block, graph.add(new BeginNode()));
            }
            targetNode = getFirstInstruction(block);
            Target target = checkLoopExit(targetNode, block, state);
            FixedNode result = target.fixed;
            FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
            setEntryState(block, currentEntryState);
            currentEntryState.clearNonLiveLocals(block, liveness, true);
            debug.log("createTarget %s: first visit, result: %s", block, targetNode);
            return result;
        }
        // We already saw this block before, so we have to merge states.
        if (!getEntryState(block).isCompatibleWith(state)) {
            throw bailout("stacks do not match; bytecodes would not verify");
        }
        if (getFirstInstruction(block) instanceof LoopBeginNode) {
            assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
            /*
                 * Backward loop edge. We need to create a special LoopEndNode and merge with the
                 * loop begin node created before.
                 */
            LoopBeginNode loopBegin = (LoopBeginNode) getFirstInstruction(block);
            LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
            Target target = checkLoopExit(loopEnd, block, state);
            FixedNode result = target.fixed;
            getEntryState(block).merge(loopBegin, target.state);
            debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
            return result;
        }
        assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
        assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
        if (getFirstInstruction(block) instanceof AbstractBeginNode && !(getFirstInstruction(block) instanceof AbstractMergeNode)) {
            /*
                 * This is the second time we see this block. Create the actual MergeNode and the
                 * End Node for the already existing edge.
                 */
            AbstractBeginNode beginNode = (AbstractBeginNode) getFirstInstruction(block);
            // The EndNode for the already existing edge.
            EndNode end = graph.add(new EndNode());
            // The MergeNode that replaces the placeholder.
            AbstractMergeNode mergeNode = graph.add(new MergeNode());
            FixedNode next = beginNode.next();
            if (beginNode.predecessor() instanceof ControlSplitNode) {
                beginNode.setNext(end);
            } else {
                beginNode.replaceAtPredecessor(end);
                beginNode.safeDelete();
            }
            mergeNode.addForwardEnd(end);
            mergeNode.setNext(next);
            setFirstInstruction(block, mergeNode);
        }
        AbstractMergeNode mergeNode = (AbstractMergeNode) getFirstInstruction(block);
        // The EndNode for the newly merged edge.
        EndNode newEnd = graph.add(new EndNode());
        Target target = checkLoopExit(newEnd, block, state);
        FixedNode result = target.fixed;
        getEntryState(block).merge(mergeNode, target.state);
        mergeNode.addForwardEnd(newEnd);
        debug.log("createTarget %s: merging state, result: %s", block, result);
        return result;
    }
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) BeginNode(org.graalvm.compiler.nodes.BeginNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 43 with AbstractBeginNode

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

the class ControlFlowGraph method identifyBlocks.

/**
 * Identify and connect blocks (including loop backward edges). Predecessors need to be in the
 * order expected when iterating phi inputs.
 */
private void identifyBlocks() {
    // Find all block headers.
    int numBlocks = 0;
    for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.TYPE)) {
        Block block = new Block(begin);
        identifyBlock(block);
        numBlocks++;
    }
    // Compute reverse post order.
    int count = 0;
    NodeMap<Block> nodeMap = this.nodeToBlock;
    Block[] stack = new Block[numBlocks];
    int tos = 0;
    Block startBlock = blockFor(graph.start());
    stack[0] = startBlock;
    startBlock.setPredecessors(Block.EMPTY_ARRAY);
    do {
        Block block = stack[tos];
        int id = block.getId();
        if (id == BLOCK_ID_INITIAL) {
            // First time we see this block: push all successors.
            FixedNode last = block.getEndNode();
            if (last instanceof EndNode) {
                EndNode endNode = (EndNode) last;
                Block suxBlock = nodeMap.get(endNode.merge());
                if (suxBlock.getId() == BLOCK_ID_INITIAL) {
                    stack[++tos] = suxBlock;
                }
                block.setSuccessors(new Block[] { suxBlock });
            } else if (last instanceof IfNode) {
                IfNode ifNode = (IfNode) last;
                Block trueSucc = nodeMap.get(ifNode.trueSuccessor());
                stack[++tos] = trueSucc;
                Block falseSucc = nodeMap.get(ifNode.falseSuccessor());
                stack[++tos] = falseSucc;
                block.setSuccessors(new Block[] { trueSucc, falseSucc });
                Block[] ifPred = new Block[] { block };
                trueSucc.setPredecessors(ifPred);
                falseSucc.setPredecessors(ifPred);
            } else if (last instanceof LoopEndNode) {
                LoopEndNode loopEndNode = (LoopEndNode) last;
                block.setSuccessors(new Block[] { nodeMap.get(loopEndNode.loopBegin()) });
            // Nothing to do push onto the stack.
            } else if (last instanceof ControlSinkNode) {
                block.setSuccessors(Block.EMPTY_ARRAY);
            } else {
                assert !(last instanceof AbstractEndNode) : "Algorithm only supports EndNode and LoopEndNode.";
                int startTos = tos;
                Block[] ifPred = new Block[] { block };
                for (Node suxNode : last.successors()) {
                    Block sux = nodeMap.get(suxNode);
                    stack[++tos] = sux;
                    sux.setPredecessors(ifPred);
                }
                int suxCount = tos - startTos;
                Block[] successors = new Block[suxCount];
                System.arraycopy(stack, startTos + 1, successors, 0, suxCount);
                block.setSuccessors(successors);
            }
            block.setId(BLOCK_ID_VISITED);
            AbstractBeginNode beginNode = block.getBeginNode();
            if (beginNode instanceof LoopBeginNode) {
                computeLoopPredecessors(nodeMap, block, (LoopBeginNode) beginNode);
            } else if (beginNode instanceof MergeNode) {
                MergeNode mergeNode = (MergeNode) beginNode;
                int forwardEndCount = mergeNode.forwardEndCount();
                Block[] predecessors = new Block[forwardEndCount];
                for (int i = 0; i < forwardEndCount; ++i) {
                    predecessors[i] = nodeMap.get(mergeNode.forwardEndAt(i));
                }
                block.setPredecessors(predecessors);
            }
        } else if (id == BLOCK_ID_VISITED) {
            // Second time we see this block: All successors have been processed, so add block
            // to result list. Can safely reuse the stack for this.
            --tos;
            count++;
            int index = numBlocks - count;
            stack[index] = block;
            block.setId(index);
        } else {
            throw GraalError.shouldNotReachHere();
        }
    } while (tos >= 0);
    // Compute reverse postorder and number blocks.
    assert count == numBlocks : "all blocks must be reachable";
    this.reversePostOrder = stack;
}
Also used : ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) 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) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) ControlSinkNode(org.graalvm.compiler.nodes.ControlSinkNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) 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)

Example 44 with AbstractBeginNode

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

the class ControlFlowGraph method computeLoopInformation.

private void computeLoopInformation() {
    loops = new ArrayList<>();
    if (graph.hasLoops()) {
        Block[] stack = new Block[this.reversePostOrder.length];
        for (Block block : reversePostOrder) {
            AbstractBeginNode beginNode = block.getBeginNode();
            if (beginNode instanceof LoopBeginNode) {
                Loop<Block> parent = block.getLoop();
                Loop<Block> loop = new HIRLoop(parent, loops.size(), block);
                if (parent != null) {
                    parent.getChildren().add(loop);
                }
                loops.add(loop);
                block.setLoop(loop);
                loop.getBlocks().add(block);
                LoopBeginNode loopBegin = (LoopBeginNode) beginNode;
                for (LoopEndNode end : loopBegin.loopEnds()) {
                    Block endBlock = nodeToBlock.get(end);
                    computeLoopBlocks(endBlock, loop, stack, true);
                }
                if (graph.getGuardsStage() != GuardsStage.AFTER_FSA) {
                    for (LoopExitNode exit : loopBegin.loopExits()) {
                        Block exitBlock = nodeToBlock.get(exit);
                        assert exitBlock.getPredecessorCount() == 1;
                        computeLoopBlocks(exitBlock.getFirstPredecessor(), loop, stack, true);
                        loop.addExit(exitBlock);
                    }
                    // The following loop can add new blocks to the end of the loop's block
                    // list.
                    int size = loop.getBlocks().size();
                    for (int i = 0; i < size; ++i) {
                        Block b = loop.getBlocks().get(i);
                        for (Block sux : b.getSuccessors()) {
                            if (sux.getLoop() != loop) {
                                AbstractBeginNode begin = sux.getBeginNode();
                                if (!(begin instanceof LoopExitNode && ((LoopExitNode) begin).loopBegin() == loopBegin)) {
                                    graph.getDebug().log(DebugContext.VERBOSE_LEVEL, "Unexpected loop exit with %s, including whole branch in the loop", sux);
                                    computeLoopBlocks(sux, loop, stack, false);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    /*
         * Compute the loop exit blocks after FSA.
         */
    if (graph.getGuardsStage() == GuardsStage.AFTER_FSA) {
        for (Block b : reversePostOrder) {
            if (b.getLoop() != null) {
                for (Block succ : b.getSuccessors()) {
                    // if the loop of the succ is a different one (or none)
                    if (b.getLoop() != succ.getLoop()) {
                        // and the succ loop is not a child loop of the curr one
                        if (succ.getLoop() == null) {
                            // we might exit multiple loops if b.loops is not a loop at depth 0
                            Loop<Block> curr = b.getLoop();
                            while (curr != null) {
                                curr.addExit(succ);
                                curr = curr.getParent();
                            }
                        } else {
                            /*
                                 * succ also has a loop, might be a child loop
                                 *
                                 * if it is a child loop we do not exit a loop. if it is a loop
                                 * different than b.loop and not a child loop it must be a parent
                                 * loop, thus we exit all loops between b.loop and succ.loop
                                 *
                                 * if we exit multiple loops immediately after each other the
                                 * bytecode parser might generate loop exit nodes after another and
                                 * the CFG will identify them as separate blocks, we just take the
                                 * first one and exit all loops at this one
                                 */
                            if (succ.getLoop().getParent() != b.getLoop()) {
                                assert succ.getLoop().getDepth() < b.getLoop().getDepth();
                                // b.loop must not be a transitive parent of succ.loop
                                assert !Loop.transitiveParentLoop(succ.getLoop(), b.getLoop());
                                Loop<Block> curr = b.getLoop();
                                while (curr != null && curr != succ.getLoop()) {
                                    curr.addExit(succ);
                                    curr = curr.getParent();
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode)

Example 45 with AbstractBeginNode

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

the class ControlFlowGraph method identifyBlock.

private void identifyBlock(Block block) {
    FixedWithNextNode cur = block.getBeginNode();
    while (true) {
        assert !cur.isDeleted();
        assert nodeToBlock.get(cur) == null;
        nodeToBlock.set(cur, block);
        FixedNode next = cur.next();
        if (next instanceof AbstractBeginNode) {
            block.endNode = cur;
            return;
        } else if (next instanceof FixedWithNextNode) {
            cur = (FixedWithNextNode) next;
        } else {
            nodeToBlock.set(next, block);
            block.endNode = next;
            return;
        }
    }
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Aggregations

AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)63 FixedNode (org.graalvm.compiler.nodes.FixedNode)32 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)31 Node (org.graalvm.compiler.graph.Node)24 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)23 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)23 EndNode (org.graalvm.compiler.nodes.EndNode)22 BeginNode (org.graalvm.compiler.nodes.BeginNode)21 ValueNode (org.graalvm.compiler.nodes.ValueNode)20 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)16 IfNode (org.graalvm.compiler.nodes.IfNode)16 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)15 MergeNode (org.graalvm.compiler.nodes.MergeNode)15 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)15 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)14 PhiNode (org.graalvm.compiler.nodes.PhiNode)14 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)13 LogicNode (org.graalvm.compiler.nodes.LogicNode)12 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)11 DeoptimizeNode (org.graalvm.compiler.nodes.DeoptimizeNode)11