Search in sources :

Example 16 with EndNode

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

the class GraphKit method endInvokeWithException.

/**
 * Finishes a control flow started with {@link #startInvokeWithException}. If necessary, creates
 * a merge of the non-exception and exception edges. The merge node is returned and the
 * non-exception edge is the first forward end of the merge, the exception edge is the second
 * forward end (relevant for phi nodes).
 */
public AbstractMergeNode endInvokeWithException() {
    InvokeWithExceptionStructure s = saveLastInvokeWithExceptionNode();
    FixedWithNextNode noExceptionEdge = s.noExceptionEdge instanceof FixedWithNextNode ? (FixedWithNextNode) s.noExceptionEdge : null;
    FixedWithNextNode exceptionEdge = s.exceptionEdge instanceof FixedWithNextNode ? (FixedWithNextNode) s.exceptionEdge : null;
    AbstractMergeNode merge = null;
    if (noExceptionEdge != null && exceptionEdge != null) {
        EndNode noExceptionEnd = graph.add(new EndNode());
        graph.addAfterFixed(noExceptionEdge, noExceptionEnd);
        EndNode exceptionEnd = graph.add(new EndNode());
        graph.addAfterFixed(exceptionEdge, exceptionEnd);
        merge = graph.add(new MergeNode());
        merge.addForwardEnd(noExceptionEnd);
        merge.addForwardEnd(exceptionEnd);
        lastFixedNode = merge;
    } else if (noExceptionEdge != null) {
        lastFixedNode = noExceptionEdge;
    } else if (exceptionEdge != null) {
        lastFixedNode = exceptionEdge;
    } else {
        assert lastFixedNode == null;
    }
    s.state = InvokeWithExceptionStructure.State.FINISHED;
    popStructure();
    return merge;
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) EndNode(org.graalvm.compiler.nodes.EndNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode)

Example 17 with EndNode

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

the class BytecodeParser method appendLoopBegin.

@SuppressWarnings("try")
private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext, int startBci) {
    try (DebugCloseable context = openNodeContext(frameState, startBci)) {
        EndNode preLoopEnd = graph.add(new EndNode());
        LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
        if (disableLoopSafepoint()) {
            loopBegin.disableSafepoint();
        }
        fixedWithNext.setNext(preLoopEnd);
        // Add the single non-loop predecessor of the loop header.
        loopBegin.addForwardEnd(preLoopEnd);
        return loopBegin;
    }
}
Also used : LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) EndNode(org.graalvm.compiler.nodes.EndNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable)

Example 18 with EndNode

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

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

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

the class ExpandLogicPhase method processIf.

@SuppressWarnings("try")
private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
    try (DebugCloseable context = ifNode.withNodeSourcePosition()) {
        /*
             * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into
             * two separate IfNodes: if(X) and if(Y)
             *
             * for computing the probabilities P(X) and P(Y), we use two different approaches. The
             * first one assumes that the shortCircuitProbability and the probability on the IfNode
             * were created with each other in mind. If this assumption does not hold, we fall back
             * to another mechanism for computing the probabilities.
             */
        AbstractBeginNode trueTarget = ifNode.trueSuccessor();
        AbstractBeginNode falseTarget = ifNode.falseSuccessor();
        // 1st approach
        // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
        double firstIfTrueProbability = shortCircuitProbability;
        double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability));
        double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability;
        if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) {
            /*
                 * 2nd approach
                 *
                 * the assumption above did not hold, so we either used an artificial probability as
                 * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode.
                 *
                 * so, we distribute the if's trueSuccessorProbability between the newly generated
                 * if nodes according to the shortCircuitProbability. the following invariant is
                 * always true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) *
                 * P(Y))
                 */
            firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability;
            secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability)));
        }
        ifNode.clearSuccessors();
        Graph graph = ifNode.graph();
        AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
        trueTargetMerge.setNext(trueTarget);
        EndNode firstTrueEnd = graph.add(new EndNode());
        EndNode secondTrueEnd = graph.add(new EndNode());
        trueTargetMerge.addForwardEnd(firstTrueEnd);
        trueTargetMerge.addForwardEnd(secondTrueEnd);
        AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
        AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
        if (yNegated) {
            secondIfTrueProbability = 1.0 - secondIfTrueProbability;
        }
        if (xNegated) {
            firstIfTrueProbability = 1.0 - firstIfTrueProbability;
        }
        AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability)));
        IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability));
        ifNode.replaceAtPredecessor(firstIf);
        ifNode.safeDelete();
    }
}
Also used : AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) Graph(org.graalvm.compiler.graph.Graph) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) EndNode(org.graalvm.compiler.nodes.EndNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Aggregations

EndNode (org.graalvm.compiler.nodes.EndNode)30 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)22 FixedNode (org.graalvm.compiler.nodes.FixedNode)18 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)16 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)15 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)14 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)13 MergeNode (org.graalvm.compiler.nodes.MergeNode)13 Node (org.graalvm.compiler.graph.Node)12 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)12 ValueNode (org.graalvm.compiler.nodes.ValueNode)10 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)9 PhiNode (org.graalvm.compiler.nodes.PhiNode)9 BeginNode (org.graalvm.compiler.nodes.BeginNode)7 ControlSinkNode (org.graalvm.compiler.nodes.ControlSinkNode)7 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)7 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)7 FrameState (org.graalvm.compiler.nodes.FrameState)6 IfNode (org.graalvm.compiler.nodes.IfNode)6 ValuePhiNode (org.graalvm.compiler.nodes.ValuePhiNode)6