changeset 23250:e67189aa2e06

Refactor scheduling phase to be without state and produce a ScheduleResult that is stored in the graph.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Mon, 04 Jan 2016 00:48:58 +0100
parents 1efad828d77f
children e34b2e8f3471
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphScheduleTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest2.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/LIRGenerationPhase.java graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java graal/com.oracle.graal.salver/src/com/oracle/graal/salver/dumper/GraphDumper.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java
diffstat 32 files changed, 885 insertions(+), 834 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraalCompilerTest.java	Mon Jan 04 00:48:58 2016 +0100
@@ -91,6 +91,7 @@
 import com.oracle.graal.nodes.ReturnNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.graphbuilderconf.GraphBuilderConfiguration;
@@ -348,6 +349,7 @@
     protected static String getCanonicalGraphString(StructuredGraph graph, boolean excludeVirtual, boolean checkConstants) {
         SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST);
         schedule.apply(graph);
+        ScheduleResult scheduleResult = graph.getLastSchedule();
 
         NodeMap<Integer> canonicalId = graph.createNodeMap();
         int nextId = 0;
@@ -355,9 +357,9 @@
         List<String> constantsLines = new ArrayList<>();
 
         StringBuilder result = new StringBuilder();
-        for (Block block : schedule.getCFG().getBlocks()) {
+        for (Block block : scheduleResult.getCFG().getBlocks()) {
             result.append("Block " + block + " ");
-            if (block == schedule.getCFG().getStartBlock()) {
+            if (block == scheduleResult.getCFG().getStartBlock()) {
                 result.append("* ");
             }
             result.append("-> ");
@@ -365,7 +367,7 @@
                 result.append(succ + " ");
             }
             result.append("\n");
-            for (Node node : schedule.getBlockToNodesMap().get(block)) {
+            for (Node node : scheduleResult.getBlockToNodesMap().get(block)) {
                 if (node instanceof ValueNode && node.isAlive()) {
                     if (!excludeVirtual || !(node instanceof VirtualObjectNode || node instanceof ProxyNode || node instanceof InfopointNode)) {
                         if (node instanceof ConstantNode) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphScheduleTest.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/GraphScheduleTest.java	Mon Jan 04 00:48:58 2016 +0100
@@ -29,6 +29,7 @@
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.NodeMap;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.phases.schedule.SchedulePhase;
 
@@ -37,10 +38,10 @@
     protected void assertOrderedAfterSchedule(StructuredGraph graph, Node a, Node b) {
         SchedulePhase ibp = new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST);
         ibp.apply(graph);
-        assertOrderedAfterSchedule(ibp, a, b);
+        assertOrderedAfterSchedule(graph.getLastSchedule(), a, b);
     }
 
-    protected void assertOrderedAfterSchedule(SchedulePhase ibp, Node a, Node b) {
+    protected void assertOrderedAfterSchedule(ScheduleResult ibp, Node a, Node b) {
         NodeMap<Block> nodeToBlock = ibp.getCFG().getNodeToBlock();
         Block bBlock = nodeToBlock.get(b);
         Block aBlock = nodeToBlock.get(a);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MemoryScheduleTest.java	Mon Jan 04 00:48:58 2016 +0100
@@ -43,6 +43,7 @@
 import com.oracle.graal.nodes.StartNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.memory.FloatingReadNode;
 import com.oracle.graal.nodes.memory.WriteNode;
@@ -103,7 +104,7 @@
     @Test
     public void testSimple() {
         for (TestMode mode : TestMode.values()) {
-            SchedulePhase schedule = getFinalSchedule("testSimpleSnippet", mode);
+            ScheduleResult schedule = getFinalSchedule("testSimpleSnippet", mode);
             StructuredGraph graph = schedule.getCFG().graph;
             assertReadAndWriteInSameBlock(schedule, true);
             assertOrderedAfterSchedule(schedule, graph.getNodes().filter(FloatingReadNode.class).first(), graph.getNodes().filter(WriteNode.class).first());
@@ -128,7 +129,7 @@
     @Test
     public void testSplit1() {
         for (TestMode mode : TestMode.values()) {
-            SchedulePhase schedule = getFinalSchedule("testSplit1Snippet", mode);
+            ScheduleResult schedule = getFinalSchedule("testSplit1Snippet", mode);
             assertReadWithinStartBlock(schedule, true);
             assertReadWithinAllReturnBlocks(schedule, false);
         }
@@ -152,7 +153,7 @@
 
     @Test
     public void testSplit2() {
-        SchedulePhase schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testSplit2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, true);
     }
@@ -176,7 +177,7 @@
 
     @Test
     public void testLoop1() {
-        SchedulePhase schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop1Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(6, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, true);
         assertReadWithinAllReturnBlocks(schedule, false);
@@ -201,7 +202,7 @@
 
     @Test
     public void testLoop2() {
-        SchedulePhase schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(6, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, true);
@@ -223,7 +224,7 @@
 
     @Test
     public void testLoop3() {
-        SchedulePhase schedule = getFinalSchedule("testLoop3Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop3Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(6, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, true);
         assertReadWithinAllReturnBlocks(schedule, false);
@@ -259,7 +260,7 @@
 
     @Test
     public void testLoop5() {
-        SchedulePhase schedule = getFinalSchedule("testLoop5Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop5Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(10, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
@@ -288,7 +289,7 @@
 
     @Test
     public void testLoop6() {
-        SchedulePhase schedule = getFinalSchedule("testLoop6Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop6Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(13, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
@@ -321,7 +322,7 @@
 
     @Test
     public void testLoop7() {
-        SchedulePhase schedule = getFinalSchedule("testLoop7Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop7Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(18, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
@@ -348,7 +349,7 @@
 
     @Test
     public void testLoop8() {
-        SchedulePhase schedule = getFinalSchedule("testLoop8Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop8Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(10, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, true);
         assertReadWithinAllReturnBlocks(schedule, false);
@@ -368,7 +369,7 @@
 
     @Test
     public void testLoop9() {
-        SchedulePhase schedule = getFinalSchedule("testLoop9Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop9Snippet", TestMode.WITHOUT_FRAMESTATES);
         StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph();
         assertThat(graph.getNodes(ReturnNode.TYPE), hasCount(1));
         ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first();
@@ -387,7 +388,7 @@
 
     @Test
     public void testArrayCopy() {
-        SchedulePhase schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testArrayCopySnippet", TestMode.INLINED_WITHOUT_FRAMESTATES);
         StructuredGraph graph = schedule.getCFG().getStartBlock().getBeginNode().graph();
         assertDeepEquals(1, graph.getNodes(ReturnNode.TYPE).count());
         ReturnNode ret = graph.getNodes(ReturnNode.TYPE).first();
@@ -409,7 +410,7 @@
 
     @Test
     public void testIfRead1() {
-        SchedulePhase schedule = getFinalSchedule("testIfRead1Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testIfRead1Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(3, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, true);
         assertReadAndWriteInSameBlock(schedule, false);
@@ -430,7 +431,7 @@
 
     @Test
     public void testIfRead2() {
-        SchedulePhase schedule = getFinalSchedule("testIfRead2Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testIfRead2Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(3, schedule.getCFG().getBlocks().size());
         assertDeepEquals(1, schedule.getCFG().graph.getNodes().filter(FloatingReadNode.class).count());
         assertReadWithinStartBlock(schedule, false);
@@ -452,7 +453,7 @@
 
     @Test
     public void testIfRead3() {
-        SchedulePhase schedule = getFinalSchedule("testIfRead3Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testIfRead3Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(4, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, true);
@@ -473,7 +474,7 @@
 
     @Test
     public void testIfRead4() {
-        SchedulePhase schedule = getFinalSchedule("testIfRead4Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testIfRead4Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(3, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
@@ -492,7 +493,7 @@
 
     @Test
     public void testIfRead5() {
-        SchedulePhase schedule = getFinalSchedule("testIfRead5Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testIfRead5Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(4, schedule.getCFG().getBlocks().size());
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, true);
@@ -518,7 +519,7 @@
 
     @Test
     public void testAntiDependency() {
-        SchedulePhase schedule = getFinalSchedule("testAntiDependencySnippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testAntiDependencySnippet", TestMode.WITHOUT_FRAMESTATES);
         assertDeepEquals(4, schedule.getCFG().getBlocks().size());
         assertReadBeforeAllWritesInStartBlock(schedule);
     }
@@ -542,7 +543,7 @@
 
     @Test
     public void testBlockSchedule() {
-        SchedulePhase schedule = getFinalSchedule("testBlockScheduleSnippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testBlockScheduleSnippet", TestMode.WITHOUT_FRAMESTATES);
         StructuredGraph graph = schedule.getCFG().graph;
         NodeIterable<WriteNode> writeNodes = graph.getNodes().filter(WriteNode.class);
 
@@ -583,7 +584,7 @@
 
     @Test
     public void testBlockSchedule2() {
-        SchedulePhase schedule = getFinalSchedule("testBlockSchedule2Snippet", TestMode.WITHOUT_FRAMESTATES, SchedulingStrategy.LATEST);
+        ScheduleResult schedule = getFinalSchedule("testBlockSchedule2Snippet", TestMode.WITHOUT_FRAMESTATES, SchedulingStrategy.LATEST);
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
         assertReadAndWriteInSameBlock(schedule, false);
@@ -606,7 +607,7 @@
 
     @Test
     public void testProxy() {
-        SchedulePhase schedule = getFinalSchedule("testProxySnippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testProxySnippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
     }
@@ -629,7 +630,7 @@
 
     @Test
     public void testStringHashCode() {
-        SchedulePhase schedule = getFinalSchedule("testStringHashCodeSnippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testStringHashCodeSnippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, true);
         assertReadWithinAllReturnBlocks(schedule, false);
 
@@ -661,12 +662,12 @@
 
     @Test
     public void testLoop4() {
-        SchedulePhase schedule = getFinalSchedule("testLoop4Snippet", TestMode.WITHOUT_FRAMESTATES);
+        ScheduleResult schedule = getFinalSchedule("testLoop4Snippet", TestMode.WITHOUT_FRAMESTATES);
         assertReadWithinStartBlock(schedule, false);
         assertReadWithinAllReturnBlocks(schedule, false);
     }
 
-    private void assertReadWithinAllReturnBlocks(SchedulePhase schedule, boolean withinReturnBlock) {
+    private void assertReadWithinAllReturnBlocks(ScheduleResult schedule, boolean withinReturnBlock) {
         StructuredGraph graph = schedule.getCFG().graph;
         assertTrue(graph.getNodes(ReturnNode.TYPE).isNotEmpty());
 
@@ -685,7 +686,7 @@
         assertDeepEquals(withRead == returnBlocks, withinReturnBlock);
     }
 
-    private void assertReadWithinStartBlock(SchedulePhase schedule, boolean withinStartBlock) {
+    private void assertReadWithinStartBlock(ScheduleResult schedule, boolean withinStartBlock) {
         boolean readEncountered = false;
         for (Node node : schedule.getBlockToNodesMap().get(schedule.getCFG().getStartBlock())) {
             if (node instanceof FloatingReadNode) {
@@ -695,14 +696,14 @@
         assertDeepEquals(withinStartBlock, readEncountered);
     }
 
-    private static void assertReadAndWriteInSameBlock(SchedulePhase schedule, boolean inSame) {
+    private static void assertReadAndWriteInSameBlock(ScheduleResult schedule, boolean inSame) {
         StructuredGraph graph = schedule.getCFG().graph;
         FloatingReadNode read = graph.getNodes().filter(FloatingReadNode.class).first();
         WriteNode write = graph.getNodes().filter(WriteNode.class).first();
         assertTrue(!(inSame ^ schedule.getCFG().blockFor(read) == schedule.getCFG().blockFor(write)));
     }
 
-    private static void assertReadBeforeAllWritesInStartBlock(SchedulePhase schedule) {
+    private static void assertReadBeforeAllWritesInStartBlock(ScheduleResult schedule) {
         boolean writeNodeFound = false;
         boolean readNodeFound = false;
         for (Node node : schedule.nodesFor(schedule.getCFG().getStartBlock())) {
@@ -716,12 +717,12 @@
         assertTrue(readNodeFound);
     }
 
-    private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode) {
+    private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode) {
         return getFinalSchedule(snippet, mode, SchedulingStrategy.LATEST_OUT_OF_LOOPS);
     }
 
     @SuppressWarnings("try")
-    private SchedulePhase getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) {
+    private ScheduleResult getFinalSchedule(final String snippet, final TestMode mode, final SchedulingStrategy schedulingStrategy) {
         final StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
         try (Scope d = Debug.scope("FloatingReadTest", graph)) {
             try (OverrideScope s = OptionValue.override(OptScheduleOutOfLoops, schedulingStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS, OptImplicitNullChecks, false)) {
@@ -748,7 +749,7 @@
                 SchedulePhase schedule = new SchedulePhase(schedulingStrategy);
                 schedule.apply(graph);
                 assertDeepEquals(1, graph.getNodes().filter(StartNode.class).count());
-                return schedule;
+                return graph.getLastSchedule();
             }
         } catch (Throwable e) {
             throw Debug.handle(e);
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest.java	Mon Jan 04 00:48:58 2016 +0100
@@ -32,6 +32,7 @@
 import com.oracle.graal.nodes.LoopExitNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.calc.AddNode;
 import com.oracle.graal.nodes.calc.BinaryArithmeticNode;
 import com.oracle.graal.nodes.cfg.Block;
@@ -59,8 +60,9 @@
             fs.replaceAtUsages(null);
             GraphUtil.killWithUnusedFloatingInputs(fs);
         }
-        SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.LATEST);
-        schedule.apply(graph);
+        SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST);
+        schedulePhase.apply(graph);
+        ScheduleResult schedule = graph.getLastSchedule();
         NodeMap<Block> nodeToBlock = schedule.getCFG().getNodeToBlock();
         assertTrue(graph.getNodes().filter(LoopExitNode.class).count() == 1);
         LoopExitNode loopExit = graph.getNodes().filter(LoopExitNode.class).first();
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest2.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/SchedulingTest2.java	Mon Jan 04 00:48:58 2016 +0100
@@ -37,6 +37,7 @@
 import com.oracle.graal.nodes.StateSplit;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.calc.AddNode;
 import com.oracle.graal.nodes.calc.BinaryArithmeticNode;
 import com.oracle.graal.nodes.cfg.Block;
@@ -69,8 +70,9 @@
         returnNode.replaceAtPredecessor(beginNode);
         beginNode.setNext(returnNode);
         Debug.dump(graph, "Graph");
-        SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST);
-        schedule.apply(graph);
+        SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST);
+        schedulePhase.apply(graph);
+        ScheduleResult schedule = graph.getLastSchedule();
         BlockMap<List<Node>> blockToNodesMap = schedule.getBlockToNodesMap();
         NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
         assertDeepEquals(2, schedule.getCFG().getBlocks().size());
@@ -103,8 +105,8 @@
         FrameStateAssignmentPhase phase = new FrameStateAssignmentPhase();
         phase.apply(graph);
 
-        schedule = new SchedulePhase(SchedulingStrategy.EARLIEST);
-        schedule.apply(graph);
+        schedulePhase.apply(graph);
+        schedule = graph.getLastSchedule();
         blockToNodesMap = schedule.getBlockToNodesMap();
         nodeToBlock = schedule.getNodeToBlockMap();
         for (FrameState fs : graph.getNodes(FrameState.TYPE)) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/TypeSystemTest.java	Mon Jan 04 00:48:58 2016 +0100
@@ -39,6 +39,7 @@
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.java.CheckCastNode;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
@@ -208,8 +209,9 @@
 
     public static void outputGraph(StructuredGraph graph, String message) {
         TTY.println("========================= " + message);
-        SchedulePhase schedule = new SchedulePhase();
-        schedule.apply(graph);
+        SchedulePhase schedulePhase = new SchedulePhase();
+        schedulePhase.apply(graph);
+        ScheduleResult schedule = graph.getLastSchedule();
         for (Block block : schedule.getCFG().getBlocks()) {
             TTY.print("Block " + block + " ");
             if (block == schedule.getCFG().getStartBlock()) {
--- a/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/backend/BackendTest.java	Mon Jan 04 00:48:58 2016 +0100
@@ -34,7 +34,6 @@
 import com.oracle.graal.lir.gen.LIRGenerationResult;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.phases.OptimisticOptimizations;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 public abstract class BackendTest extends GraalCompilerTest {
 
@@ -48,15 +47,14 @@
 
     @SuppressWarnings("try")
     protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) {
-        SchedulePhase schedule = null;
         try (Scope s = Debug.scope("FrontEnd")) {
-            schedule = GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.method().getProfilingInfo(), getSuites());
+            GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.method().getProfilingInfo(), getSuites());
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
 
         CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false);
-        LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), schedule, graph, null, cc, null, getLIRSuites());
+        LIRGenerationResult lirGen = GraalCompiler.emitLIR(getBackend(), graph, null, cc, null, getLIRSuites());
         return lirGen;
     }
 
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java	Mon Jan 04 00:48:58 2016 +0100
@@ -68,6 +68,7 @@
 import com.oracle.graal.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
 import com.oracle.graal.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
 import com.oracle.graal.options.OptionValue;
@@ -176,8 +177,8 @@
     public static <T extends CompilationResult> T compile(Request<T> r) {
         assert !r.graph.isFrozen();
         try (Scope s0 = Debug.scope("GraalCompiler", r.graph, r.providers.getCodeCache())) {
-            SchedulePhase schedule = emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites);
-            emitBackEnd(r.graph, null, r.cc, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, schedule, null, r.lirSuites);
+            emitFrontEnd(r.providers, r.backend, r.graph, r.graphBuilderSuite, r.optimisticOpts, r.profilingInfo, r.suites);
+            emitBackEnd(r.graph, null, r.cc, r.installedCodeOwner, r.backend, r.compilationResult, r.factory, null, r.lirSuites);
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
@@ -196,7 +197,7 @@
      * Builds the graph, optimizes it.
      */
     @SuppressWarnings("try")
-    public static SchedulePhase emitFrontEnd(Providers providers, TargetProvider target, StructuredGraph graph, PhaseSuite<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts,
+    public static void emitFrontEnd(Providers providers, TargetProvider target, StructuredGraph graph, PhaseSuite<HighTierContext> graphBuilderSuite, OptimisticOptimizations optimisticOpts,
                     ProfilingInfo profilingInfo, Suites suites) {
         try (Scope s = Debug.scope("FrontEnd"); DebugCloseable a = FrontEnd.start()) {
             HighTierContext highTierContext = new HighTierContext(providers, graphBuilderSuite, optimisticOpts);
@@ -219,12 +220,8 @@
 
             LowTierContext lowTierContext = new LowTierContext(providers, target);
             suites.getLowTier().apply(graph, lowTierContext);
-            graph.maybeCompress();
 
-            SchedulePhase schedule = new SchedulePhase();
-            schedule.apply(graph);
-            Debug.dump(schedule, "Final HIR schedule");
-            return schedule;
+            Debug.dump(graph.getLastSchedule(), "Final HIR schedule");
         } catch (Throwable e) {
             throw Debug.handle(e);
         }
@@ -232,17 +229,17 @@
 
     @SuppressWarnings("try")
     public static <T extends CompilationResult> void emitBackEnd(StructuredGraph graph, Object stub, CallingConvention cc, ResolvedJavaMethod installedCodeOwner, Backend backend, T compilationResult,
-                    CompilationResultBuilderFactory factory, SchedulePhase schedule, RegisterConfig registerConfig, LIRSuites lirSuites) {
-        try (Scope s = Debug.scope("BackEnd", schedule); DebugCloseable a = BackEnd.start()) {
+                    CompilationResultBuilderFactory factory, RegisterConfig registerConfig, LIRSuites lirSuites) {
+        try (Scope s = Debug.scope("BackEnd", graph.getLastSchedule()); DebugCloseable a = BackEnd.start()) {
             // Repeatedly run the LIR code generation pass to improve statistical profiling results.
             for (int i = 0; i < EmitLIRRepeatCount.getValue(); i++) {
                 SchedulePhase dummySchedule = new SchedulePhase();
                 dummySchedule.apply(graph);
-                emitLIR(backend, dummySchedule, graph, stub, cc, registerConfig, lirSuites);
+                emitLIR(backend, graph, stub, cc, registerConfig, lirSuites);
             }
 
             LIRGenerationResult lirGen = null;
-            lirGen = emitLIR(backend, schedule, graph, stub, cc, registerConfig, lirSuites);
+            lirGen = emitLIR(backend, graph, stub, cc, registerConfig, lirSuites);
             try (Scope s2 = Debug.scope("CodeGen", lirGen, lirGen.getLIR())) {
                 int bytecodeSize = graph.method() == null ? 0 : graph.getBytecodeSize();
                 compilationResult.setHasUnsafeAccess(graph.hasUnsafeAccess());
@@ -256,14 +253,14 @@
     }
 
     @SuppressWarnings("try")
-    public static LIRGenerationResult emitLIR(Backend backend, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc, RegisterConfig registerConfig, LIRSuites lirSuites) {
+    public static LIRGenerationResult emitLIR(Backend backend, StructuredGraph graph, Object stub, CallingConvention cc, RegisterConfig registerConfig, LIRSuites lirSuites) {
         try {
-            return emitLIR0(backend, schedule, graph, stub, cc, registerConfig, lirSuites);
+            return emitLIR0(backend, graph, stub, cc, registerConfig, lirSuites);
         } catch (OutOfRegistersException e) {
             if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) {
                 try (OverrideScope s = OptionValue.override(RegisterPressure, ALL_REGISTERS)) {
                     // retry with default register set
-                    return emitLIR0(backend, schedule, graph, stub, cc, registerConfig, lirSuites);
+                    return emitLIR0(backend, graph, stub, cc, registerConfig, lirSuites);
                 }
             } else {
                 throw e;
@@ -272,8 +269,9 @@
     }
 
     @SuppressWarnings("try")
-    private static LIRGenerationResult emitLIR0(Backend backend, SchedulePhase schedule, StructuredGraph graph, Object stub, CallingConvention cc, RegisterConfig registerConfig, LIRSuites lirSuites) {
+    private static LIRGenerationResult emitLIR0(Backend backend, StructuredGraph graph, Object stub, CallingConvention cc, RegisterConfig registerConfig, LIRSuites lirSuites) {
         try (Scope ds = Debug.scope("EmitLIR"); DebugCloseable a = EmitLIR.start()) {
+            ScheduleResult schedule = graph.getLastSchedule();
             List<Block> blocks = schedule.getCFG().getBlocks();
             Block startBlock = schedule.getCFG().getStartBlock();
             assert startBlock != null;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/LIRGenerationPhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/LIRGenerationPhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -36,9 +36,9 @@
 import com.oracle.graal.lir.phases.LIRPhase;
 import com.oracle.graal.lir.ssa.SSAUtil;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.spi.NodeLIRBuilderTool;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 public class LIRGenerationPhase extends LIRPhase<LIRGenerationPhase.LIRGenerationContext> {
 
@@ -46,9 +46,9 @@
         private final NodeLIRBuilderTool nodeLirBuilder;
         private final LIRGeneratorTool lirGen;
         private final StructuredGraph graph;
-        private final SchedulePhase schedule;
+        private final ScheduleResult schedule;
 
-        public LIRGenerationContext(LIRGeneratorTool lirGen, NodeLIRBuilderTool nodeLirBuilder, StructuredGraph graph, SchedulePhase schedule) {
+        public LIRGenerationContext(LIRGeneratorTool lirGen, NodeLIRBuilderTool nodeLirBuilder, StructuredGraph graph, ScheduleResult schedule) {
             this.nodeLirBuilder = nodeLirBuilder;
             this.lirGen = lirGen;
             this.graph = graph;
@@ -61,7 +61,7 @@
                     LIRGenerationPhase.LIRGenerationContext context) {
         NodeLIRBuilderTool nodeLirBuilder = context.nodeLirBuilder;
         StructuredGraph graph = context.graph;
-        SchedulePhase schedule = context.schedule;
+        ScheduleResult schedule = context.schedule;
         for (B b : linearScanOrder) {
             emitBlock(nodeLirBuilder, lirGenRes, (Block) b, graph, schedule.getBlockToNodesMap());
         }
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/phases/LowTier.java	Mon Jan 04 00:48:58 2016 +0100
@@ -42,6 +42,7 @@
 import com.oracle.graal.phases.common.RemoveValueProxyPhase;
 import com.oracle.graal.phases.common.UseTrappingNullChecksPhase;
 import com.oracle.graal.phases.common.instrumentation.InlineInstrumentationPhase;
+import com.oracle.graal.phases.schedule.SchedulePhase;
 import com.oracle.graal.phases.tiers.LowTierContext;
 
 public class LowTier extends PhaseSuite<LowTierContext> {
@@ -84,5 +85,7 @@
         appendPhase(new UseTrappingNullChecksPhase());
 
         appendPhase(new DeadCodeEliminationPhase(Required));
+
+        appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.FINAL_SCHEDULE));
     }
 }
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java	Mon Jan 04 00:48:58 2016 +0100
@@ -58,7 +58,6 @@
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.phases.OptimisticOptimizations;
 import com.oracle.graal.phases.PhaseSuite;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 import com.oracle.graal.phases.tiers.Suites;
 
 //JaCoCo Exclude
@@ -182,9 +181,9 @@
                 try (Scope s0 = Debug.scope("StubCompilation", graph, providers.getCodeCache())) {
                     Suites defaultSuites = providers.getSuites().getDefaultSuites();
                     Suites suites = new Suites(new PhaseSuite<>(), defaultSuites.getMidTier(), defaultSuites.getLowTier());
-                    SchedulePhase schedule = emitFrontEnd(providers, backend, graph, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), suites);
+                    emitFrontEnd(providers, backend, graph, providers.getSuites().getDefaultGraphBuilderSuite(), OptimisticOptimizations.ALL, getProfilingInfo(graph), suites);
                     LIRSuites lirSuites = createLIRSuites();
-                    emitBackEnd(graph, Stub.this, incomingCc, getInstalledCodeOwner(), backend, compResult, CompilationResultBuilderFactory.Default, schedule, getRegisterConfig(), lirSuites);
+                    emitBackEnd(graph, Stub.this, incomingCc, getInstalledCodeOwner(), backend, compResult, CompilationResultBuilderFactory.Default, getRegisterConfig(), lirSuites);
                     assert checkStubInvariants();
                 } catch (Throwable e) {
                     throw Debug.handle(e);
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/StructuredGraph.java	Mon Jan 04 00:48:58 2016 +0100
@@ -36,12 +36,16 @@
 import jdk.vm.ci.meta.SpeculationLog;
 import jdk.vm.ci.runtime.JVMCICompiler;
 
+import com.oracle.graal.compiler.common.cfg.BlockMap;
 import com.oracle.graal.compiler.common.type.Stamp;
 import com.oracle.graal.debug.JavaMethodContext;
 import com.oracle.graal.graph.Graph;
 import com.oracle.graal.graph.Node;
+import com.oracle.graal.graph.NodeMap;
 import com.oracle.graal.graph.spi.SimplifierTool;
 import com.oracle.graal.nodes.calc.FloatingNode;
+import com.oracle.graal.nodes.cfg.Block;
+import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.nodes.java.MethodCallTargetNode;
 import com.oracle.graal.nodes.spi.VirtualizableAllocation;
 import com.oracle.graal.nodes.util.GraphUtil;
@@ -108,6 +112,34 @@
         }
     }
 
+    public static class ScheduleResult {
+        private final ControlFlowGraph cfg;
+        private final NodeMap<Block> nodeToBlockMap;
+        private final BlockMap<List<Node>> blockToNodesMap;
+
+        public ScheduleResult(ControlFlowGraph cfg, NodeMap<Block> nodeToBlockMap, BlockMap<List<Node>> blockToNodesMap) {
+            this.cfg = cfg;
+            this.nodeToBlockMap = nodeToBlockMap;
+            this.blockToNodesMap = blockToNodesMap;
+        }
+
+        public ControlFlowGraph getCFG() {
+            return cfg;
+        }
+
+        public NodeMap<Block> getNodeToBlockMap() {
+            return nodeToBlockMap;
+        }
+
+        public BlockMap<List<Node>> getBlockToNodesMap() {
+            return blockToNodesMap;
+        }
+
+        public List<Node> nodesFor(Block block) {
+            return blockToNodesMap.get(block);
+        }
+    }
+
     public static final long INVALID_GRAPH_ID = -1;
 
     private static final AtomicLong uniqueGraphIds = new AtomicLong();
@@ -127,6 +159,8 @@
 
     private final SpeculationLog speculationLog;
 
+    private ScheduleResult lastSchedule;
+
     /**
      * Records the methods that were inlined while constructing this graph, one entry for each time
      * a specific method is inlined.
@@ -183,6 +217,18 @@
         this.speculationLog = speculationLog;
     }
 
+    public void setLastSchedule(ScheduleResult result) {
+        lastSchedule = result;
+    }
+
+    public ScheduleResult getLastSchedule() {
+        return lastSchedule;
+    }
+
+    public void clearLastSchedule() {
+        setLastSchedule(null);
+    }
+
     public Stamp getReturnStamp() {
         Stamp returnStamp = null;
         for (ReturnNode returnNode : getNodes(ReturnNode.TYPE)) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/DominatorConditionalEliminationPhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -154,10 +154,10 @@
             if (fullSchedule) {
                 SchedulePhase schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST);
                 schedule.apply(graph);
-                ControlFlowGraph cfg = schedule.getCFG();
+                ControlFlowGraph cfg = graph.getLastSchedule().getCFG();
                 cfg.computePostdominators();
-                blockToNodes = b -> schedule.getBlockToNodesMap().get(b);
-                nodeToBlock = n -> schedule.getNodeToBlockMap().get(n);
+                blockToNodes = b -> graph.getLastSchedule().getBlockToNodesMap().get(b);
+                nodeToBlock = n -> graph.getLastSchedule().getNodeToBlockMap().get(n);
                 startBlock = cfg.getStartBlock();
             } else {
                 ControlFlowGraph cfg = ControlFlowGraph.compute(graph, true, true, true, true);
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -47,6 +47,7 @@
 import com.oracle.graal.nodes.StateSplit;
 import com.oracle.graal.nodes.StructuredGraph;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.IsNullNode;
 import com.oracle.graal.nodes.cfg.Block;
@@ -259,8 +260,9 @@
     @Override
     protected void run(StructuredGraph graph, MidTierContext context) {
         if (graph.getGuardsStage().allowsFloatingGuards()) {
-            SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.EARLIEST);
-            schedule.apply(graph);
+            SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.EARLIEST);
+            schedulePhase.apply(graph);
+            ScheduleResult schedule = graph.getLastSchedule();
 
             for (Block block : schedule.getCFG().getBlocks()) {
                 processBlock(block, schedule, context != null ? context.getTarget().implicitNullCheckLimit : 0);
@@ -276,7 +278,7 @@
         return true;
     }
 
-    private static void processBlock(Block block, SchedulePhase schedule, int implicitNullCheckLimit) {
+    private static void processBlock(Block block, ScheduleResult schedule, int implicitNullCheckLimit) {
         if (OptImplicitNullChecks.getValue() && implicitNullCheckLimit > 0) {
             new UseImplicitNullChecks(implicitNullCheckLimit).processNodes(block, schedule);
         }
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -58,6 +58,7 @@
 import com.oracle.graal.nodes.GuardNode;
 import com.oracle.graal.nodes.LogicNode;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.calc.FloatingNode;
 import com.oracle.graal.nodes.cfg.Block;
@@ -272,7 +273,8 @@
 
         private final PhaseContext context;
         private final LoweringMode mode;
-        private final SchedulePhase schedule;
+        private ScheduleResult schedule;
+        private final SchedulePhase schedulePhase;
 
         private Round(PhaseContext context, LoweringMode mode) {
             this.context = context;
@@ -285,7 +287,7 @@
              */
             boolean immutableSchedule = mode == LoweringMode.VERIFY_LOWERING;
 
-            this.schedule = new SchedulePhase(immutableSchedule);
+            this.schedulePhase = new SchedulePhase(immutableSchedule);
         }
 
         @Override
@@ -302,7 +304,8 @@
 
         @Override
         public void run(StructuredGraph graph) {
-            schedule.apply(graph, false);
+            schedulePhase.apply(graph, false);
+            schedule = graph.getLastSchedule();
             schedule.getCFG().computePostdominators();
             Block startBlock = schedule.getCFG().getStartBlock();
             ProcessFrame rootFrame = new ProcessFrame(startBlock, graph.createNodeBitMap(), startBlock.getBeginNode(), null);
@@ -457,7 +460,7 @@
      *     if (alwaysReachedBlock != null &amp;&amp; alwaysReachedBlock.getDominator() == block) {
      *         processBlock(alwaysReachedBlock);
      *     }
-     *
+     * 
      *     // Now go for the other dominators.
      *     for (Block dominated : block.getDominated()) {
      *         if (dominated != alwaysReachedBlock) {
--- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -42,6 +42,7 @@
 import com.oracle.graal.nodes.ReturnNode;
 import com.oracle.graal.nodes.SafepointNode;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.UnwindNode;
 import com.oracle.graal.nodes.VirtualState;
 import com.oracle.graal.nodes.calc.BinaryNode;
@@ -97,7 +98,7 @@
         for (Loop<Block> loop : cfg.getLoops()) {
             double loopProbability = cfg.blockFor(loop.getHeader().getBeginNode()).probability();
             if (loopProbability > (1D / Integer.MAX_VALUE)) {
-                addSectionCounters(loop.getHeader().getBeginNode(), loop.getBlocks(), loop.getChildren(), schedule, cfg);
+                addSectionCounters(loop.getHeader().getBeginNode(), loop.getBlocks(), loop.getChildren(), graph.getLastSchedule(), cfg);
             }
         }
         // don't put the counter increase directly after the start (problems with OSR)
@@ -105,7 +106,7 @@
         while (current.next() instanceof FixedWithNextNode) {
             current = (FixedWithNextNode) current.next();
         }
-        addSectionCounters(current, cfg.getBlocks(), cfg.getLoops(), schedule, cfg);
+        addSectionCounters(current, cfg.getBlocks(), cfg.getLoops(), graph.getLastSchedule(), cfg);
 
         if (WITH_INVOKES) {
             for (Node node : graph.getNodes()) {
@@ -118,7 +119,7 @@
         }
     }
 
-    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop<Block>> childLoops, SchedulePhase schedule, ControlFlowGraph cfg) {
+    private static void addSectionCounters(FixedWithNextNode start, Collection<Block> sectionBlocks, Collection<Loop<Block>> childLoops, ScheduleResult schedule, ControlFlowGraph cfg) {
         HashSet<Block> blocks = new HashSet<>(sectionBlocks);
         for (Loop<?> loop : childLoops) {
             blocks.removeAll(loop.getBlocks());
@@ -138,7 +139,7 @@
         }
     }
 
-    private static double getSectionWeight(SchedulePhase schedule, Collection<Block> blocks) {
+    private static double getSectionWeight(ScheduleResult schedule, Collection<Block> blocks) {
         double count = 0;
         for (Block block : blocks) {
             double blockProbability = block.probability();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/graph/ScheduledNodeIterator.java	Mon Jan 04 00:48:58 2016 +0100
@@ -27,12 +27,12 @@
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.FixedNode;
 import com.oracle.graal.nodes.FixedWithNextNode;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.Block;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 /**
  * Iterates over a list of nodes, which usually comes from
- * {@link SchedulePhase#getBlockToNodesMap()}.
+ * {@link ScheduleResult#getBlockToNodesMap()}.
  *
  * While iterating, it is possible to {@link #insert(FixedNode, FixedWithNextNode) insert} and
  * {@link #replaceCurrent(FixedWithNextNode) replace} nodes.
@@ -43,11 +43,11 @@
     private FixedWithNextNode reconnect;
     private ListIterator<Node> iterator;
 
-    public void processNodes(Block block, SchedulePhase shedule) {
+    public void processNodes(Block block, ScheduleResult schedule) {
         lastFixed = block.getBeginNode();
         assert lastFixed != null;
         reconnect = null;
-        iterator = shedule.nodesFor(block).listIterator();
+        iterator = schedule.nodesFor(block).listIterator();
 
         while (iterator.hasNext()) {
             Node node = iterator.next();
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -23,7 +23,6 @@
 package com.oracle.graal.phases.schedule;
 
 import static com.oracle.graal.compiler.common.GraalOptions.OptScheduleOutOfLoops;
-import static com.oracle.graal.compiler.common.cfg.AbstractControlFlowGraph.dominates;
 import static com.oracle.graal.compiler.common.cfg.AbstractControlFlowGraph.strictlyDominates;
 
 import java.util.ArrayList;
@@ -60,6 +59,7 @@
 import com.oracle.graal.nodes.StartNode;
 import com.oracle.graal.nodes.StateSplit;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.VirtualState;
 import com.oracle.graal.nodes.StructuredGraph.GuardsStage;
@@ -75,45 +75,14 @@
 
 public final class SchedulePhase extends Phase {
 
-    /**
-     * Error thrown when a graph cannot be scheduled.
-     */
-    public static class SchedulingError extends Error {
-
-        private static final long serialVersionUID = 1621001069476473145L;
-
-        public SchedulingError() {
-            super();
-        }
-
-        /**
-         * This constructor creates a {@link SchedulingError} with a message assembled via
-         * {@link String#format(String, Object...)}.
-         *
-         * @param format a {@linkplain Formatter format} string
-         * @param args parameters to {@link String#format(String, Object...)}
-         */
-        public SchedulingError(String format, Object... args) {
-            super(String.format(format, args));
-        }
-
-    }
-
     public static enum SchedulingStrategy {
         EARLIEST,
         LATEST,
-        LATEST_OUT_OF_LOOPS
+        LATEST_OUT_OF_LOOPS,
+        FINAL_SCHEDULE
     }
 
-    private ControlFlowGraph cfg;
-
-    /**
-     * Map from blocks to the nodes in each block.
-     */
-    private BlockMap<List<Node>> blockToNodesMap;
-    private BlockMap<LocationSet> blockToKillSet;
     private final SchedulingStrategy selectedStrategy;
-    private NodeMap<Block> nodeToBlockMap;
 
     private final boolean immutableGraph;
 
@@ -129,7 +98,7 @@
         this(strategy, false);
     }
 
-    public SchedulePhase(SchedulingStrategy strategy, boolean immutableGraph) {
+    private SchedulePhase(SchedulingStrategy strategy, boolean immutableGraph) {
         this.selectedStrategy = strategy;
         this.immutableGraph = immutableGraph;
     }
@@ -149,9 +118,27 @@
     }
 
     @Override
-    @SuppressWarnings("try")
     protected void run(StructuredGraph graph) {
         try (NodeEventScope scope = verifyImmutableGraph(graph)) {
+            Instance inst = new Instance();
+            inst.run(graph, selectedStrategy, immutableGraph);
+        }
+    }
+
+    public static class Instance {
+
+        private ControlFlowGraph cfg;
+
+        /**
+         * Map from blocks to the nodes in each block.
+         */
+        private BlockMap<List<Node>> blockToNodesMap;
+        private BlockMap<LocationSet> blockToKillSet;
+
+        private NodeMap<Block> nodeToBlockMap;
+
+        @SuppressWarnings("try")
+        public void run(StructuredGraph graph, SchedulingStrategy selectedStrategy, boolean immutableGraph) {
             // assert GraphOrder.assertNonCyclicGraph(graph);
             cfg = ControlFlowGraph.compute(graph, true, true, true, false);
 
@@ -160,69 +147,67 @@
                 this.nodeToBlockMap = graph.createNodeMap();
                 this.blockToNodesMap = new BlockMap<>(cfg);
                 NodeBitMap visited = graph.createNodeBitMap();
-                scheduleEarliestIterative(blockToNodesMap, nodeToBlockMap, visited, graph, null);
-                return;
+                scheduleEarliestIterative(blockToNodesMap, nodeToBlockMap, visited, graph, null, immutableGraph);
             } else {
-                boolean isOutOfLoops = selectedStrategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS;
-                if (selectedStrategy == SchedulingStrategy.LATEST || isOutOfLoops) {
-                    NodeMap<Block> currentNodeMap = graph.createNodeMap();
-                    BlockMap<List<Node>> earliestBlockToNodesMap = new BlockMap<>(cfg);
-                    NodeBitMap visited = graph.createNodeBitMap();
-                    NodeBitMap unreachableNodes = immutableGraph ? graph.createNodeBitMap() : null;
+                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;
+                // Assign early so we are getting a context in case of an exception.
+                this.blockToNodesMap = earliestBlockToNodesMap;
+                this.nodeToBlockMap = currentNodeMap;
 
-                    scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, unreachableNodes);
-                    BlockMap<List<Node>> latestBlockToNodesMap = new BlockMap<>(cfg);
+                scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, unreachableNodes, immutableGraph);
+                BlockMap<List<Node>> latestBlockToNodesMap = new BlockMap<>(cfg);
 
-                    for (Block b : cfg.getBlocks()) {
-                        latestBlockToNodesMap.put(b, new ArrayList<Node>());
-                    }
+                for (Block b : cfg.getBlocks()) {
+                    latestBlockToNodesMap.put(b, new ArrayList<Node>());
+                }
 
-                    BlockMap<ArrayList<FloatingReadNode>> watchListMap = calcLatestBlocks(isOutOfLoops, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap, unreachableNodes);
-                    sortNodesLatestWithinBlock(cfg, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited);
+                BlockMap<ArrayList<FloatingReadNode>> watchListMap = calcLatestBlocks(selectedStrategy, currentNodeMap, earliestBlockToNodesMap, visited, latestBlockToNodesMap, unreachableNodes,
+                                immutableGraph);
+                sortNodesLatestWithinBlock(cfg, earliestBlockToNodesMap, latestBlockToNodesMap, currentNodeMap, watchListMap, visited);
 
-                    assert verifySchedule(cfg, latestBlockToNodesMap, currentNodeMap);
-                    assert MemoryScheduleVerification.check(cfg.getStartBlock(), latestBlockToNodesMap);
+                assert verifySchedule(cfg, latestBlockToNodesMap, currentNodeMap);
+                assert MemoryScheduleVerification.check(cfg.getStartBlock(), latestBlockToNodesMap);
 
-                    this.blockToNodesMap = latestBlockToNodesMap;
-                    this.nodeToBlockMap = currentNodeMap;
+                this.blockToNodesMap = latestBlockToNodesMap;
+                this.nodeToBlockMap = currentNodeMap;
 
-                    cfg.setNodeToBlock(currentNodeMap);
-                }
+                cfg.setNodeToBlock(currentNodeMap);
             }
+
+            graph.setLastSchedule(new ScheduleResult(this.cfg, this.nodeToBlockMap, this.blockToNodesMap));
         }
-    }
 
-    @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, NodeBitMap unreachableNodes) {
-        BlockMap<ArrayList<FloatingReadNode>> watchListMap = null;
-        for (Block b : cfg.postOrder()) {
-            List<Node> blockToNodes = earliestBlockToNodesMap.get(b);
-            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) == b;
-                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 currentBlock = b;
-                    assert currentBlock != null;
+        @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, NodeBitMap unreachableNodes, boolean immutableGraph) {
+            BlockMap<ArrayList<FloatingReadNode>> watchListMap = new BlockMap<>(cfg);
+            for (Block currentBlock : cfg.postOrder()) {
+                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;
 
-                    Block latestBlock = calcLatestBlock(b, isOutOfLoops, currentNode, currentNodeMap, unreachableNodes);
-                    assert checkLatestEarliestRelation(currentNode, currentBlock, latestBlock);
-                    if (latestBlock != currentBlock) {
+                        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();
@@ -230,651 +215,657 @@
                                     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 != currentBlock) {
-                                    // We are not constraint within currentBlock. Check if
-                                    // we are contraint while walking down the dominator
-                                    // line.
-                                    Block newLatestBlock = adjustLatestForRead(floatingReadNode, currentBlock, latestBlock, location);
-                                    assert dominates(newLatestBlock, latestBlock);
-                                    assert dominates(currentBlock, newLatestBlock);
-                                    latestBlock = newLatestBlock;
-
-                                    if (newLatestBlock != currentBlock && latestBlock.canKill(location)) {
-                                        if (watchListMap == null) {
-                                            watchListMap = new BlockMap<>(cfg);
-                                        }
-                                        if (watchListMap.get(latestBlock) == null) {
-                                            watchListMap.put(latestBlock, new ArrayList<>());
-                                        }
-                                        watchListMap.get(latestBlock).add(floatingReadNode);
-                                    }
-                                }
                             }
                         }
-                        currentNodeMap.set(currentNode, latestBlock);
-                        currentBlock = latestBlock;
+
+                        if (latestBlock == null) {
+                            // We are not constraint within earliest block => calculate optimized
+                            // schedule.
+                            calcLatestBlock(currentBlock, strategy, currentNode, currentNodeMap, unreachableNodes, constrainingLocation, watchListMap, latestBlockToNodesMap, visited, immutableGraph);
+                        } else {
+                            selectLatestBlock(currentNode, currentBlock, latestBlock, currentNodeMap, watchListMap, constrainingLocation, latestBlockToNodesMap);
+                        }
                     }
-                    latestBlockToNodesMap.get(currentBlock).add(currentNode);
                 }
             }
-        }
-        return watchListMap;
-    }
-
-    private static boolean checkLatestEarliestRelation(Node currentNode, Block earliestBlock, Block latestBlock) {
-        assert AbstractControlFlowGraph.dominates(earliestBlock, latestBlock) || (currentNode instanceof VirtualState && latestBlock == earliestBlock.getDominator()) : String.format(
-                        "%s %s (%s) %s (%s)", currentNode, earliestBlock, earliestBlock.getBeginNode(), latestBlock, latestBlock.getBeginNode());
-        return true;
-    }
-
-    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 Block adjustLatestForRead(FloatingReadNode floatingReadNode, Block earliestBlock, Block latestBlock, LocationIdentity location) {
-        assert strictlyDominates(earliestBlock, latestBlock);
-        Block current = latestBlock.getDominator();
-
-        // Collect dominator chain that needs checking.
-        List<Block> dominatorChain = new ArrayList<>();
-        dominatorChain.add(latestBlock);
-        while (current != earliestBlock) {
-            // Current is an intermediate dominator between earliestBlock and latestBlock.
-            assert strictlyDominates(earliestBlock, current) && strictlyDominates(current, latestBlock);
-            if (current.canKill(location)) {
-                dominatorChain.clear();
-            }
-            dominatorChain.add(current);
-            current = current.getDominator();
-            assert current != null : floatingReadNode;
+            return watchListMap;
         }
 
-        // The first element of dominatorChain now contains the latest possible block.
-        assert dominatorChain.size() >= 1;
-        assert dominatorChain.get(dominatorChain.size() - 1).getDominator() == earliestBlock;
+        protected static void selectLatestBlock(Node currentNode, Block currentBlock, Block latestBlock, NodeMap<Block> currentNodeMap, BlockMap<ArrayList<FloatingReadNode>> watchListMap,
+                        LocationIdentity constrainingLocation, BlockMap<List<Node>> latestBlockToNodesMap) {
 
-        Block lastBlock = earliestBlock;
-        for (int i = dominatorChain.size() - 1; i >= 0; --i) {
-            Block currentBlock = dominatorChain.get(i);
-            if (currentBlock.getLoopDepth() > lastBlock.getLoopDepth()) {
-                // We are entering a loop boundary. The new loops must not kill the location for the
-                // crossing to be safe.
-                if (currentBlock.getLoop() != null && ((HIRLoop) currentBlock.getLoop()).canKill(location)) {
-                    break;
+            assert checkLatestEarliestRelation(currentNode, currentBlock, latestBlock);
+            if (currentBlock != latestBlock) {
+                currentNodeMap.setAndGrow(currentNode, latestBlock);
+
+                if (constrainingLocation != null && latestBlock.canKill(constrainingLocation)) {
+                    if (watchListMap.get(latestBlock) == null) {
+                        watchListMap.put(latestBlock, new ArrayList<>());
+                    }
+                    watchListMap.get(latestBlock).add((FloatingReadNode) currentNode);
                 }
             }
 
-            if (currentBlock.canKillBetweenThisAndDominator(location)) {
-                break;
-            }
-            lastBlock = currentBlock;
+            latestBlockToNodesMap.get(latestBlock).add(currentNode);
         }
 
-        return lastBlock;
-    }
+        private static boolean checkLatestEarliestRelation(Node currentNode, Block earliestBlock, Block latestBlock) {
+            assert AbstractControlFlowGraph.dominates(earliestBlock, latestBlock) || (currentNode instanceof VirtualState && latestBlock == earliestBlock.getDominator()) : String.format(
+                            "%s %s (%s) %s (%s)", currentNode, earliestBlock, earliestBlock.getBeginNode(), latestBlock, latestBlock.getBeginNode());
+            return true;
+        }
 
-    private static void fillKillSet(LocationSet killed, List<Node> subList) {
-        if (!killed.isAny()) {
-            for (Node n : subList) {
-                // Check if this node kills a node in the watch list.
-                if (n instanceof MemoryCheckpoint.Single) {
-                    LocationIdentity identity = ((MemoryCheckpoint.Single) n).getLocationIdentity();
-                    killed.add(identity);
-                    if (killed.isAny()) {
-                        return;
+        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;
                     }
-                } else if (n instanceof MemoryCheckpoint.Multi) {
-                    for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) {
+                }
+            }
+            return true;
+        }
+
+        public static Block checkKillsBetween(Block earliestBlock, Block latestBlock, LocationIdentity location) {
+            assert strictlyDominates(earliestBlock, latestBlock);
+            Block current = latestBlock.getDominator();
+
+            // Collect dominator chain that needs checking.
+            List<Block> dominatorChain = new ArrayList<>();
+            dominatorChain.add(latestBlock);
+            while (current != earliestBlock) {
+                // Current is an intermediate dominator between earliestBlock and latestBlock.
+                assert strictlyDominates(earliestBlock, current) && strictlyDominates(current, latestBlock);
+                if (current.canKill(location)) {
+                    dominatorChain.clear();
+                }
+                dominatorChain.add(current);
+                current = current.getDominator();
+            }
+
+            // The first element of dominatorChain now contains the latest possible block.
+            assert dominatorChain.size() >= 1;
+            assert dominatorChain.get(dominatorChain.size() - 1).getDominator() == earliestBlock;
+
+            Block lastBlock = earliestBlock;
+            for (int i = dominatorChain.size() - 1; i >= 0; --i) {
+                Block currentBlock = dominatorChain.get(i);
+                if (currentBlock.getLoopDepth() > lastBlock.getLoopDepth()) {
+                    // We are entering a loop boundary. The new loops must not kill the location for
+                    // the crossing to be safe.
+                    if (currentBlock.getLoop() != null && ((HIRLoop) currentBlock.getLoop()).canKill(location)) {
+                        break;
+                    }
+                }
+
+                if (currentBlock.canKillBetweenThisAndDominator(location)) {
+                    break;
+                }
+                lastBlock = currentBlock;
+            }
+
+            return lastBlock;
+        }
+
+        private static void fillKillSet(LocationSet killed, List<Node> subList) {
+            if (!killed.isAny()) {
+                for (Node n : subList) {
+                    // Check if this node kills a node in the watch list.
+                    if (n instanceof MemoryCheckpoint.Single) {
+                        LocationIdentity identity = ((MemoryCheckpoint.Single) n).getLocationIdentity();
                         killed.add(identity);
                         if (killed.isAny()) {
                             return;
                         }
+                    } else if (n instanceof MemoryCheckpoint.Multi) {
+                        for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) {
+                            killed.add(identity);
+                            if (killed.isAny()) {
+                                return;
+                            }
+                        }
                     }
                 }
             }
         }
-    }
 
-    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 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 void sortNodesLatestWithinBlock(Block b, BlockMap<List<Node>> earliestBlockToNodesMap, BlockMap<List<Node>> latestBlockToNodesMap, NodeMap<Block> nodeMap,
-                    BlockMap<ArrayList<FloatingReadNode>> watchListMap, NodeBitMap unprocessed) {
-        List<Node> earliestSorting = earliestBlockToNodesMap.get(b);
-        ArrayList<Node> result = new ArrayList<>(earliestSorting.size());
-        ArrayList<FloatingReadNode> watchList = null;
-        if (watchListMap != null) {
-            watchList = watchListMap.get(b);
-            assert watchList == null || !b.getKillLocations().isEmpty();
-        }
-        AbstractBeginNode beginNode = b.getBeginNode();
-        if (beginNode instanceof LoopExitNode) {
-            LoopExitNode loopExitNode = (LoopExitNode) beginNode;
-            for (ProxyNode proxy : loopExitNode.proxies()) {
-                unprocessed.clear(proxy);
-                ValueNode value = proxy.value();
-                if (value != null && nodeMap.get(value) == b) {
-                    sortIntoList(value, b, result, nodeMap, unprocessed, null);
+        private static void sortNodesLatestWithinBlock(Block b, BlockMap<List<Node>> earliestBlockToNodesMap, BlockMap<List<Node>> latestBlockToNodesMap, NodeMap<Block> nodeMap,
+                        BlockMap<ArrayList<FloatingReadNode>> watchListMap, NodeBitMap unprocessed) {
+            List<Node> earliestSorting = earliestBlockToNodesMap.get(b);
+            ArrayList<Node> result = new ArrayList<>(earliestSorting.size());
+            ArrayList<FloatingReadNode> watchList = null;
+            if (watchListMap != null) {
+                watchList = watchListMap.get(b);
+                assert watchList == null || !b.getKillLocations().isEmpty();
+            }
+            AbstractBeginNode beginNode = b.getBeginNode();
+            if (beginNode instanceof LoopExitNode) {
+                LoopExitNode loopExitNode = (LoopExitNode) beginNode;
+                for (ProxyNode proxy : loopExitNode.proxies()) {
+                    unprocessed.clear(proxy);
+                    ValueNode value = proxy.value();
+                    if (value != null && nodeMap.get(value) == b) {
+                        sortIntoList(value, b, result, nodeMap, unprocessed, null);
+                    }
                 }
             }
+            FixedNode endNode = b.getEndNode();
+            FixedNode fixedEndNode = null;
+            if (isFixedEnd(endNode)) {
+                // Only if the end node is either a control split or an end node, we need to force
+                // it to be the last node in the schedule.
+                fixedEndNode = endNode;
+            }
+            for (Node n : earliestSorting) {
+                if (n != fixedEndNode) {
+                    if (n instanceof FixedNode) {
+                        assert nodeMap.get(n) == b;
+                        checkWatchList(b, nodeMap, unprocessed, result, watchList, n);
+                        sortIntoList(n, b, result, nodeMap, unprocessed, null);
+                    } else if (nodeMap.get(n) == b && n instanceof FloatingReadNode) {
+                        FloatingReadNode floatingReadNode = (FloatingReadNode) n;
+                        LocationIdentity location = floatingReadNode.getLocationIdentity();
+                        if (b.canKill(location)) {
+                            // This read can be killed in this block, add to watch list.
+                            if (watchList == null) {
+                                watchList = new ArrayList<>();
+                            }
+                            watchList.add(floatingReadNode);
+                        }
+                    }
+                }
+            }
+
+            for (Node n : latestBlockToNodesMap.get(b)) {
+                assert nodeMap.get(n) == b : n;
+                assert !(n instanceof FixedNode);
+                if (unprocessed.isMarked(n)) {
+                    sortIntoList(n, b, result, nodeMap, unprocessed, fixedEndNode);
+                }
+            }
+
+            if (endNode != null && unprocessed.isMarked(endNode)) {
+                sortIntoList(endNode, b, result, nodeMap, unprocessed, null);
+            }
+
+            latestBlockToNodesMap.put(b, result);
         }
-        FixedNode endNode = b.getEndNode();
-        FixedNode fixedEndNode = null;
-        if (isFixedEnd(endNode)) {
-            // Only if the end node is either a control split or an end node, we need to force it to
-            // be the last node in the schedule.
-            fixedEndNode = endNode;
-        }
-        for (Node n : earliestSorting) {
-            if (n != fixedEndNode) {
-                if (n instanceof FixedNode) {
-                    assert nodeMap.get(n) == b;
-                    checkWatchList(b, nodeMap, unprocessed, result, watchList, n);
-                    sortIntoList(n, b, result, nodeMap, unprocessed, null);
-                } else if (nodeMap.get(n) == b && n instanceof FloatingReadNode) {
-                    FloatingReadNode floatingReadNode = (FloatingReadNode) n;
-                    LocationIdentity location = floatingReadNode.getLocationIdentity();
-                    if (b.canKill(location)) {
-                        // This read can be killed in this block, add to watch list.
-                        if (watchList == null) {
-                            watchList = new ArrayList<>();
-                        }
-                        watchList.add(floatingReadNode);
+
+        private static void checkWatchList(Block b, NodeMap<Block> nodeMap, NodeBitMap unprocessed, ArrayList<Node> result, ArrayList<FloatingReadNode> watchList, Node n) {
+            if (watchList != null && !watchList.isEmpty()) {
+                // Check if this node kills a node in the watch list.
+                if (n instanceof MemoryCheckpoint.Single) {
+                    LocationIdentity identity = ((MemoryCheckpoint.Single) n).getLocationIdentity();
+                    checkWatchList(watchList, identity, b, result, nodeMap, unprocessed);
+                } else if (n instanceof MemoryCheckpoint.Multi) {
+                    for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) {
+                        checkWatchList(watchList, identity, b, result, nodeMap, unprocessed);
                     }
                 }
             }
         }
 
-        for (Node n : latestBlockToNodesMap.get(b)) {
-            assert nodeMap.get(n) == b;
-            assert !(n instanceof FixedNode);
-            if (unprocessed.isMarked(n)) {
-                sortIntoList(n, b, result, nodeMap, unprocessed, fixedEndNode);
-            }
-        }
-
-        if (endNode != null && unprocessed.isMarked(endNode)) {
-            sortIntoList(endNode, b, result, nodeMap, unprocessed, null);
-        }
-
-        latestBlockToNodesMap.put(b, result);
-    }
-
-    private static void checkWatchList(Block b, NodeMap<Block> nodeMap, NodeBitMap unprocessed, ArrayList<Node> result, ArrayList<FloatingReadNode> watchList, Node n) {
-        if (watchList != null && !watchList.isEmpty()) {
-            // Check if this node kills a node in the watch list.
-            if (n instanceof MemoryCheckpoint.Single) {
-                LocationIdentity identity = ((MemoryCheckpoint.Single) n).getLocationIdentity();
-                checkWatchList(watchList, identity, b, result, nodeMap, unprocessed);
-            } else if (n instanceof MemoryCheckpoint.Multi) {
-                for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) {
-                    checkWatchList(watchList, identity, b, result, nodeMap, unprocessed);
-                }
-            }
-        }
-    }
-
-    private static void checkWatchList(ArrayList<FloatingReadNode> watchList, LocationIdentity identity, Block b, ArrayList<Node> result, NodeMap<Block> nodeMap, NodeBitMap unprocessed) {
-        assert identity.isMutable();
-        if (identity.isAny()) {
-            for (FloatingReadNode r : watchList) {
-                if (unprocessed.isMarked(r)) {
-                    sortIntoList(r, b, result, nodeMap, unprocessed, null);
-                }
-            }
-            watchList.clear();
-        } else {
-            int index = 0;
-            while (index < watchList.size()) {
-                FloatingReadNode r = watchList.get(index);
-                LocationIdentity locationIdentity = r.getLocationIdentity();
-                assert locationIdentity.isMutable();
-                if (unprocessed.isMarked(r)) {
-                    if (identity.overlaps(locationIdentity)) {
+        private static void checkWatchList(ArrayList<FloatingReadNode> watchList, LocationIdentity identity, Block b, ArrayList<Node> result, NodeMap<Block> nodeMap, NodeBitMap unprocessed) {
+            assert identity.isMutable();
+            if (identity.isAny()) {
+                for (FloatingReadNode r : watchList) {
+                    if (unprocessed.isMarked(r)) {
                         sortIntoList(r, b, result, nodeMap, unprocessed, null);
-                    } else {
-                        ++index;
-                        continue;
                     }
                 }
-                int lastIndex = watchList.size() - 1;
-                watchList.set(index, watchList.get(lastIndex));
-                watchList.remove(lastIndex);
-            }
-        }
-    }
-
-    private static void sortIntoList(Node n, Block b, ArrayList<Node> result, NodeMap<Block> nodeMap, NodeBitMap unprocessed, Node excludeNode) {
-        assert unprocessed.isMarked(n) : n;
-        unprocessed.clear(n);
-
-        assert nodeMap.get(n) == b;
-
-        if (n instanceof PhiNode) {
-            return;
-        }
-
-        for (Node input : n.inputs()) {
-            if (nodeMap.get(input) == b && unprocessed.isMarked(input) && input != excludeNode) {
-                sortIntoList(input, b, result, nodeMap, unprocessed, excludeNode);
-            }
-        }
-
-        if (n instanceof ProxyNode) {
-            // Skip proxy nodes.
-        } else {
-            result.add(n);
-        }
-
-    }
-
-    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) {
-                while (block.getLoopDepth() > earliestBlock.getLoopDepth() && block != earliestBlock.getDominator()) {
-                    block = block.getDominator();
-                    assert checkLatestEarliestRelation(currentNode, earliestBlock, block);
-                }
-            }
-        }
-        assert block != null : currentNode;
-        return block;
-    }
-
-    private static Block calcBlockForUsage(Node node, Node usage, Block startCurrentBlock, NodeMap<Block> currentNodeMap) {
-        assert !(node instanceof PhiNode);
-        Block currentBlock = startCurrentBlock;
-        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) {
-                    currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, mergeBlock.getPredecessors().get(i));
-                }
-            }
-        } else if (usage instanceof AbstractBeginNode) {
-            AbstractBeginNode abstractBeginNode = (AbstractBeginNode) usage;
-            if (abstractBeginNode instanceof StartNode) {
-                currentBlock = currentNodeMap.get(abstractBeginNode);
+                watchList.clear();
             } else {
-                currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, currentNodeMap.get(abstractBeginNode).getDominator());
-            }
-        } else {
-            // All other types of usages: Put the input into the same block as the usage.
-            currentBlock = AbstractControlFlowGraph.commonDominatorTyped(currentBlock, currentNodeMap.get(usage));
-        }
-        return currentBlock;
-    }
-
-    private void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph, NodeBitMap unreachableNodes) {
-
-        BitSet floatingReads = new BitSet(cfg.getBlocks().size());
-
-        // 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);
+                int index = 0;
+                while (index < watchList.size()) {
+                    FloatingReadNode r = watchList.get(index);
+                    LocationIdentity locationIdentity = r.getLocationIdentity();
+                    assert locationIdentity.isMutable();
+                    if (unprocessed.isMarked(r)) {
+                        if (identity.overlaps(locationIdentity)) {
+                            sortIntoList(r, b, result, nodeMap, unprocessed, null);
+                        } else {
+                            ++index;
+                            continue;
+                        }
+                    }
+                    int lastIndex = watchList.size() - 1;
+                    watchList.set(index, watchList.get(lastIndex));
+                    watchList.remove(lastIndex);
                 }
             }
         }
 
-        NodeStack stack = new NodeStack();
+        private static void sortIntoList(Node n, Block b, ArrayList<Node> result, NodeMap<Block> nodeMap, NodeBitMap unprocessed, Node excludeNode) {
+            assert unprocessed.isMarked(n) : n;
+            unprocessed.clear(n);
 
-        // Start analysis with control flow ends.
-        for (Block b : cfg.postOrder()) {
-            FixedNode endNode = b.getEndNode();
-            if (isFixedEnd(endNode)) {
-                stack.push(endNode);
-                nodeToBlock.set(endNode, b);
+            assert nodeMap.get(n) == b;
+
+            if (n instanceof PhiNode) {
+                return;
             }
+
+            for (Node input : n.inputs()) {
+                if (nodeMap.get(input) == b && unprocessed.isMarked(input) && input != excludeNode) {
+                    sortIntoList(input, b, result, nodeMap, unprocessed, excludeNode);
+                }
+            }
+
+            if (n instanceof ProxyNode) {
+                // Skip proxy nodes.
+            } else {
+                result.add(n);
+            }
+
         }
 
-        processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack);
+        @SuppressWarnings("unused")
+        protected void calcLatestBlock(Block earliestBlock, SchedulingStrategy strategy, Node currentNode, NodeMap<Block> currentNodeMap, NodeBitMap unreachableNodes,
+                        LocationIdentity constrainingLocation, BlockMap<ArrayList<FloatingReadNode>> watchListMap, BlockMap<List<Node>> latestBlockToNodesMap, NodeBitMap visited,
+                        boolean immutableGraph) {
+            Block latestBlock = 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;
+                }
+                latestBlock = calcBlockForUsage(currentNode, usage, latestBlock, currentNodeMap);
+            }
 
-        // 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;
+            if (strategy == SchedulingStrategy.FINAL_SCHEDULE || strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS) {
+                while (latestBlock.getLoopDepth() > earliestBlock.getLoopDepth() && latestBlock != earliestBlock.getDominator()) {
+                    latestBlock = latestBlock.getDominator();
+                }
+            }
+
+            if (latestBlock != earliestBlock && latestBlock != earliestBlock.getDominator() && constrainingLocation != null) {
+                latestBlock = checkKillsBetween(earliestBlock, latestBlock, constrainingLocation);
+            }
+
+            selectLatestBlock(currentNode, earliestBlock, latestBlock, currentNodeMap, watchListMap, constrainingLocation, latestBlockToNodesMap);
+        }
+
+        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().get(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 void scheduleEarliestIterative(BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap visited, StructuredGraph graph, NodeBitMap unreachableNodes,
+                        boolean immutableGraph) {
+
+            BitSet floatingReads = new BitSet(cfg.getBlocks().size());
+
+            // 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);
                     }
                 }
             }
 
-            /*
-             * the processing of one loop phi could have marked a previously checked loop phi,
-             * therefore this needs to be iterative.
-             */
-        } while (unmarkedPhi && changed);
+            NodeStack stack = new NodeStack();
 
-        // Check for dead nodes.
-        if (visited.getCounter() < graph.getNodeCount()) {
-            for (Node n : graph.getNodes()) {
-                if (!visited.isMarked(n)) {
-                    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);
+            // Start analysis with control flow ends.
+            for (Block b : cfg.postOrder()) {
+                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 (visited.getCounter() < graph.getNodeCount()) {
+                for (Node n : graph.getNodes()) {
+                    if (!visited.isMarked(n)) {
+                        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);
+                        }
+                    }
+                }
+            }
+
+            // 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);
+        }
+
+        private static boolean isFixedEnd(FixedNode endNode) {
+            return endNode instanceof ControlSplitNode || endNode instanceof ControlSinkNode || endNode instanceof AbstractEndNode;
+        }
+
+        private static void resortEarliestWithinBlock(Block b, BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap unprocessed) {
+            ArrayList<FloatingReadNode> watchList = new ArrayList<>();
+            List<Node> oldList = blockToNodes.get(b);
+            AbstractBeginNode beginNode = b.getBeginNode();
+            for (Node n : oldList) {
+                if (n instanceof FloatingReadNode) {
+                    FloatingReadNode floatingReadNode = (FloatingReadNode) n;
+                    LocationIdentity locationIdentity = floatingReadNode.getLocationIdentity();
+                    MemoryNode lastLocationAccess = floatingReadNode.getLastLocationAccess();
+                    if (locationIdentity.isMutable() && lastLocationAccess != null) {
+                        ValueNode lastAccessLocation = lastLocationAccess.asNode();
+                        if (nodeToBlock.get(lastAccessLocation) == b && lastAccessLocation != beginNode && !(lastAccessLocation instanceof MemoryPhiNode)) {
+                            // This node's last access location is within this block. Add to watch
+                            // list when processing the last access location.
+                        } else {
+                            watchList.add(floatingReadNode);
+                        }
+                    }
+                }
+            }
+
+            ArrayList<Node> newList = new ArrayList<>(oldList.size());
+            assert oldList.get(0) == beginNode;
+            unprocessed.clear(beginNode);
+            newList.add(beginNode);
+            for (int i = 1; i < oldList.size(); ++i) {
+                Node n = oldList.get(i);
+                if (unprocessed.isMarked(n)) {
+                    if (n instanceof MemoryNode) {
+                        if (n instanceof MemoryCheckpoint) {
+                            assert n instanceof FixedNode;
+                            if (watchList.size() > 0) {
+                                // Check whether we need to commit reads from the watch list.
+                                checkWatchList(b, nodeToBlock, unprocessed, newList, watchList, n);
+                            }
+                        }
+                        // Add potential dependent reads to the watch list.
+                        for (Node usage : n.usages()) {
+                            if (usage instanceof FloatingReadNode) {
+                                FloatingReadNode floatingReadNode = (FloatingReadNode) usage;
+                                if (nodeToBlock.get(floatingReadNode) == b && floatingReadNode.getLastLocationAccess() == n && !(n instanceof MemoryPhiNode)) {
+                                    watchList.add(floatingReadNode);
+                                }
+                            }
+                        }
+                    }
+                    assert unprocessed.isMarked(n);
+                    unprocessed.clear(n);
+                    newList.add(n);
+                } else {
+                    // This node was pulled up.
+                    assert !(n instanceof FixedNode) : n;
+                }
+            }
+
+            for (Node n : newList) {
+                unprocessed.mark(n);
+            }
+
+            assert newList.size() == oldList.size();
+            blockToNodes.put(b, newList);
+        }
+
+        private static void addNode(BlockMap<List<Node>> blockToNodes, Block b, Node endNode) {
+            assert !blockToNodes.get(b).contains(endNode) : endNode;
+            blockToNodes.get(b).add(endNode);
+        }
+
+        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) {
+                        PhiNode phiNode = (PhiNode) current;
+                        AbstractMergeNode merge = phiNode.merge();
+                        for (int i = 0; i < merge.forwardEndCount(); ++i) {
+                            Node input = phiNode.valueAt(i);
+                            if (input != null) {
+                                stack.push(input);
+                            }
+                        }
+                    } else if (current instanceof ProxyNode) {
+                        ProxyNode proxyNode = (ProxyNode) current;
+                        for (Node input : proxyNode.inputs()) {
+                            if (input != proxyNode.proxyPoint()) {
+                                stack.push(input);
+                            }
+                        }
+                    } else if (current instanceof FrameState) {
+                        for (Node input : current.inputs()) {
+                            if (input instanceof StateSplit && ((StateSplit) input).stateAfter() == current) {
+                                // Ignore the cycle.
+                            } else {
+                                stack.push(input);
+                            }
+                        }
+                    } 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());
+                            }
+                        }
                     }
                 }
             }
         }
 
-        // 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);
+        public String printScheduleHelper(String desc) {
+            Formatter buf = new Formatter();
+            buf.format("=== %s / %s ===%n", getCFG().getStartBlock().getBeginNode().graph(), desc);
+            for (Block b : getCFG().getBlocks()) {
+                buf.format("==== b: %s (loopDepth: %s). ", b, b.getLoopDepth());
+                buf.format("dom: %s. ", b.getDominator());
+                buf.format("preds: %s. ", b.getPredecessors());
+                buf.format("succs: %s ====%n", b.getSuccessors());
+                BlockMap<LocationSet> killSets = blockToKillSet;
+                if (killSets != null) {
+                    buf.format("X block kills: %n");
+                    if (killSets.get(b) != null) {
+                        for (LocationIdentity locId : killSets.get(b).getCopyAsList()) {
+                            buf.format("X %s killed by %s%n", locId, "dunno anymore");
+                        }
+                    }
                 }
-            }
-        }
 
-        if (!floatingReads.isEmpty()) {
-            for (Block b : cfg.getBlocks()) {
-                if (floatingReads.get(b.getId())) {
-                    resortEarliestWithinBlock(b, blockToNodes, nodeToBlock, visited);
-                }
-            }
-        }
-
-        assert MemoryScheduleVerification.check(cfg.getStartBlock(), blockToNodes);
-    }
-
-    private static boolean isFixedEnd(FixedNode endNode) {
-        return endNode instanceof ControlSplitNode || endNode instanceof ControlSinkNode || endNode instanceof AbstractEndNode;
-    }
-
-    private static void resortEarliestWithinBlock(Block b, BlockMap<List<Node>> blockToNodes, NodeMap<Block> nodeToBlock, NodeBitMap unprocessed) {
-        ArrayList<FloatingReadNode> watchList = new ArrayList<>();
-        List<Node> oldList = blockToNodes.get(b);
-        AbstractBeginNode beginNode = b.getBeginNode();
-        for (Node n : oldList) {
-            if (n instanceof FloatingReadNode) {
-                FloatingReadNode floatingReadNode = (FloatingReadNode) n;
-                LocationIdentity locationIdentity = floatingReadNode.getLocationIdentity();
-                MemoryNode lastLocationAccess = floatingReadNode.getLastLocationAccess();
-                if (locationIdentity.isMutable() && lastLocationAccess != null) {
-                    ValueNode lastAccessLocation = lastLocationAccess.asNode();
-                    if (nodeToBlock.get(lastAccessLocation) == b && lastAccessLocation != beginNode && !(lastAccessLocation instanceof MemoryPhiNode)) {
-                        // This node's last access location is within this block. Add to watch list
-                        // when processing the last access location.
-                    } else {
-                        watchList.add(floatingReadNode);
+                if (blockToNodesMap.get(b) != null) {
+                    for (Node n : nodesFor(b)) {
+                        printNode(n);
+                    }
+                } else {
+                    for (Node n : b.getNodes()) {
+                        printNode(n);
                     }
                 }
             }
+            buf.format("%n");
+            return buf.toString();
         }
 
-        ArrayList<Node> newList = new ArrayList<>(oldList.size());
-        assert oldList.get(0) == beginNode;
-        unprocessed.clear(beginNode);
-        newList.add(beginNode);
-        for (int i = 1; i < oldList.size(); ++i) {
-            Node n = oldList.get(i);
-            if (unprocessed.isMarked(n)) {
-                if (n instanceof MemoryNode) {
-                    if (n instanceof MemoryCheckpoint) {
-                        assert n instanceof FixedNode;
-                        if (watchList.size() > 0) {
-                            // Check whether we need to commit reads from the watch list.
-                            checkWatchList(b, nodeToBlock, unprocessed, newList, watchList, n);
-                        }
-                    }
-                    // Add potential dependent reads to the watch list.
-                    for (Node usage : n.usages()) {
-                        if (usage instanceof FloatingReadNode) {
-                            FloatingReadNode floatingReadNode = (FloatingReadNode) usage;
-                            if (nodeToBlock.get(floatingReadNode) == b && floatingReadNode.getLastLocationAccess() == n && !(n instanceof MemoryPhiNode)) {
-                                watchList.add(floatingReadNode);
-                            }
-                        }
-                    }
+        private static void printNode(Node n) {
+            Formatter buf = new Formatter();
+            buf.format("%s", n);
+            if (n instanceof MemoryCheckpoint.Single) {
+                buf.format(" // kills %s", ((MemoryCheckpoint.Single) n).getLocationIdentity());
+            } else if (n instanceof MemoryCheckpoint.Multi) {
+                buf.format(" // kills ");
+                for (LocationIdentity locid : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) {
+                    buf.format("%s, ", locid);
                 }
-                assert unprocessed.isMarked(n);
-                unprocessed.clear(n);
-                newList.add(n);
-            } else {
-                // This node was pulled up.
-                assert !(n instanceof FixedNode) : n;
+            } else if (n instanceof FloatingReadNode) {
+                FloatingReadNode frn = (FloatingReadNode) n;
+                buf.format(" // from %s", frn.getLocationIdentity());
+                buf.format(", lastAccess: %s", frn.getLastLocationAccess());
+                buf.format(", address: %s", frn.getAddress());
+            } else if (n instanceof GuardNode) {
+                buf.format(", anchor: %s", ((GuardNode) n).getAnchor());
             }
+            Debug.log("%s", buf);
         }
 
-        for (Node n : newList) {
-            unprocessed.mark(n);
+        public ControlFlowGraph getCFG() {
+            return cfg;
         }
 
-        assert newList.size() == oldList.size();
-        blockToNodes.put(b, newList);
-    }
-
-    private static void addNode(BlockMap<List<Node>> blockToNodes, Block b, Node endNode) {
-        assert !blockToNodes.get(b).contains(endNode) : endNode;
-        blockToNodes.get(b).add(endNode);
-    }
-
-    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) {
-                    PhiNode phiNode = (PhiNode) current;
-                    AbstractMergeNode merge = phiNode.merge();
-                    for (int i = 0; i < merge.forwardEndCount(); ++i) {
-                        Node input = phiNode.valueAt(i);
-                        if (input != null) {
-                            stack.push(input);
-                        }
-                    }
-                } else if (current instanceof ProxyNode) {
-                    ProxyNode proxyNode = (ProxyNode) current;
-                    for (Node input : proxyNode.inputs()) {
-                        if (input != proxyNode.proxyPoint()) {
-                            stack.push(input);
-                        }
-                    }
-                } else if (current instanceof FrameState) {
-                    for (Node input : current.inputs()) {
-                        if (input instanceof StateSplit && ((StateSplit) input).stateAfter() == current) {
-                            // Ignore the cycle.
-                        } else {
-                            stack.push(input);
-                        }
-                    }
-                } 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());
-                        }
-                    }
-                }
-            }
+        /**
+         * Gets the nodes in a given block.
+         */
+        public List<Node> nodesFor(Block block) {
+            return blockToNodesMap.get(block);
         }
     }
-
-    public String printScheduleHelper(String desc) {
-        Formatter buf = new Formatter();
-        buf.format("=== %s / %s / %s ===%n", getCFG().getStartBlock().getBeginNode().graph(), selectedStrategy, desc);
-        for (Block b : getCFG().getBlocks()) {
-            buf.format("==== b: %s (loopDepth: %s). ", b, b.getLoopDepth());
-            buf.format("dom: %s. ", b.getDominator());
-            buf.format("preds: %s. ", b.getPredecessors());
-            buf.format("succs: %s ====%n", b.getSuccessors());
-            BlockMap<LocationSet> killSets = blockToKillSet;
-            if (killSets != null) {
-                buf.format("X block kills: %n");
-                if (killSets.get(b) != null) {
-                    for (LocationIdentity locId : killSets.get(b).getCopyAsList()) {
-                        buf.format("X %s killed by %s%n", locId, "dunno anymore");
-                    }
-                }
-            }
-
-            if (blockToNodesMap.get(b) != null) {
-                for (Node n : nodesFor(b)) {
-                    printNode(n);
-                }
-            } else {
-                for (Node n : b.getNodes()) {
-                    printNode(n);
-                }
-            }
-        }
-        buf.format("%n");
-        return buf.toString();
-    }
-
-    private static void printNode(Node n) {
-        Formatter buf = new Formatter();
-        buf.format("%s", n);
-        if (n instanceof MemoryCheckpoint.Single) {
-            buf.format(" // kills %s", ((MemoryCheckpoint.Single) n).getLocationIdentity());
-        } else if (n instanceof MemoryCheckpoint.Multi) {
-            buf.format(" // kills ");
-            for (LocationIdentity locid : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) {
-                buf.format("%s, ", locid);
-            }
-        } else if (n instanceof FloatingReadNode) {
-            FloatingReadNode frn = (FloatingReadNode) n;
-            buf.format(" // from %s", frn.getLocationIdentity());
-            buf.format(", lastAccess: %s", frn.getLastLocationAccess());
-            buf.format(", address: %s", frn.getAddress());
-        } else if (n instanceof GuardNode) {
-            buf.format(", anchor: %s", ((GuardNode) n).getAnchor());
-        }
-        Debug.log("%s", buf);
-    }
-
-    public ControlFlowGraph getCFG() {
-        return cfg;
-    }
-
-    /**
-     * Gets the map from each block to the nodes in the block.
-     */
-    public BlockMap<List<Node>> getBlockToNodesMap() {
-        return blockToNodesMap;
-    }
-
-    public NodeMap<Block> getNodeToBlockMap() {
-        return this.nodeToBlockMap;
-    }
-
-    /**
-     * Gets the nodes in a given block.
-     */
-    public List<Node> nodesFor(Block block) {
-        return blockToNodesMap.get(block);
-    }
 }
--- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/util/GraphOrder.java	Mon Jan 04 00:48:58 2016 +0100
@@ -45,6 +45,7 @@
 import com.oracle.graal.nodes.ProxyNode;
 import com.oracle.graal.nodes.StateSplit;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.VirtualState;
 import com.oracle.graal.nodes.VirtualState.NodeClosure;
@@ -154,9 +155,10 @@
      */
     public static boolean assertSchedulableGraph(final StructuredGraph graph) {
         try {
-            final SchedulePhase schedule = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS);
+            final SchedulePhase schedulePhase = new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS);
             final Map<LoopBeginNode, NodeBitMap> loopEntryStates = Node.newIdentityMap();
-            schedule.apply(graph, false);
+            schedulePhase.apply(graph, false);
+            final ScheduleResult schedule = graph.getLastSchedule();
 
             BlockIteratorClosure<NodeBitMap> closure = new BlockIteratorClosure<NodeBitMap>() {
 
@@ -167,7 +169,7 @@
 
                 @Override
                 protected NodeBitMap processBlock(final Block block, final NodeBitMap currentState) {
-                    final List<Node> list = schedule.getBlockToNodesMap().get(block);
+                    final List<Node> list = graph.getLastSchedule().getBlockToNodesMap().get(block);
 
                     /*
                      * A stateAfter is not valid directly after its associated state split, but
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/BinaryGraphPrinter.java	Mon Jan 04 00:48:58 2016 +0100
@@ -56,6 +56,7 @@
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.ProxyNode;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.VirtualState;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
@@ -141,32 +142,35 @@
         this.channel = channel;
     }
 
-    public void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException {
+    public void print(Graph graph, String title) throws IOException {
         writeByte(BEGIN_GRAPH);
         writePoolObject(title);
-        writeGraph(graph, predefinedSchedule);
+        writeGraph(graph);
         flush();
     }
 
     private void writeGraph(Graph graph) throws IOException {
-        writeGraph(graph, null);
-    }
+        ScheduleResult scheduleResult = null;
+        if (graph instanceof StructuredGraph) {
 
-    private void writeGraph(Graph graph, SchedulePhase predefinedSchedule) throws IOException {
-        SchedulePhase schedule = predefinedSchedule;
-        if (schedule == null) {
-            // Also provide a schedule when an error occurs
-            if (PrintIdealGraphSchedule.getValue() || Debug.contextLookup(Throwable.class) != null) {
-                try {
-                    schedule = new SchedulePhase();
-                    schedule.apply((StructuredGraph) graph);
-                } catch (Throwable t) {
+            StructuredGraph structuredGraph = (StructuredGraph) graph;
+            scheduleResult = structuredGraph.getLastSchedule();
+            if (scheduleResult == null) {
+
+                // Also provide a schedule when an error occurs
+                if (PrintIdealGraphSchedule.getValue() || Debug.contextLookup(Throwable.class) != null) {
+                    try {
+                        SchedulePhase schedule = new SchedulePhase();
+                        schedule.apply(structuredGraph);
+                    } catch (Throwable t) {
+                    }
                 }
+
             }
         }
-        ControlFlowGraph cfg = schedule == null ? null : schedule.getCFG();
-        BlockMap<List<Node>> blockToNodes = schedule == null ? null : schedule.getBlockToNodesMap();
-        NodeMap<Block> nodeToBlocks = schedule == null ? null : schedule.getNodeToBlockMap();
+        ControlFlowGraph cfg = scheduleResult == null ? null : scheduleResult.getCFG();
+        BlockMap<List<Node>> blockToNodes = scheduleResult == null ? null : scheduleResult.getBlockToNodesMap();
+        NodeMap<Block> nodeToBlocks = scheduleResult == null ? null : scheduleResult.getNodeToBlockMap();
         List<Block> blocks = cfg == null ? null : cfg.getBlocks();
         writeNodes(graph, nodeToBlocks, cfg);
         writeBlocks(blocks, blockToNodes);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinter.java	Mon Jan 04 00:48:58 2016 +0100
@@ -57,12 +57,12 @@
 import com.oracle.graal.nodes.FrameState;
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.StateSplit;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.ValuePhiNode;
 import com.oracle.graal.nodes.calc.FloatingNode;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 /**
  * Utility for printing Graal IR at various compilation phases.
@@ -73,7 +73,7 @@
     protected LIR lir;
     protected NodeLIRBuilder nodeLirGenerator;
     protected ControlFlowGraph cfg;
-    protected SchedulePhase schedule;
+    protected ScheduleResult schedule;
     protected ResolvedJavaMethod method;
 
     /**
@@ -564,7 +564,7 @@
         end("intervals");
     }
 
-    public void printSchedule(String message, SchedulePhase theSchedule) {
+    public void printSchedule(String message, ScheduleResult theSchedule) {
         schedule = theSchedule;
         cfg = schedule.getCFG();
         printedNodes = new NodeBitMap(cfg.graph);
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/CFGPrinterObserver.java	Mon Jan 04 00:48:58 2016 +0100
@@ -56,8 +56,8 @@
 import com.oracle.graal.lir.LIR;
 import com.oracle.graal.lir.debug.IntervalDumper;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 /**
  * Observes compilation events and uses {@link CFGPrinter} to produce a control flow graph for the
@@ -188,8 +188,8 @@
                 cfgPrinter.printIntervals(message, delayedIntervals);
                 delayedIntervals = null;
             }
-        } else if (object instanceof SchedulePhase) {
-            cfgPrinter.printSchedule(message, (SchedulePhase) object);
+        } else if (object instanceof ScheduleResult) {
+            cfgPrinter.printSchedule(message, (ScheduleResult) object);
         } else if (object instanceof StructuredGraph) {
             if (cfgPrinter.cfg == null) {
                 StructuredGraph graph = (StructuredGraph) object;
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinter.java	Mon Jan 04 00:48:58 2016 +0100
@@ -28,7 +28,6 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 import com.oracle.graal.graph.Graph;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 interface GraphPrinter extends Closeable {
 
@@ -42,7 +41,7 @@
      * Prints an entire {@link Graph} with the specified title, optionally using short names for
      * nodes.
      */
-    void print(Graph graph, String title, SchedulePhase predefinedSchedule) throws IOException;
+    void print(Graph graph, String title) throws IOException;
 
     /**
      * Ends the current group.
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java	Mon Jan 04 00:48:58 2016 +0100
@@ -57,7 +57,6 @@
 import com.oracle.graal.debug.DebugDumpScope;
 import com.oracle.graal.debug.TTY;
 import com.oracle.graal.graph.Graph;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 //JaCoCo Exclude
 
@@ -202,10 +201,9 @@
                 // Save inline context for next dump.
                 previousInlineContext = inlineContext;
 
-                final SchedulePhase predefinedSchedule = getPredefinedSchedule();
                 try (Scope s = Debug.sandbox("PrintingGraph", null)) {
                     // Finally, output the graph.
-                    printer.print(graph, nextDumpId() + ":" + message, predefinedSchedule);
+                    printer.print(graph, nextDumpId() + ":" + message);
                 } catch (IOException e) {
                     failuresCount++;
                     printer = null;
@@ -248,16 +246,6 @@
         return result;
     }
 
-    private static SchedulePhase getPredefinedSchedule() {
-        SchedulePhase result = null;
-        for (Object o : Debug.context()) {
-            if (o instanceof SchedulePhase) {
-                result = (SchedulePhase) o;
-            }
-        }
-        return result;
-    }
-
     private void openScope(String name, int inlineDepth) {
         String prefix = inlineDepth == 0 ? Thread.currentThread().getName() + ":" : "";
         try {
--- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/IdealGraphPrinter.java	Mon Jan 04 00:48:58 2016 +0100
@@ -48,6 +48,7 @@
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.StateSplit;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.phases.schedule.SchedulePhase;
@@ -89,25 +90,26 @@
         endMethod();
     }
 
-    public void print(Graph graph, String title) {
-        print(graph, title, null);
-    }
-
     /**
      * Prints an entire {@link Graph} with the specified title, optionally using short names for
      * nodes.
      */
     @Override
-    public void print(Graph graph, String title, SchedulePhase predefinedSchedule) {
+    public void print(Graph graph, String title) {
         beginGraph(title);
         Set<Node> noBlockNodes = Node.newSet();
-        SchedulePhase schedule = predefinedSchedule;
-        if (schedule == null && tryToSchedule) {
-            if (PrintIdealGraphSchedule.getValue()) {
-                try {
-                    schedule = new SchedulePhase();
-                    schedule.apply((StructuredGraph) graph);
-                } catch (Throwable t) {
+        ScheduleResult schedule = null;
+        if (graph instanceof StructuredGraph) {
+            StructuredGraph structuredGraph = (StructuredGraph) graph;
+            schedule = structuredGraph.getLastSchedule();
+            if (schedule == null && tryToSchedule) {
+                if (PrintIdealGraphSchedule.getValue()) {
+                    try {
+                        SchedulePhase schedulePhase = new SchedulePhase();
+                        schedulePhase.apply(structuredGraph);
+                        schedule = structuredGraph.getLastSchedule();
+                    } catch (Throwable t) {
+                    }
                 }
             }
         }
--- a/graal/com.oracle.graal.salver/src/com/oracle/graal/salver/dumper/GraphDumper.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.salver/src/com/oracle/graal/salver/dumper/GraphDumper.java	Mon Jan 04 00:48:58 2016 +0100
@@ -53,6 +53,7 @@
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.ProxyNode;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.VirtualState;
 import com.oracle.graal.nodes.cfg.Block;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
@@ -90,13 +91,7 @@
         resolveMethodContext();
 
         try (Scope s = Debug.sandbox(getClass().getSimpleName(), null)) {
-            SchedulePhase predefinedSchedule = null;
-            for (Object obj : Debug.context()) {
-                if (obj instanceof SchedulePhase) {
-                    predefinedSchedule = (SchedulePhase) obj;
-                }
-            }
-            processGraph(graph, msg, predefinedSchedule);
+            processGraph(graph, msg);
         } catch (IOException e) {
             throw e;
         } catch (Throwable e) {
@@ -104,15 +99,24 @@
         }
     }
 
-    private void processGraph(Graph graph, String name, SchedulePhase predefinedSchedule) throws IOException {
-        SchedulePhase schedule = predefinedSchedule;
-        if (schedule == null) {
-            // Also provide a schedule when an error occurs
-            if (PrintIdealGraphSchedule.getValue() || Debug.contextLookup(Throwable.class) != null) {
-                if (graph instanceof StructuredGraph) {
-                    schedule = new SchedulePhase();
-                    schedule.apply((StructuredGraph) graph);
+    private void processGraph(Graph graph, String name) throws IOException {
+
+        ScheduleResult scheduleResult = null;
+        if (graph instanceof StructuredGraph) {
+
+            StructuredGraph structuredGraph = (StructuredGraph) graph;
+            scheduleResult = structuredGraph.getLastSchedule();
+            if (scheduleResult == null) {
+
+                // Also provide a schedule when an error occurs
+                if (PrintIdealGraphSchedule.getValue() || Debug.contextLookup(Throwable.class) != null) {
+                    try {
+                        SchedulePhase schedule = new SchedulePhase();
+                        schedule.apply(structuredGraph);
+                    } catch (Throwable t) {
+                    }
                 }
+
             }
         }
 
@@ -123,19 +127,19 @@
         DataDict graphDict = new DataDict();
         dataDict.put("graph", graphDict);
 
-        processNodes(graphDict, graph.getNodes(), schedule);
+        processNodes(graphDict, graph.getNodes(), scheduleResult);
 
-        if (schedule != null) {
-            ControlFlowGraph cfg = schedule.getCFG();
+        if (scheduleResult != null) {
+            ControlFlowGraph cfg = scheduleResult.getCFG();
             if (cfg != null) {
                 List<Block> blocks = cfg.getBlocks();
-                processBlocks(graphDict, blocks, schedule);
+                processBlocks(graphDict, blocks, scheduleResult);
             }
         }
         serializeAndFlush(createEventDictWithId("graph", dataDict));
     }
 
-    private static void processNodes(DataDict graphDict, NodeIterable<Node> nodes, SchedulePhase schedule) {
+    private static void processNodes(DataDict graphDict, NodeIterable<Node> nodes, ScheduleResult schedule) {
         Map<NodeClass<?>, Integer> classMap = new HashMap<>();
 
         DataList classList = new DataList();
@@ -172,7 +176,7 @@
         }
     }
 
-    private static void processNodeSchedule(DataDict nodeDict, Node node, SchedulePhase schedule) {
+    private static void processNodeSchedule(DataDict nodeDict, Node node, ScheduleResult schedule) {
         NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
         if (nodeToBlock != null) {
             if (nodeToBlock.isNew(node)) {
@@ -195,7 +199,7 @@
         }
     }
 
-    private static void processBlocks(DataDict graphDict, List<Block> blocks, SchedulePhase schedule) {
+    private static void processBlocks(DataDict graphDict, List<Block> blocks, ScheduleResult schedule) {
         BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
         DataList blockList = new DataList();
         graphDict.put("blocks", blockList);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EarlyReadEliminationPhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -25,9 +25,9 @@
 import static com.oracle.graal.compiler.common.GraalOptions.EscapeAnalyzeOnly;
 
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 import com.oracle.graal.phases.tiers.PhaseContext;
 
 public class EarlyReadEliminationPhase extends EffectsPhase<PhaseContext> {
@@ -44,7 +44,7 @@
     }
 
     @Override
-    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) {
+    protected Closure<?> createEffectsClosure(PhaseContext context, ScheduleResult schedule, ControlFlowGraph cfg) {
         assert schedule == null;
         return new ReadEliminationClosure(cfg);
     }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsClosure.java	Mon Jan 04 00:48:58 2016 +0100
@@ -47,6 +47,7 @@
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.ProxyNode;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.ValuePhiNode;
 import com.oracle.graal.nodes.cfg.Block;
@@ -59,12 +60,11 @@
 import com.oracle.graal.phases.graph.ReentrantBlockIterator;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
 import com.oracle.graal.phases.graph.ReentrantBlockIterator.LoopInfo;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
 
     protected final ControlFlowGraph cfg;
-    protected final SchedulePhase schedule;
+    protected final ScheduleResult schedule;
 
     protected final NodeMap<ValueNode> aliases;
     protected final BlockMap<GraphEffectList> blockEffects;
@@ -74,7 +74,7 @@
 
     protected boolean changed;
 
-    public EffectsClosure(SchedulePhase schedule, ControlFlowGraph cfg) {
+    public EffectsClosure(ScheduleResult schedule, ControlFlowGraph cfg) {
         this.schedule = schedule;
         this.cfg = cfg;
         this.aliases = cfg.graph.createNodeMap();
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/EffectsPhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -33,6 +33,7 @@
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.graph.spi.Simplifiable;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.phases.BasePhase;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
@@ -75,14 +76,14 @@
         boolean changed = false;
         for (int iteration = 0; iteration < maxIterations; iteration++) {
             try (Scope s = Debug.scope(isEnabled() ? "iteration " + iteration : null)) {
-                SchedulePhase schedule;
+                ScheduleResult schedule;
                 ControlFlowGraph cfg;
                 if (unscheduled) {
                     schedule = null;
                     cfg = ControlFlowGraph.compute(graph, true, true, false, false);
                 } else {
-                    schedule = new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST);
-                    schedule.apply(graph, false);
+                    new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST).apply(graph, false);
+                    schedule = graph.getLastSchedule();
                     cfg = schedule.getCFG();
                 }
                 try (Scope scheduleScope = Debug.scope("EffectsPhaseWithSchedule", schedule)) {
@@ -127,5 +128,5 @@
         }
     }
 
-    protected abstract Closure<?> createEffectsClosure(PhaseContextT context, SchedulePhase schedule, ControlFlowGraph cfg);
+    protected abstract Closure<?> createEffectsClosure(PhaseContextT context, ScheduleResult schedule, ControlFlowGraph cfg);
 }
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PEReadEliminationClosure.java	Mon Jan 04 00:48:58 2016 +0100
@@ -45,6 +45,7 @@
 import com.oracle.graal.nodes.NamedLocationIdentity;
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.ProxyNode;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.ValueProxyNode;
 import com.oracle.graal.nodes.cfg.Block;
@@ -60,7 +61,6 @@
 import com.oracle.graal.nodes.type.StampTool;
 import com.oracle.graal.nodes.util.GraphUtil;
 import com.oracle.graal.nodes.virtual.VirtualArrayNode;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 import com.oracle.graal.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry;
 
 public class PEReadEliminationClosure extends PartialEscapeClosure<PEReadEliminationBlockState> {
@@ -73,7 +73,7 @@
         }
     }
 
-    public PEReadEliminationClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
+    public PEReadEliminationClosure(ScheduleResult schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
         super(schedule, metaAccess, constantReflection);
     }
 
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapeClosure.java	Mon Jan 04 00:48:58 2016 +0100
@@ -62,6 +62,7 @@
 import com.oracle.graal.nodes.LoopExitNode;
 import com.oracle.graal.nodes.PhiNode;
 import com.oracle.graal.nodes.ProxyNode;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.ValueNode;
 import com.oracle.graal.nodes.ValuePhiNode;
 import com.oracle.graal.nodes.ValueProxyNode;
@@ -74,7 +75,6 @@
 import com.oracle.graal.nodes.spi.VirtualizerTool;
 import com.oracle.graal.nodes.virtual.VirtualObjectNode;
 import com.oracle.graal.phases.common.instrumentation.nodes.InstrumentationNode;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 
 public abstract class PartialEscapeClosure<BlockT extends PartialEscapeBlockState<BlockT>> extends EffectsClosure<BlockT> {
 
@@ -128,7 +128,7 @@
      */
     public static final class Final extends PartialEscapeClosure<PartialEscapeBlockState.Final> {
 
-        public Final(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
+        public Final(ScheduleResult schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
             super(schedule, metaAccess, constantReflection);
         }
 
@@ -143,7 +143,7 @@
         }
     }
 
-    public PartialEscapeClosure(SchedulePhase schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
+    public PartialEscapeClosure(ScheduleResult schedule, MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection) {
         super(schedule, schedule.getCFG());
         this.hasVirtualInputs = schedule.getCFG().graph.createNodeBitMap();
         this.tool = new VirtualizerToolImpl(metaAccess, constantReflection, this);
--- a/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Sat Jan 02 16:49:35 2016 +0100
+++ b/graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/PartialEscapePhase.java	Mon Jan 04 00:48:58 2016 +0100
@@ -29,6 +29,7 @@
 
 import com.oracle.graal.graph.Node;
 import com.oracle.graal.nodes.StructuredGraph;
+import com.oracle.graal.nodes.StructuredGraph.ScheduleResult;
 import com.oracle.graal.nodes.cfg.ControlFlowGraph;
 import com.oracle.graal.nodes.virtual.VirtualObjectNode;
 import com.oracle.graal.options.Option;
@@ -36,7 +37,6 @@
 import com.oracle.graal.options.OptionValue;
 import com.oracle.graal.phases.BasePhase;
 import com.oracle.graal.phases.common.CanonicalizerPhase;
-import com.oracle.graal.phases.schedule.SchedulePhase;
 import com.oracle.graal.phases.tiers.PhaseContext;
 
 public class PartialEscapePhase extends EffectsPhase<PhaseContext> {
@@ -83,7 +83,7 @@
     }
 
     @Override
-    protected Closure<?> createEffectsClosure(PhaseContext context, SchedulePhase schedule, ControlFlowGraph cfg) {
+    protected Closure<?> createEffectsClosure(PhaseContext context, ScheduleResult schedule, ControlFlowGraph cfg) {
         for (VirtualObjectNode virtual : cfg.graph.getNodes(VirtualObjectNode.TYPE)) {
             virtual.resetObjectId();
         }