Search in sources :

Example 31 with LoopBeginNode

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

the class PartialEscapeClosure method stripKilledLoopLocations.

@Override
protected BlockT stripKilledLoopLocations(Loop<Block> loop, BlockT originalInitialState) {
    BlockT initialState = super.stripKilledLoopLocations(loop, originalInitialState);
    if (loop.getDepth() > GraalOptions.EscapeAnalysisLoopCutoff.getValue(cfg.graph.getOptions())) {
        /*
             * After we've reached the maximum loop nesting, we'll simply materialize everything we
             * can to make sure that the loops only need to be iterated one time. Care is taken here
             * to not materialize virtual objects that have the "ensureVirtualized" flag set.
             */
        LoopBeginNode loopBegin = (LoopBeginNode) loop.getHeader().getBeginNode();
        AbstractEndNode end = loopBegin.forwardEnd();
        Block loopPredecessor = loop.getHeader().getFirstPredecessor();
        assert loopPredecessor.getEndNode() == end;
        int length = initialState.getStateCount();
        boolean change;
        BitSet ensureVirtualized = new BitSet(length);
        for (int i = 0; i < length; i++) {
            ObjectState state = initialState.getObjectStateOptional(i);
            if (state != null && state.isVirtual() && state.getEnsureVirtualized()) {
                ensureVirtualized.set(i);
            }
        }
        do {
            // propagate "ensureVirtualized" flag
            change = false;
            for (int i = 0; i < length; i++) {
                if (!ensureVirtualized.get(i)) {
                    ObjectState state = initialState.getObjectStateOptional(i);
                    if (state != null && state.isVirtual()) {
                        for (ValueNode entry : state.getEntries()) {
                            if (entry instanceof VirtualObjectNode) {
                                if (ensureVirtualized.get(((VirtualObjectNode) entry).getObjectId())) {
                                    change = true;
                                    ensureVirtualized.set(i);
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        } while (change);
        for (int i = 0; i < length; i++) {
            ObjectState state = initialState.getObjectStateOptional(i);
            if (state != null && state.isVirtual() && !ensureVirtualized.get(i)) {
                initialState.materializeBefore(end, virtualObjects.get(i), blockEffects.get(loopPredecessor));
            }
        }
    }
    return initialState;
}
Also used : VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) VirtualObjectState(org.graalvm.compiler.virtual.nodes.VirtualObjectState) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) BitSet(java.util.BitSet) ValueNode(org.graalvm.compiler.nodes.ValueNode) Block(org.graalvm.compiler.nodes.cfg.Block)

Example 32 with LoopBeginNode

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

the class PartialEscapeClosure method processInitialLoopState.

@Override
protected void processInitialLoopState(Loop<Block> loop, BlockT initialState) {
    for (PhiNode phi : ((LoopBeginNode) loop.getHeader().getBeginNode()).phis()) {
        if (phi.valueAt(0) != null) {
            ValueNode alias = getAliasAndResolve(initialState, phi.valueAt(0));
            if (alias instanceof VirtualObjectNode) {
                VirtualObjectNode virtual = (VirtualObjectNode) alias;
                addVirtualAlias(virtual, phi);
            } else {
                aliases.set(phi, null);
            }
        }
    }
}
Also used : VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode)

Example 33 with LoopBeginNode

use of org.graalvm.compiler.nodes.LoopBeginNode 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)

Example 34 with LoopBeginNode

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

the class LoopPhiCanonicalizerTest method test.

@Test
public void test() {
    StructuredGraph graph = parseEager("loopSnippet", AllowAssumptions.YES);
    NodePredicate loopPhis = node -> node instanceof PhiNode && ((PhiNode) node).merge() instanceof LoopBeginNode;
    PhaseContext context = new PhaseContext(getProviders());
    Assert.assertEquals(5, graph.getNodes().filter(loopPhis).count());
    new CanonicalizerPhase().apply(graph, context);
    Assert.assertEquals(2, graph.getNodes().filter(loopPhis).count());
    test("loopSnippet");
}
Also used : LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) NodePredicate(org.graalvm.compiler.graph.iterators.NodePredicate) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) BeforeClass(org.junit.BeforeClass) CanonicalizerPhase(org.graalvm.compiler.phases.common.CanonicalizerPhase) Test(org.junit.Test) PhaseContext(org.graalvm.compiler.phases.tiers.PhaseContext) GraalCompilerTest(org.graalvm.compiler.core.test.GraalCompilerTest) Assert(org.junit.Assert) AllowAssumptions(org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions) PhiNode(org.graalvm.compiler.nodes.PhiNode) PhaseContext(org.graalvm.compiler.phases.tiers.PhaseContext) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) PhiNode(org.graalvm.compiler.nodes.PhiNode) CanonicalizerPhase(org.graalvm.compiler.phases.common.CanonicalizerPhase) NodePredicate(org.graalvm.compiler.graph.iterators.NodePredicate) Test(org.junit.Test) GraalCompilerTest(org.graalvm.compiler.core.test.GraalCompilerTest)

Example 35 with LoopBeginNode

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

the class LoopFragmentInside method nodes.

@Override
public NodeBitMap nodes() {
    if (nodes == null) {
        LoopFragmentWhole whole = loop().whole();
        // init nodes bitmap in whole
        whole.nodes();
        nodes = whole.nodes.copy();
        // remove the phis
        LoopBeginNode loopBegin = loop().loopBegin();
        for (PhiNode phi : loopBegin.phis()) {
            nodes.clear(phi);
        }
        clearStateNodes(loopBegin);
        for (LoopExitNode exit : exits()) {
            clearStateNodes(exit);
            for (ProxyNode proxy : exit.proxies()) {
                nodes.clear(proxy);
            }
        }
    }
    return nodes;
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) MemoryPhiNode(org.graalvm.compiler.nodes.memory.MemoryPhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode)

Aggregations

LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)61 FixedNode (org.graalvm.compiler.nodes.FixedNode)30 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)26 LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)24 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)23 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)22 Node (org.graalvm.compiler.graph.Node)21 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)21 EndNode (org.graalvm.compiler.nodes.EndNode)20 PhiNode (org.graalvm.compiler.nodes.PhiNode)20 ValueNode (org.graalvm.compiler.nodes.ValueNode)20 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)19 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)14 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)13 MergeNode (org.graalvm.compiler.nodes.MergeNode)11 ProxyNode (org.graalvm.compiler.nodes.ProxyNode)10 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)10 ArrayList (java.util.ArrayList)9 IfNode (org.graalvm.compiler.nodes.IfNode)9 LogicNode (org.graalvm.compiler.nodes.LogicNode)9