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);
}
}
}
}
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;
}
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();
}
}
}
}
}
}
}
}
}
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;
}
}
}
}
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();
}
}
Aggregations