Search in sources :

Example 26 with AbstractBeginNode

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

the class SinglePassNodeIterator method nextQueuedNode.

/**
 * This method is invoked upon not having a (single) next {@link FixedNode} to visit. This
 * method picks such next-node-to-visit from {@link #nodeQueue} and updates {@link #state} with
 * the pre-state for that node.
 *
 * <p>
 * Upon reaching a {@link AbstractMergeNode}, some entries are pruned from {@link #nodeStates}
 * (ie, the entries associated to forward-ends for that merge-node).
 * </p>
 */
private FixedNode nextQueuedNode() {
    if (nodeQueue.isEmpty()) {
        return null;
    }
    PathStart<T> elem = nodeQueue.removeFirst();
    if (elem.node instanceof AbstractMergeNode) {
        AbstractMergeNode merge = (AbstractMergeNode) elem.node;
        state = pruneEntry(merge.forwardEndAt(0));
        ArrayList<T> states = new ArrayList<>(merge.forwardEndCount() - 1);
        for (int i = 1; i < merge.forwardEndCount(); i++) {
            T other = pruneEntry(merge.forwardEndAt(i));
            states.add(other);
        }
        boolean ready = state.merge(merge, states);
        assert ready : "Not a single-pass iterator after all";
        return merge;
    } else {
        AbstractBeginNode begin = elem.node;
        assert begin.predecessor() != null;
        state = elem.stateOnEntry;
        state.afterSplit(begin);
        return begin;
    }
}
Also used : ArrayList(java.util.ArrayList) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 27 with AbstractBeginNode

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

the class FixedNodeProbabilityCache method findBegin.

