changeset 22839:e5879d8381dd

Bugfix: when scheduler is not allowed to delete dead nodes, it must ignore them
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 15 Oct 2015 11:29:54 -0700
parents b2438b37ab3c
children 63a6c6173649
files graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java
diffstat 1 files changed, 25 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu Oct 15 11:29:00 2015 -0700
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Thu Oct 15 11:29:54 2015 -0700
@@ -158,7 +158,7 @@
                 this.nodeToBlockMap = graph.createNodeMap();
                 this.blockToNodesMap = new BlockMap<>(cfg);
                 NodeBitMap visited = graph.createNodeBitMap();
-                scheduleEarliestIterative(blockToNodesMap, nodeToBlockMap, visited, graph);
+                scheduleEarliestIterative(blockToNodesMap, nodeToBlockMap, visited, graph, null);
                 return;
             } else {
                 boolean isOutOfLoops = selectedStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS;
@@ -166,19 +166,20 @@
                     NodeMap<Block> currentNodeMap = graph.createNodeMap();
                     BlockMap<List<Node>> earliestBlockToNodesMap = new BlockMap<>(cfg);
                     NodeBitMap visited = graph.createNodeBitMap();
+                    NodeBitMap unreachableNodes = immutableGraph ? graph.createNodeBitMap() : null;
 
                     // Assign early so we are getting a context in case of an exception.
                     this.blockToNodesMap = earliestBlockToNodesMap;
                     this.nodeToBlockMap = currentNodeMap;
 
-                    scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph);
+                    scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, unreachableNodes);
                     BlockMap<List<Node>> latestBlockToNodesMap = new BlockMap<>(cfg);
 
                     for (Block b : cfg.getBlocks()) {
                         latestBlockToNodesMap.put(b, new ArrayList<Node>());
                     }
 
-                    BlockMap<ArrayList<FloatingReadNode>> watchListMap = calcLatestBlocks(isOutOfLoops, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap);
+                    BlockMap<ArrayList<FloatingReadNode>> watchListMap = calcLatestBlocks(isOutOfLoops, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap, unreachableNodes);
                     sortNodesLatestWithinBlock(cfg, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited);
 
                     assert verifySchedule(cfg, latestBlockToNodesMap, currentNodeMap);
@@ -195,7 +196,7 @@
 
     @SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE", justification = "false positive found by findbugs")
     private BlockMap<ArrayList<FloatingReadNode>> calcLatestBlocks(boolean isOutOfLoops, NodeMap<Block> currentNodeMap, BlockMap<List<Node>> earliestBlockToNodesMap, NodeBitMap visited,
-                    BlockMap<List<Node>> latestBlockToNodesMap) {
+                    BlockMap<List<Node>> latestBlockToNodesMap, NodeBitMap unreachableNodes) {
         BlockMap<ArrayList<FloatingReadNode>> watchListMap = null;
         for (Block b : cfg.postOrder()) {
             List<Node> blockToNodes = earliestBlockToNodesMap.get(b);
@@ -212,7 +213,7 @@
                     Block currentBlock = b;
                     assert currentBlock != null;
 
-                    Block latestBlock = calcLatestBlock(b, isOutOfLoops, currentNode, currentNodeMap);
+                    Block latestBlock = calcLatestBlock(b, isOutOfLoops, currentNode, currentNodeMap, unreachableNodes);
                     assert checkLatestEarliestRelation(currentNode, currentBlock, latestBlock);
                     if (latestBlock != currentBlock) {
                         if (currentNode instanceof FloatingReadNode) {
@@ -480,10 +481,19 @@
 
     }
 
-    private static Block calcLatestBlock(Block earliestBlock, boolean scheduleOutOfLoops, Node currentNode, NodeMap<Block> currentNodeMap) {
+    private Block calcLatestBlock(Block earliestBlock, boolean scheduleOutOfLoops, Node currentNode, NodeMap<Block> currentNodeMap, NodeBitMap unreachableNodes) {
         Block block = null;
         assert currentNode.hasUsages();
         for (Node usage : currentNode.usages()) {
+            if (unreachableNodes != null && unreachableNodes.contains(usage)) {
+                /*
+                 * Normally, dead nodes are deleted by the scheduler before we reach this point.
+                 * Only when the scheduler is asked to not modify a graph, we can see dead nodes
+                 * here.
+                 */
+                assert immutableGraph;
+                continue;
+            }
             block = calcBlockForUsage(currentNode, usage, block, currentNodeMap);
             assert checkLatestEarliestRelation(currentNode, earliestBlock, block);
             if (scheduleOutOfLoops) {
@@ -525,7 +535,7 @@
         return currentBlock;
     }
 
-    private void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph) {
+    private void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph, NodeBitMap unreachableNodes) {
 
         BitSet floatingReads = new BitSet(cfg.getBlocks().size());
 
@@ -593,11 +603,16 @@
         } while (unmarkedPhi && changed);
 
         // Check for dead nodes.
-        if (!immutableGraph && visited.getCounter() < graph.getNodeCount()) {
+        if (visited.getCounter() < graph.getNodeCount()) {
             for (Node n : graph.getNodes()) {
                 if (!visited.isMarked(n)) {
-                    n.clearInputs();
-                    n.markDeleted();
+                    if (!immutableGraph) {
+                        n.clearInputs();
+                        n.markDeleted();
+                    } else if (unreachableNodes != null) {
+                        /* We are not allowed to modify the graph, so remember that node is dead. */
+                        unreachableNodes.mark(n);
+                    }
                 }
             }
         }