Search in sources :

Example 16 with LoopExitNode

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

the class LoopFragment method computeNodes.

protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
    for (AbstractBeginNode b : blocks) {
        if (b.isDeleted()) {
            continue;
        }
        for (Node n : b.getBlockNodes()) {
            if (n instanceof Invoke) {
                nodes.mark(((Invoke) n).callTarget());
            }
            if (n instanceof NodeWithState) {
                NodeWithState withState = (NodeWithState) n;
                withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
            }
            if (n instanceof AbstractMergeNode) {
                // if a merge is in the loop, all of its phis are also in the loop
                for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
                    nodes.mark(phi);
                }
            }
            nodes.mark(n);
        }
    }
    for (AbstractBeginNode earlyExit : earlyExits) {
        if (earlyExit.isDeleted()) {
            continue;
        }
        nodes.mark(earlyExit);
        if (earlyExit instanceof LoopExitNode) {
            LoopExitNode loopExit = (LoopExitNode) earlyExit;
            FrameState stateAfter = loopExit.stateAfter();
            if (stateAfter != null) {
                stateAfter.applyToVirtual(node -> nodes.mark(node));
            }
            for (ProxyNode proxy : loopExit.proxies()) {
                nodes.mark(proxy);
            }
        }
    }
    final NodeBitMap nonLoopNodes = graph.createNodeBitMap();
    Deque<WorkListEntry> worklist = new ArrayDeque<>();
    for (AbstractBeginNode b : blocks) {
        if (b.isDeleted()) {
            continue;
        }
        for (Node n : b.getBlockNodes()) {
            if (n instanceof CommitAllocationNode) {
                for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
                    markFloating(worklist, obj, nodes, nonLoopNodes);
                }
            }
            if (n instanceof MonitorEnterNode) {
                markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
            }
            if (n instanceof AbstractMergeNode) {
                /*
                     * Since we already marked all phi nodes as being in the loop to break cycles,
                     * we also have to iterate over their usages here.
                     */
                for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
                    for (Node usage : phi.usages()) {
                        markFloating(worklist, usage, nodes, nonLoopNodes);
                    }
                }
            }
            for (Node usage : n.usages()) {
                markFloating(worklist, usage, nodes, nonLoopNodes);
            }
        }
    }
}
Also used : GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) Deque(java.util.Deque) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) TriState(jdk.vm.ci.meta.TriState) EconomicMap(org.graalvm.collections.EconomicMap) MergeNode(org.graalvm.compiler.nodes.MergeNode) VirtualState(org.graalvm.compiler.nodes.VirtualState) FixedNode(org.graalvm.compiler.nodes.FixedNode) NodeWithState(org.graalvm.compiler.nodes.spi.NodeWithState) Iterator(java.util.Iterator) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) NodeView(org.graalvm.compiler.nodes.NodeView) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) Graph(org.graalvm.compiler.graph.Graph) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) DuplicationReplacement(org.graalvm.compiler.graph.Graph.DuplicationReplacement) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) FrameState(org.graalvm.compiler.nodes.FrameState) NodeIterable(org.graalvm.compiler.graph.iterators.NodeIterable) Invoke(org.graalvm.compiler.nodes.Invoke) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Block(org.graalvm.compiler.nodes.cfg.Block) GraalError(org.graalvm.compiler.debug.GraalError) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) NodeBitMap(org.graalvm.compiler.graph.NodeBitMap) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) GuardProxyNode(org.graalvm.compiler.nodes.GuardProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MergeNode(org.graalvm.compiler.nodes.MergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ValueProxyNode(org.graalvm.compiler.nodes.ValueProxyNode) GuardPhiNode(org.graalvm.compiler.nodes.GuardPhiNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FrameState(org.graalvm.compiler.nodes.FrameState) ArrayDeque(java.util.ArrayDeque) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) Invoke(org.graalvm.compiler.nodes.Invoke) MonitorEnterNode(org.graalvm.compiler.nodes.java.MonitorEnterNode) NodeWithState(org.graalvm.compiler.nodes.spi.NodeWithState) CommitAllocationNode(org.graalvm.compiler.nodes.virtual.CommitAllocationNode)

Example 17 with LoopExitNode

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

Example 18 with LoopExitNode

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

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

the class GraphUtil method checkRedundantProxy.

public static void checkRedundantProxy(ProxyNode vpn) {
    if (vpn.isDeleted()) {
        return;
    }
    AbstractBeginNode proxyPoint = vpn.proxyPoint();
    if (proxyPoint instanceof LoopExitNode) {
        LoopExitNode exit = (LoopExitNode) proxyPoint;
        LoopBeginNode loopBegin = exit.loopBegin();
        Node vpnValue = vpn.value();
        for (ValueNode v : loopBegin.stateAfter().values()) {
            ValueNode v2 = v;
            if (loopBegin.isPhiAtMerge(v2)) {
                v2 = ((PhiNode) v2).valueAt(loopBegin.forwardEnd());
            }
            if (vpnValue == v2) {
                Collection<PhiNode> phiUsages = vpn.usages().filter(PhiNode.class).snapshot();
                Collection<ProxyNode> proxyUsages = vpn.usages().filter(ProxyNode.class).snapshot();
                vpn.replaceAtUsagesAndDelete(vpnValue);
                for (PhiNode phi : phiUsages) {
                    checkRedundantPhi(phi);
                }
                for (ProxyNode proxy : proxyUsages) {
                    checkRedundantProxy(proxy);
                }
                return;
            }
        }
    }
}
Also used : ProxyNode(org.graalvm.compiler.nodes.ProxyNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) MonitorIdNode(org.graalvm.compiler.nodes.java.MonitorIdNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) LoadIndexedNode(org.graalvm.compiler.nodes.java.LoadIndexedNode) LoopBeginNode(org.graalvm.compiler.nodes.LoopBeginNode) VirtualObjectNode(org.graalvm.compiler.nodes.virtual.VirtualObjectNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) PiNode(org.graalvm.compiler.nodes.PiNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) VirtualArrayNode(org.graalvm.compiler.nodes.virtual.VirtualArrayNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LoopEndNode(org.graalvm.compiler.nodes.LoopEndNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) PhiNode(org.graalvm.compiler.nodes.PhiNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode)

Example 20 with LoopExitNode

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

the class ConvertDeoptimizeToGuardPhase method propagateFixed.

@SuppressWarnings("try")
private void propagateFixed(FixedNode from, StaticDeoptimizingNode deopt, LoweringProvider loweringProvider) {
    Node current = from;
    while (current != null) {
        if (GraalOptions.GuardPriorities.getValue(from.getOptions()) && current instanceof FixedGuardNode) {
            FixedGuardNode otherGuard = (FixedGuardNode) current;
            if (otherGuard.computePriority().isHigherPriorityThan(deopt.computePriority())) {
                moveAsDeoptAfter(otherGuard, deopt);
                return;
            }
        } else if (current instanceof AbstractBeginNode) {
            if (current instanceof AbstractMergeNode) {
                AbstractMergeNode mergeNode = (AbstractMergeNode) current;
                FixedNode next = mergeNode.next();
                while (mergeNode.isAlive()) {
                    AbstractEndNode end = mergeNode.forwardEnds().first();
                    propagateFixed(end, deopt, loweringProvider);
                }
                assert next.isAlive();
                propagateFixed(next, deopt, loweringProvider);
                return;
            } else if (current.predecessor() instanceof IfNode) {
                IfNode ifNode = (IfNode) current.predecessor();
                // Prioritize the source position of the IfNode
                try (DebugCloseable closable = ifNode.withNodeSourcePosition()) {
                    StructuredGraph graph = ifNode.graph();
                    LogicNode conditionNode = ifNode.condition();
                    boolean negateGuardCondition = current == ifNode.trueSuccessor();
                    FixedGuardNode guard = graph.add(new FixedGuardNode(conditionNode, deopt.getReason(), deopt.getAction(), deopt.getSpeculation(), negateGuardCondition));
                    FixedWithNextNode pred = (FixedWithNextNode) ifNode.predecessor();
                    AbstractBeginNode survivingSuccessor;
                    if (negateGuardCondition) {
                        survivingSuccessor = ifNode.falseSuccessor();
                    } else {
                        survivingSuccessor = ifNode.trueSuccessor();
                    }
                    graph.removeSplitPropagate(ifNode, survivingSuccessor);
                    Node newGuard = guard;
                    if (survivingSuccessor instanceof LoopExitNode) {
                        newGuard = ProxyNode.forGuard(guard, (LoopExitNode) survivingSuccessor, graph);
                    }
                    survivingSuccessor.replaceAtUsages(InputType.Guard, newGuard);
                    graph.getDebug().log("Converting deopt on %-5s branch of %s to guard for remaining branch %s.", negateGuardCondition, ifNode, survivingSuccessor);
                    FixedNode next = pred.next();
                    pred.setNext(guard);
                    guard.setNext(next);
                    SimplifierTool simplifierTool = GraphUtil.getDefaultSimplifier(null, null, null, false, graph.getAssumptions(), graph.getOptions(), loweringProvider);
                    survivingSuccessor.simplify(simplifierTool);
                    return;
                }
            } else if (current.predecessor() == null || current.predecessor() instanceof ControlSplitNode) {
                assert current.predecessor() != null || (current instanceof StartNode && current == ((AbstractBeginNode) current).graph().start());
                moveAsDeoptAfter((AbstractBeginNode) current, deopt);
                return;
            }
        }
        current = current.predecessor();
    }
}
Also used : FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) StartNode(org.graalvm.compiler.nodes.StartNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StartNode(org.graalvm.compiler.nodes.StartNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) StaticDeoptimizingNode(org.graalvm.compiler.nodes.StaticDeoptimizingNode) DeoptimizeNode(org.graalvm.compiler.nodes.DeoptimizeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) LoopExitNode(org.graalvm.compiler.nodes.LoopExitNode) Node(org.graalvm.compiler.graph.Node) EndNode(org.graalvm.compiler.nodes.EndNode) FixedWithNextNode(org.graalvm.compiler.nodes.FixedWithNextNode) ProxyNode(org.graalvm.compiler.nodes.ProxyNode) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) FixedNode(org.graalvm.compiler.nodes.FixedNode) IfNode(org.graalvm.compiler.nodes.IfNode) SimplifierTool(org.graalvm.compiler.graph.spi.SimplifierTool) AbstractBeginNode(org.graalvm.compiler.nodes.AbstractBeginNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) AbstractEndNode(org.graalvm.compiler.nodes.AbstractEndNode) LogicNode(org.graalvm.compiler.nodes.LogicNode) ControlSplitNode(org.graalvm.compiler.nodes.ControlSplitNode) DebugCloseable(org.graalvm.compiler.debug.DebugCloseable)

Aggregations

LoopExitNode (org.graalvm.compiler.nodes.LoopExitNode)25 LoopBeginNode (org.graalvm.compiler.nodes.LoopBeginNode)18 AbstractMergeNode (org.graalvm.compiler.nodes.AbstractMergeNode)17 FixedNode (org.graalvm.compiler.nodes.FixedNode)16 AbstractBeginNode (org.graalvm.compiler.nodes.AbstractBeginNode)14 Node (org.graalvm.compiler.graph.Node)13 EndNode (org.graalvm.compiler.nodes.EndNode)12 FixedWithNextNode (org.graalvm.compiler.nodes.FixedWithNextNode)10 LoopEndNode (org.graalvm.compiler.nodes.LoopEndNode)10 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)10 AbstractEndNode (org.graalvm.compiler.nodes.AbstractEndNode)9 PhiNode (org.graalvm.compiler.nodes.PhiNode)9 ProxyNode (org.graalvm.compiler.nodes.ProxyNode)9 ValueNode (org.graalvm.compiler.nodes.ValueNode)9 MergeNode (org.graalvm.compiler.nodes.MergeNode)8 ArrayList (java.util.ArrayList)6 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)6 ControlSplitNode (org.graalvm.compiler.nodes.ControlSplitNode)6 IfNode (org.graalvm.compiler.nodes.IfNode)6 FrameState (org.graalvm.compiler.nodes.FrameState)5