changeset 19897:0b5036d27c02

Fix for earliest possible schedule when the last node in a block is an invoke. Added a new scheduling test.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Tue, 17 Mar 2015 13:13:57 +0100
parents 6dcbb4e05ce9
children 749b96e8ff90
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest2.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java
diffstat 2 files changed, 129 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest2.java	Tue Mar 17 13:13:57 2015 +0100
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import java.util.*;
+
+import org.junit.*;
+
+import com.oracle.graal.compiler.common.cfg.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.DeoptimizingNode.DeoptDuring;
+import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.calc.*;
+import com.oracle.graal.nodes.cfg.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.phases.*;
+import com.oracle.graal.phases.common.*;
+import com.oracle.graal.phases.schedule.*;
+import com.oracle.graal.phases.schedule.SchedulePhase.SchedulingStrategy;
+import com.oracle.graal.phases.tiers.*;
+
+public class SchedulingTest2 extends GraphScheduleTest {
+
+    public static int testSnippet() {
+        return test() + 2;
+    }
+
+    public static int test() {
+        return 40;
+    }
+
+    @Test
+    public void testValueProxyInputs() {
+        StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES);
+        ReturnNode returnNode = graph.getNodes(ReturnNode.TYPE).first();
+        BeginNode beginNode = graph.add(new BeginNode());
+        returnNode.replaceAtPredecessor(beginNode);
+        beginNode.setNext(returnNode);
+        Debug.dump(graph, "Graph");
+        SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST);
+        schedule.apply(graph);
+        BlockMap<List<Node>> blockToNodesMap = schedule.getBlockToNodesMap();
+        NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
+        assertDeepEquals(2, schedule.getCFG().getBlocks().size());
+        for (BinaryArithmeticNode<?> node : graph.getNodes().filter(BinaryArithmeticNode.class)) {
+            if (node instanceof AddNode) {
+                assertTrue(node.toString() + " expected: " + nodeToBlock.get(beginNode) + " but was: " + nodeToBlock.get(node), nodeToBlock.get(node) == nodeToBlock.get(beginNode));
+            }
+        }
+
+        for (FrameState fs : graph.getNodes(FrameState.TYPE)) {
+            Block block = nodeToBlock.get(fs);
+            assertTrue(fs.toString(), block == schedule.getCFG().getStartBlock());
+            for (Node usage : fs.usages()) {
+                if (usage instanceof StateSplit && ((StateSplit) usage).stateAfter() == fs) {
+                    assertTrue(usage.toString(), nodeToBlock.get(usage) == block);
+                    if (usage != block.getBeginNode()) {
+                        List<Node> map = blockToNodesMap.get(block);
+                        assertTrue(map.indexOf(fs) + " < " + map.indexOf(usage), map.indexOf(fs) < map.indexOf(usage));
+                    }
+                }
+            }
+        }
+
+        PhaseContext context = new PhaseContext(getProviders());
+        new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+        new LoweringPhase(new CanonicalizerPhase(), LoweringTool.StandardLoweringStage.MID_TIER).apply(graph, context);
+        MidTierContext midContext = new MidTierContext(getProviders(), getCodeCache().getTarget(), OptimisticOptimizations.ALL, graph.method().getProfilingInfo(), null);
+
+        new GuardLoweringPhase().apply(graph, midContext);
+        FrameStateAssignmentPhase phase = new FrameStateAssignmentPhase();
+        phase.apply(graph);
+
+        schedule = new SchedulePhase(SchedulingStrategy.EARLIEST);
+        schedule.apply(graph);
+        blockToNodesMap = schedule.getBlockToNodesMap();
+        nodeToBlock = schedule.getNodeToBlockMap();
+        for (FrameState fs : graph.getNodes(FrameState.TYPE)) {
+            Block block = nodeToBlock.get(fs);
+            assertTrue(fs.toString(), block == schedule.getCFG().getStartBlock());
+            for (Node usage : fs.usages()) {
+                if ((usage instanceof StateSplit && ((StateSplit) usage).stateAfter() == fs) || (usage instanceof DeoptDuring && ((DeoptDuring) usage).stateDuring() == fs)) {
+                    assertTrue(usage.toString(), nodeToBlock.get(usage) == block);
+                    if (usage != block.getBeginNode()) {
+                        List<Node> map = blockToNodesMap.get(block);
+                        assertTrue(map.indexOf(fs) + " < " + map.indexOf(usage), map.indexOf(fs) < map.indexOf(usage));
+                    }
+                }
+            }
+        }
+    }
+}
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Mar 16 21:50:15 2015 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Tue Mar 17 13:13:57 2015 +0100
@@ -165,7 +165,7 @@
                                     // We are not constraint within currentBlock. Check if
                                     // we are contraint while walking down the dominator
                                     // line.
-                                    Block newLatestBlock = adjustLatestForRead(currentBlock, latestBlock, location);
+                                    Block newLatestBlock = adjustLatestForRead(floatingReadNode, currentBlock, latestBlock, location);
                                     assert dominates(newLatestBlock, latestBlock);
                                     assert dominates(currentBlock, newLatestBlock);
                                     latestBlock = newLatestBlock;
@@ -203,7 +203,7 @@
         return true;
     }
 
-    private static Block adjustLatestForRead(Block earliestBlock, Block latestBlock, LocationIdentity location) {
+    private static Block adjustLatestForRead(FloatingReadNode floatingReadNode, Block earliestBlock, Block latestBlock, LocationIdentity location) {
         assert strictlyDominates(earliestBlock, latestBlock);
         Block current = latestBlock.getDominator();
 
@@ -218,6 +218,7 @@
             }
             dominatorChain.add(current);
             current = current.getDominator();
+            assert current != null : floatingReadNode;
         }
 
         // The first element of dominatorChain now contains the latest possible block.
@@ -650,16 +651,22 @@
                         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;
-                            if (input instanceof ControlSplitNode) {
-                                inputEarliest = nodeToBlock.get(((ControlSplitNode) input).getPrimarySuccessor());
-                            } else {
-                                inputEarliest = nodeToBlock.get(input);
-                            }
+                            Block inputEarliest = nodeToBlock.get(input);
                             if (inputEarliest == null) {
                                 assert current instanceof FrameState && input instanceof StateSplit && ((StateSplit) input).stateAfter() == 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;
+                                        inputEarliest = inputEarliest.getSuccessors().get(0);
+                                    }
+                                }
                                 if (earliest.getDominatorDepth() < inputEarliest.getDominatorDepth()) {
                                     earliest = inputEarliest;
                                 }