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); } } }
private void visitForward(NodeBitMap visited, Node node) { if (node != null && !visited.isMarked(node)) { visited.mark(node); if (node.predecessor() != null) { visitForward(visited, node.predecessor()); } if (node instanceof MergeNode) { // make sure that the cfg predecessors of a MergeNode are processed first MergeNode merge = (MergeNode) node; for (int i = 0; i < merge.forwardEndCount(); i++) { visitForward(visited, merge.forwardEndAt(i)); } } for (Node input : node.inputs()) { visitForward(visited, input); } if (node instanceof LoopBeginNode) { LoopBeginNode loopBegin = (LoopBeginNode) node; for (LoopEndNode loopEnd : loopBegin.loopEnds()) { visitForward(visited, loopEnd); } } nodes.add(node); } }
/** * 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() } } } }
private Collection<Edge> handleEdge( Edge nextEdge, Map<Integer, MergeNode> mergeNodes, Set<ARGState> elementsOnPath, EdgeVisitor callback) { ARGState childElement = nextEdge.getChildState(); CFAEdge edge = nextEdge.getEdge(); Stack<FunctionBody> functionStack = nextEdge.getStack(); // clone stack to have a different representation of the function calls and conditions // for every element functionStack = cloneStack(functionStack); // we do not have a single edge, instead a dynamic multi-edge if (edge == null) { List<CFAEdge> edges = nextEdge.getParentState().getEdgesToChild(childElement); for (CFAEdge inner : edges) { callback.visit(childElement, inner, functionStack); } } else { callback.visit(childElement, edge, functionStack); } // how many parents does the child have? // ignore parents not on the error path int noOfParents = from(childElement.getParents()).filter(in(elementsOnPath)).size(); assert noOfParents >= 1; // handle merging if necessary if (noOfParents > 1) { assert !((edge instanceof CFunctionCallEdge) || (childElement.isTarget())); // this is the end of a condition, determine whether we should continue or backtrack int elemId = childElement.getStateId(); FunctionBody currentFunction = functionStack.peek(); currentFunction.write("goto label_" + elemId + ";"); // get the merge node for that node MergeNode mergeNode = mergeNodes.get(elemId); // if null create new and put in the map if (mergeNode == null) { mergeNode = new MergeNode(elemId); mergeNodes.put(elemId, mergeNode); } // this tells us the number of edges (entering that node) processed so far int noOfProcessedBranches = mergeNode.addBranch(currentFunction); // if all edges are processed if (noOfParents == noOfProcessedBranches) { // all branches are processed, now decide which nodes to remove from the stack List<FunctionBody> incomingStacks = mergeNode.getIncomingStates(); FunctionBody newFunction = processIncomingStacks(incomingStacks); // replace the current function body with the right one functionStack.pop(); functionStack.push(newFunction); newFunction.write("label_" + elemId + ": ;"); } else { return Collections.emptySet(); } } return getRelevantChildrenOfState(childElement, functionStack, elementsOnPath); }