private static void killEnd(AbstractEndNode end) { MergeNode merge = end.merge(); if (merge != null) { merge.removeEnd(end); StructuredGraph graph = end.graph(); if (merge instanceof LoopBeginNode && merge.forwardEndCount() == 0) { // dead loop for (PhiNode phi : merge.phis().snapshot()) { propagateKill(phi); } LoopBeginNode begin = (LoopBeginNode) merge; // disconnect and delete loop ends & loop exits for (LoopEndNode loopend : begin.loopEnds().snapshot()) { loopend.predecessor().replaceFirstSuccessor(loopend, null); loopend.safeDelete(); } begin.removeExits(); FixedNode loopBody = begin.next(); if (loopBody != null) { // for small infinite loops, the body may be killed while // killing the loop ends killCFG(loopBody); } begin.safeDelete(); } else if (merge instanceof LoopBeginNode && ((LoopBeginNode) merge).loopEnds().isEmpty()) { // not // a // loop // anymore graph.reduceDegenerateLoopBegin((LoopBeginNode) merge); } else if (merge.phiPredecessorCount() == 1) { // not a merge anymore graph.reduceTrivialMerge(merge); } } }
public void reduceTrivialMerge(AbstractMergeNode merge) { assert merge.forwardEndCount() == 1; assert !(merge instanceof LoopBeginNode) || ((LoopBeginNode) merge).loopEnds().isEmpty(); for (PhiNode phi : merge.phis().snapshot()) { assert phi.valueCount() == 1; ValueNode singleValue = phi.valueAt(0); phi.replaceAtUsagesAndDelete(singleValue); } // remove loop exits if (merge instanceof LoopBeginNode) { ((LoopBeginNode) merge).removeExits(); } AbstractEndNode singleEnd = merge.forwardEndAt(0); FixedNode sux = merge.next(); FrameState stateAfter = merge.stateAfter(); // evacuateGuards merge.prepareDelete((FixedNode) singleEnd.predecessor()); merge.safeDelete(); if (stateAfter != null && stateAfter.isAlive() && stateAfter.hasNoUsages()) { GraphUtil.killWithUnusedFloatingInputs(stateAfter); } if (sux == null) { singleEnd.replaceAtPredecessor(null); singleEnd.safeDelete(); } else { singleEnd.replaceAndDelete(sux); } }
private static void iterateSuccessorsAndInputs(NodeFlood flood) { BiConsumer<Node, Node> consumer = (n, succOrInput) -> { assert succOrInput.isAlive() : "dead successor or input " + succOrInput + " in " + n; flood.add(succOrInput); }; for (Node current : flood) { if (current instanceof AbstractEndNode) { AbstractEndNode end = (AbstractEndNode) current; flood.add(end.merge()); } else { current.acceptSuccessors(consumer); current.acceptInputs(consumer); } } }
private void processFixedGuardAndMerge( FixedGuardNode fixedGuard, PhaseContext context, CompareNode compare, ValueNode x, ValuePhiNode xPhi, ValueNode y, ValuePhiNode yPhi, AbstractMergeNode merge) { List<EndNode> mergePredecessors = merge.cfgPredecessors().snapshot(); for (int i = 0; i < mergePredecessors.size(); ++i) { AbstractEndNode mergePredecessor = mergePredecessors.get(i); if (!mergePredecessor.isAlive()) { break; } Constant xs; if (xPhi == null) { xs = x.asConstant(); } else { xs = xPhi.valueAt(mergePredecessor).asConstant(); } Constant ys; if (yPhi == null) { ys = y.asConstant(); } else { ys = yPhi.valueAt(mergePredecessor).asConstant(); } if (xs != null && ys != null && compare .condition() .foldCondition(xs, ys, context.getConstantReflection(), compare.unorderedIsTrue()) == fixedGuard.isNegated()) { visitDeoptBegin( AbstractBeginNode.prevBegin(mergePredecessor), fixedGuard.getAction(), fixedGuard.getReason(), fixedGuard.getSpeculation(), fixedGuard.graph()); } } }
/** * The {@link com.oracle.graal.nodes.AbstractEndNode} at the end of the current code path * contributes values to {@link com.oracle.graal.nodes.PhiNode}s. Now is a good time to {@link * EquationalReasoner#deverbosify(com.oracle.graal.graph.Node) EquationalReasoner#deverbosify} * those values. * * <p>Precondition: inputs haven't been deverbosified yet. */ private void visitAbstractEndNode(AbstractEndNode endNode) { MergeNode merge = endNode.merge(); for (PhiNode phi : merge.phis()) { if (phi instanceof ValuePhiNode && phi.getKind() == Kind.Object) { assert phi.verify(); int index = merge.phiPredecessorIndex(endNode); ValueNode original = phi.valueAt(index); ValueNode reduced = (ValueNode) reasoner.deverbosify(original); if (reduced != original) { phi.setValueAt(index, reduced); // `original` if unused will be removed in finished() } } } }