@SuppressWarnings("try") public void run( StructuredGraph graph, SchedulingStrategy selectedStrategy, boolean immutableGraph) { // assert GraphOrder.assertNonCyclicGraph(graph); cfg = ControlFlowGraph.compute(graph, true, true, true, false); NodeMap<Block> currentNodeMap = graph.createNodeMap(); NodeBitMap visited = graph.createNodeBitMap(); BlockMap<List<Node>> earliestBlockToNodesMap = new BlockMap<>(cfg); this.nodeToBlockMap = currentNodeMap; this.blockToNodesMap = earliestBlockToNodesMap; scheduleEarliestIterative( earliestBlockToNodesMap, currentNodeMap, visited, graph, immutableGraph); if (selectedStrategy != SchedulingStrategy.EARLIEST) { // For non-earliest schedules, we need to do a second pass. BlockMap<List<Node>> latestBlockToNodesMap = new BlockMap<>(cfg); for (Block b : cfg.getBlocks()) { latestBlockToNodesMap.put(b, new ArrayList<Node>()); } BlockMap<ArrayList<FloatingReadNode>> watchListMap = calcLatestBlocks( selectedStrategy, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap, immutableGraph); sortNodesLatestWithinBlock( cfg, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited); assert verifySchedule(cfg, latestBlockToNodesMap, currentNodeMap); assert MemoryScheduleVerification.check(cfg.getStartBlock(), latestBlockToNodesMap); this.blockToNodesMap = latestBlockToNodesMap; cfg.setNodeToBlock(currentNodeMap); } graph.setLastSchedule( new ScheduleResult(this.cfg, this.nodeToBlockMap, this.blockToNodesMap)); }
public LoopsData(final StructuredGraph graph) { cfg = Debug.scope( "ControlFlowGraph", new Callable<ControlFlowGraph>() { @Override public ControlFlowGraph call() throws Exception { return ControlFlowGraph.compute(graph, true, true, true, true); } }); for (Loop lirLoop : cfg.getLoops()) { LoopEx ex = new LoopEx(lirLoop, this); lirLoopToEx.put(lirLoop, ex); loopBeginToEx.put(ex.loopBegin(), ex); } }
private static void sortNodesLatestWithinBlock( ControlFlowGraph cfg, BlockMap<List<Node>> earliestBlockToNodesMap, BlockMap<List<Node>> latestBlockToNodesMap, NodeMap<Block> currentNodeMap, BlockMap<ArrayList<FloatingReadNode>> watchListMap, NodeBitMap visited) { for (Block b : cfg.getBlocks()) { sortNodesLatestWithinBlock( b, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited); } }
private static boolean verifySchedule( ControlFlowGraph cfg, BlockMap<List<Node>> blockToNodesMap, NodeMap<Block> nodeMap) { for (Block b : cfg.getBlocks()) { List<Node> nodes = blockToNodesMap.get(b); for (Node n : nodes) { assert n.isAlive(); assert nodeMap.get(n) == b; StructuredGraph g = (StructuredGraph) n.graph(); if (g.hasLoops() && g.getGuardsStage() == GuardsStage.AFTER_FSA && n instanceof DeoptimizeNode) { assert b.getLoopDepth() == 0 : n; } } } return true; }
private static void processStack( ControlFlowGraph cfg, BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, BitSet floatingReads, NodeStack stack) { Block startBlock = cfg.getStartBlock(); while (!stack.isEmpty()) { Node current = stack.peek(); if (visited.checkAndMarkInc(current)) { // Push inputs and predecessor. Node predecessor = current.predecessor(); if (predecessor != null) { stack.push(predecessor); } if (current instanceof PhiNode) { processStackPhi(stack, (PhiNode) current); } else if (current instanceof ProxyNode) { processStackProxy(stack, (ProxyNode) current); } else if (current instanceof FrameState) { processStackFrameState(stack, current); } else { current.pushInputs(stack); } } else { stack.pop(); if (nodeToBlock.get(current) == null) { Block curBlock = cfg.blockFor(current); if (curBlock == null) { assert current.predecessor() == null && !(current instanceof FixedNode) : "The assignment of blocks to fixed nodes is already done when constructing the cfg."; Block earliest = startBlock; for (Node input : current.inputs()) { Block inputEarliest = nodeToBlock.get(input); if (inputEarliest == null) { assert current instanceof FrameState && input instanceof StateSplit && ((StateSplit) input).stateAfter() == current : current; } else { assert inputEarliest != null; if (inputEarliest.getEndNode() == input) { // This is the last node of the block. if (current instanceof FrameState && input instanceof StateSplit && ((StateSplit) input).stateAfter() == current) { // Keep regular inputEarliest. } else if (input instanceof ControlSplitNode) { inputEarliest = nodeToBlock.get(((ControlSplitNode) input).getPrimarySuccessor()); } else { assert inputEarliest.getSuccessorCount() == 1; assert !(input instanceof AbstractEndNode); // Keep regular inputEarliest } } if (earliest.getDominatorDepth() < inputEarliest.getDominatorDepth()) { earliest = inputEarliest; } } } curBlock = earliest; } assert curBlock != null; addNode(blockToNodes, curBlock, current); nodeToBlock.set(current, curBlock); if (current instanceof FloatingReadNode) { FloatingReadNode floatingReadNode = (FloatingReadNode) current; if (curBlock.canKill(floatingReadNode.getLocationIdentity())) { floatingReads.set(curBlock.getId()); } } } } } }
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); }
@SuppressFBWarnings( value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE", justification = "false positive found by findbugs") private BlockMap<ArrayList<FloatingReadNode>> calcLatestBlocks( SchedulingStrategy strategy, NodeMap<Block> currentNodeMap, BlockMap<List<Node>> earliestBlockToNodesMap, NodeBitMap visited, BlockMap<List<Node>> latestBlockToNodesMap, boolean immutableGraph) { BlockMap<ArrayList<FloatingReadNode>> watchListMap = new BlockMap<>(cfg); Block[] reversePostOrder = cfg.reversePostOrder(); for (int j = reversePostOrder.length - 1; j >= 0; --j) { Block currentBlock = reversePostOrder[j]; List<Node> blockToNodes = earliestBlockToNodesMap.get(currentBlock); LocationSet killed = null; int previousIndex = blockToNodes.size(); for (int i = blockToNodes.size() - 1; i >= 0; --i) { Node currentNode = blockToNodes.get(i); assert currentNodeMap.get(currentNode) == currentBlock; assert !(currentNode instanceof PhiNode) && !(currentNode instanceof ProxyNode); assert visited.isMarked(currentNode); if (currentNode instanceof FixedNode) { // For these nodes, the earliest is at the same time the latest block. } else { Block latestBlock = null; LocationIdentity constrainingLocation = null; if (currentNode instanceof FloatingReadNode) { // We are scheduling a floating read node => check memory // anti-dependencies. FloatingReadNode floatingReadNode = (FloatingReadNode) currentNode; LocationIdentity location = floatingReadNode.getLocationIdentity(); if (location.isMutable()) { // Location can be killed. constrainingLocation = location; if (currentBlock.canKill(location)) { if (killed == null) { killed = new LocationSet(); } fillKillSet(killed, blockToNodes.subList(i + 1, previousIndex)); previousIndex = i; if (killed.contains(location)) { // Earliest block kills location => we need to stay within // earliest block. latestBlock = currentBlock; } } } } if (latestBlock == null) { // We are not constraint within earliest block => calculate optimized // schedule. calcLatestBlock( currentBlock, strategy, currentNode, currentNodeMap, constrainingLocation, watchListMap, latestBlockToNodesMap, visited, immutableGraph); } else { selectLatestBlock( currentNode, currentBlock, latestBlock, currentNodeMap, watchListMap, constrainingLocation, latestBlockToNodesMap); } } } } return watchListMap; }
@Test public void testImplies() { StructuredGraph graph = new StructuredGraph(AllowAssumptions.YES); EndNode trueEnd = graph.add(new EndNode()); EndNode falseEnd = graph.add(new EndNode()); AbstractBeginNode trueBegin = graph.add(new BeginNode()); trueBegin.setNext(trueEnd); AbstractBeginNode falseBegin = graph.add(new BeginNode()); falseBegin.setNext(falseEnd); IfNode ifNode = graph.add(new IfNode(null, trueBegin, falseBegin, 0.5)); graph.start().setNext(ifNode); AbstractMergeNode merge = graph.add(new MergeNode()); merge.addForwardEnd(trueEnd); merge.addForwardEnd(falseEnd); ReturnNode returnNode = graph.add(new ReturnNode(null)); merge.setNext(returnNode); dumpGraph(graph); ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true); List<Block> blocks = cfg.getBlocks(); // check number of blocks assertDeepEquals(4, blocks.size()); // check block - node assignment assertDeepEquals(blocks.get(0), cfg.blockFor(graph.start())); assertDeepEquals(blocks.get(0), cfg.blockFor(ifNode)); assertDeepEquals(blocks.get(1), cfg.blockFor(trueBegin)); assertDeepEquals(blocks.get(1), cfg.blockFor(trueEnd)); assertDeepEquals(blocks.get(2), cfg.blockFor(falseBegin)); assertDeepEquals(blocks.get(2), cfg.blockFor(falseEnd)); assertDeepEquals(blocks.get(3), cfg.blockFor(merge)); assertDeepEquals(blocks.get(3), cfg.blockFor(returnNode)); // check postOrder Iterator<Block> it = cfg.postOrder().iterator(); for (int i = blocks.size() - 1; i >= 0; i--) { assertTrue(it.hasNext()); Block b = it.next(); assertDeepEquals(blocks.get(i), b); } // check dominators assertDominator(blocks.get(0), null); assertDominator(blocks.get(1), blocks.get(0)); assertDominator(blocks.get(2), blocks.get(0)); assertDominator(blocks.get(3), blocks.get(0)); // check dominated assertDominatedSize(blocks.get(0), 3); assertDominatedSize(blocks.get(1), 0); assertDominatedSize(blocks.get(2), 0); assertDominatedSize(blocks.get(3), 0); // check postdominators assertPostdominator(blocks.get(0), blocks.get(3)); assertPostdominator(blocks.get(1), blocks.get(3)); assertPostdominator(blocks.get(2), blocks.get(3)); assertPostdominator(blocks.get(3), null); }