private static Block calcBlockForUsage( Node node, Node usage, Block startBlock, NodeMap<Block> currentNodeMap) { assert !(node instanceof PhiNode); Block currentBlock = startBlock; if (usage instanceof PhiNode) { // An input to a PhiNode is used at the end of the predecessor block that // corresponds to the PhiNode input. One PhiNode can use an input multiple times. PhiNode phi = (PhiNode) usage; AbstractMergeNode merge = phi.merge(); Block mergeBlock = currentNodeMap.get(merge); for (int i = 0; i < phi.valueCount(); ++i) { if (phi.valueAt(i) == node) { Block otherBlock = mergeBlock.getPredecessors()[i]; currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, otherBlock); } } } else if (usage instanceof AbstractBeginNode) { AbstractBeginNode abstractBeginNode = (AbstractBeginNode) usage; if (abstractBeginNode instanceof StartNode) { currentBlock = AbstractControlFlowGraph.commonDominatorTyped( currentBlock, currentNodeMap.get(abstractBeginNode)); } else { Block otherBlock = currentNodeMap.get(abstractBeginNode).getDominator(); currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, otherBlock); } } else { // All other types of usages: Put the input into the same block as the usage. Block otherBlock = currentNodeMap.get(usage); currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, otherBlock); } return currentBlock; }
private static void processStackPhi(NodeStack stack, PhiNode phiNode) { AbstractMergeNode merge = phiNode.merge(); for (int i = 0; i < merge.forwardEndCount(); ++i) { Node input = phiNode.valueAt(i); if (input != null) { stack.push(input); } } }
/** * 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() } } } }
public static void checkRedundantPhi(PhiNode phiNode) { if (phiNode.isDeleted() || phiNode.valueCount() == 1) { return; } ValueNode singleValue = phiNode.singleValue(); if (singleValue != null) { Collection<PhiNode> phiUsages = phiNode.usages().filter(PhiNode.class).snapshot(); Collection<ProxyNode> proxyUsages = phiNode.usages().filter(ProxyNode.class).snapshot(); phiNode.graph().replaceFloating(phiNode, singleValue); for (PhiNode phi : phiUsages) { checkRedundantPhi(phi); } for (ProxyNode proxy : proxyUsages) { checkRedundantProxy(proxy); } } }
private void scheduleEarliestIterative( BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph, boolean immutableGraph) { BitSet floatingReads = new BitSet(cfg.getBlocks().length); // Add begin nodes as the first entry and set the block for phi nodes. for (Block b : cfg.getBlocks()) { AbstractBeginNode beginNode = b.getBeginNode(); ArrayList<Node> nodes = new ArrayList<>(); nodeToBlock.set(beginNode, b); nodes.add(beginNode); blockToNodes.put(b, nodes); if (beginNode instanceof AbstractMergeNode) { AbstractMergeNode mergeNode = (AbstractMergeNode) beginNode; for (PhiNode phi : mergeNode.phis()) { nodeToBlock.set(phi, b); } } else if (beginNode instanceof LoopExitNode) { LoopExitNode loopExitNode = (LoopExitNode) beginNode; for (ProxyNode proxy : loopExitNode.proxies()) { nodeToBlock.set(proxy, b); } } } NodeStack stack = new NodeStack(); // Start analysis with control flow ends. Block[] reversePostOrder = cfg.reversePostOrder(); for (int j = reversePostOrder.length - 1; j >= 0; --j) { Block b = reversePostOrder[j]; FixedNode endNode = b.getEndNode(); if (isFixedEnd(endNode)) { stack.push(endNode); nodeToBlock.set(endNode, b); } } processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack); // Visit back input edges of loop phis. boolean changed; boolean unmarkedPhi; do { changed = false; unmarkedPhi = false; for (LoopBeginNode loopBegin : graph.getNodes(LoopBeginNode.TYPE)) { for (PhiNode phi : loopBegin.phis()) { if (visited.isMarked(phi)) { for (int i = 0; i < loopBegin.getLoopEndCount(); ++i) { Node node = phi.valueAt(i + loopBegin.forwardEndCount()); if (node != null && !visited.isMarked(node)) { changed = true; stack.push(node); processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack); } } } else { unmarkedPhi = true; } } } /* * the processing of one loop phi could have marked a previously checked loop phi, * therefore this needs to be iterative. */ } while (unmarkedPhi && changed); // Check for dead nodes. if (!immutableGraph && visited.getCounter() < graph.getNodeCount()) { for (Node n : graph.getNodes()) { if (!visited.isMarked(n)) { n.clearInputs(); n.markDeleted(); } } } // Add end nodes as the last nodes in each block. for (Block b : cfg.getBlocks()) { FixedNode endNode = b.getEndNode(); if (isFixedEnd(endNode)) { if (endNode != b.getBeginNode()) { addNode(blockToNodes, b, endNode); } } } if (!floatingReads.isEmpty()) { for (Block b : cfg.getBlocks()) { if (floatingReads.get(b.getId())) { resortEarliestWithinBlock(b, blockToNodes, nodeToBlock, visited); } } } assert MemoryScheduleVerification.check(cfg.getStartBlock(), blockToNodes); }