private static FixedNode findBegin(FixedNode node) {
    FixedNode current = node;
    while (true) {
        assert current != null;
        Node predecessor = current.predecessor();
        if (current instanceof AbstractBeginNode) {
            if (predecessor == null) {
                break;
            } else if (predecessor.successors().count() != 1) {
                assert predecessor instanceof ControlSplitNode : "a FixedNode with multiple successors needs to be a ControlSplitNode: " + current + " / " + predecessor;
                break;
            }
        } else if (predecessor == null) {
            current = null;
            break;
        }
        current = (FixedNode) predecessor;
    }
    return current;
}
Also used : LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) StartNode(org.graalvm.compiler.nodes.StartNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 28 with AbstractBeginNode

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

the class MemoryScheduleVerification method processBlock.

@Override
protected EconomicSet<FloatingReadNode> processBlock(Block block, EconomicSet<FloatingReadNode> currentState) {
    AbstractBeginNode beginNode = block.getBeginNode();
    if (beginNode instanceof AbstractMergeNode) {
        AbstractMergeNode abstractMergeNode = (AbstractMergeNode) beginNode;
        for (PhiNode phi : abstractMergeNode.phis()) {
            if (phi instanceof MemoryPhiNode) {
                MemoryPhiNode memoryPhiNode = (MemoryPhiNode) phi;
                addFloatingReadUsages(currentState, memoryPhiNode);
            }
        }
    }
    for (Node n : blockToNodesMap.get(block)) {
        if (n instanceof MemoryCheckpoint) {
            if (n instanceof MemoryCheckpoint.Single) {
                MemoryCheckpoint.Single single = (MemoryCheckpoint.Single) n;
                processLocation(n, single.getLocationIdentity(), currentState);
            } else if (n instanceof MemoryCheckpoint.Multi) {
                MemoryCheckpoint.Multi multi = (MemoryCheckpoint.Multi) n;
                for (LocationIdentity location : multi.getLocationIdentities()) {
                    processLocation(n, location, currentState);
                }
            }
            addFloatingReadUsages(currentState, n);
        } else if (n instanceof MemoryNode) {
            addFloatingReadUsages(currentState, n);
        } else if (n instanceof FloatingReadNode) {
            FloatingReadNode floatingReadNode = (FloatingReadNode) n;
            if (floatingReadNode.getLastLocationAccess() != null && floatingReadNode.getLocationIdentity().isMutable()) {
                if (currentState.contains(floatingReadNode)) {
                    // Floating read was found in the state.
                    currentState.remove(floatingReadNode);
                } else {
                    throw new RuntimeException("Floating read node " + n + " was not found in the state, i.e., it was killed by a memory check point before its place in the schedule. Block=" + block + ", block begin: " + block.getBeginNode() + " block loop: " + block.getLoop() + ", " + blockToNodesMap.get(block).get(0));
                }
            }
        }
    }
    return currentState;
}
Also used : MemoryNode(org.graalvm.compiler.nodes.memory.MemoryNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) MemoryNode(org.graalvm.compiler.nodes.memory.MemoryNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) Node(org.graalvm.compiler.graph.Node) PhiNode(org.graalvm.compiler.nodes.PhiNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) MemoryCheckpoint(org.graalvm.compiler.nodes.memory.MemoryCheckpoint) FloatingReadNode(org.graalvm.compiler.nodes.memory.FloatingReadNode) LocationIdentity(org.graalvm.word.LocationIdentity)

Example 29 with AbstractBeginNode

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

the class PEReadEliminationClosure method processKilledLoopLocations.

@Override
protected void processKilledLoopLocations(Loop<Block> loop, PEReadEliminationBlockState initialState, PEReadEliminationBlockState mergedStates) {
    assert initialState != null;
    assert mergedStates != null;
    if (initialState.readCache.size() > 0) {
        LoopKillCache loopKilledLocations = loopLocationKillCache.get(loop);
        // it is visited
        if (loopKilledLocations == null) {
            loopKilledLocations = new LoopKillCache(1);
            loopLocationKillCache.put(loop, loopKilledLocations);
        } else {
            AbstractBeginNode beginNode = loop.getHeader().getBeginNode();
            OptionValues options = beginNode.getOptions();
            if (loopKilledLocations.visits() > ReadEliminationMaxLoopVisits.getValue(options)) {
                // we have processed the loop too many times, kill all locations so the inner
                // loop will never be processed more than once again on visit
                loopKilledLocations.setKillsAll();
            } else {
                // we have fully processed this loop >1 times, update the killed locations
                EconomicSet<LocationIdentity> forwardEndLiveLocations = EconomicSet.create(Equivalence.DEFAULT);
                for (ReadCacheEntry entry : initialState.readCache.getKeys()) {
                    forwardEndLiveLocations.add(entry.identity);
                }
                for (ReadCacheEntry entry : mergedStates.readCache.getKeys()) {
                    forwardEndLiveLocations.remove(entry.identity);
                }
                // loop
                for (LocationIdentity location : forwardEndLiveLocations) {
                    loopKilledLocations.rememberLoopKilledLocation(location);
                }
                if (debug.isLogEnabled() && loopKilledLocations != null) {
                    debug.log("[Early Read Elimination] Setting loop killed locations of loop at node %s with %s", beginNode, forwardEndLiveLocations);
                }
            }
            // remember the loop visit
            loopKilledLocations.visited();
        }
    }
}
Also used : OptionValues(org.graalvm.compiler.options.OptionValues) ReadCacheEntry(org.graalvm.compiler.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry) LocationIdentity(org.graalvm.word.LocationIdentity) FieldLocationIdentity(org.graalvm.compiler.nodes.FieldLocationIdentity) NamedLocationIdentity(org.graalvm.compiler.nodes.NamedLocationIdentity) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 30 with AbstractBeginNode

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

the class HostedBytecodeParser method finishInstruction.

/**
 * Insert deopt entries after all state splits.
 */
@Override
protected FixedWithNextNode finishInstruction(FixedWithNextNode instr, FrameStateBuilder stateBuilder) {
    if (getMethod().compilationInfo.isDeoptTarget() && !parsingIntrinsic()) {
        FrameState stateAfter = null;
        if (instr instanceof StateSplit && !(instr instanceof DeoptEntryNode)) {
            /*
                 * The regular case: the instruction is a state split and we insert a DeoptEntryNode
                 * right after it.
                 */
            StateSplit stateSplit = (StateSplit) instr;
            stateAfter = stateSplit.stateAfter();
        } else if (instr instanceof AbstractBeginNode) {
            /*
                 * We are at a block begin. If the block predecessor is a LoopExitNode or an
                 * InvokeWithException (both are state splits), we didn't inserted a deopt entry
                 * yet. So we do it at the begin of a block.
                 *
                 * Note that this only happens if the LoopExitNode/InvokeWithException is the
                 * _single_ predcessor of this block. In case of multiple predecessors, the block
                 * starts with a MergeNode and this is handled like a regular case.
                 */
            Node predecessor = instr.predecessor();
            if (predecessor instanceof KillingBeginNode) {
                /*
                     * This is between an InvokeWithException and the BlockPlaceholderNode.
                     */
                predecessor = predecessor.predecessor();
            }
            if (predecessor instanceof StateSplit && !(predecessor instanceof DeoptEntryNode)) {
                stateAfter = ((StateSplit) predecessor).stateAfter();
            }
        }
        boolean needsDeoptEntry = false;
        boolean needsProxies = false;
        if (stateAfter != null) {
            if (getMethod().compilationInfo.isDeoptEntry(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException())) {
                needsDeoptEntry = true;
                needsProxies = true;
            } else if (instr.predecessor() instanceof Invoke && getMethod().compilationInfo.isDeoptEntry(((Invoke) instr.predecessor()).bci(), true, false)) {
                /*
                     * Invoke nodes can be implicit deoptimization entry points. But we cannot
                     * anchor proxy nodes on invocations: The invoke has two successors (normal and
                     * exception handler), and we need to proxy values at the beginning of both.
                     */
                needsProxies = true;
            } else if (instr instanceof ExceptionObjectNode && getMethod().compilationInfo.isDeoptEntry(((ExceptionObjectNode) instr).stateAfter().bci, true, false)) {
                /*
                     * The predecessor of the ExceptionObjectNode will be an Invoke, but the Invoke
                     * has not been created yet. So the check above for the predecessor does not
                     * trigger.
                     */
                needsProxies = true;
            }
        }
        if (needsProxies) {
            long encodedBci = FrameInfoEncoder.encodeBci(stateAfter.bci, stateAfter.duringCall(), stateAfter.rethrowException());
            DeoptProxyAnchorNode existingDeoptEntry = deoptEntries.get(encodedBci);
            if (existingDeoptEntry != STICKY_DEOPT_ENTRY) {
                if (existingDeoptEntry != null) {
                    /*
                         * Some state splits (i.e. MergeNode and DispatchBeginNode) do not have a
                         * correspondent byte code. Therefore there can be a previously added deopt
                         * entry with the same BCI. For MergeNodes we replace the previous entry
                         * because the new frame state has less live locals.
                         */
                    existingDeoptEntry.replaceAtUsages(null);
                    graph.removeFixed(existingDeoptEntry);
                    deoptEntries.remove(encodedBci);
                    if (existingDeoptEntry instanceof DeoptEntryNode) {
                        /*
                             * We already had a DeoptEntryNode registered earlier for some reason,
                             * so be conservative and create one again (and not just a
                             * DeoptProxyAnchorNode).
                             */
                        needsDeoptEntry = true;
                    }
                }
                assert !deoptEntries.containsKey(encodedBci) : "duplicate deopt entry for encoded BCI " + encodedBci;
                DeoptProxyAnchorNode deoptEntry = createDeoptEntry(stateBuilder, stateAfter, !needsDeoptEntry);
                if (instr instanceof LoopBeginNode) {
                    /*
                         * Loop headers to not have their own bci. Never move a deopt entry for the
                         * loop header down, e.g., into a loop end (that might then end up to be
                         * dead code).
                         */
                    deoptEntries.put(encodedBci, STICKY_DEOPT_ENTRY);
                } else {
                    deoptEntries.put(encodedBci, deoptEntry);
                }
                assert instr.next() == null : "cannot append instruction to instruction which isn't end (" + instr + "->" + instr.next() + ")";
                instr.setNext(deoptEntry);
                return deoptEntry;
            }
        }
    }
    return super.finishInstruction(instr, stateBuilder);
}
Also used : DeoptProxyAnchorNode(com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) DeoptEntryNode(com.oracle.svm.core.graal.nodes.DeoptEntryNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) SubstrateMethodCallTargetNode(com.oracle.svm.hosted.nodes.SubstrateMethodCallTargetNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) DeoptEntryNode(com.oracle.svm.core.graal.nodes.DeoptEntryNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) DeoptProxyAnchorNode(com.oracle.svm.core.graal.nodes.DeoptProxyAnchorNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) DeoptProxyNode(com.oracle.svm.hosted.nodes.DeoptProxyNode) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) KillingBeginNode(org.graalvm.compiler.nodes.KillingBeginNode) FrameState(org.graalvm.compiler.nodes.FrameState) StateSplit(org.graalvm.compiler.nodes.StateSplit) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke)

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