Mercurial > hg > graal-compiler
changeset 23250:e67189aa2e06
Refactor scheduling phase to be without state and produce a ScheduleResult that is stored in the graph.
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 && 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, immutableGraph); + BlockMap<List<Node>> latestBlockToNodesMap = new BlockMap<>(cfg); - scheduleEarliestIterative(earliestBlockToNodesMap, currentNodeMap, visited, graph, unreachableNodes); - 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; + latestBlockToNodesMap.get(latestBlock).add(currentNode); + } + + 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; + } + } } - lastBlock = currentBlock; + return true; } - return lastBlock; - } + 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; - 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; + 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; } - } else if (n instanceof MemoryCheckpoint.Multi) { - for (LocationIdentity identity : ((MemoryCheckpoint.Multi) n).getLocationIdentities()) { + } + + 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; + 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); } - 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); + + 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); + } + + } - // 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); + @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); } + + 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); } - processStack(cfg, blockToNodes, nodeToBlock, visited, floatingReads, stack); + 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); + } + } + } - // 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); + NodeStack stack = new NodeStack(); + + // 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; } - } 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); + } } } } - /* - * the processing of one loop phi could have marked a previously checked loop phi, - * therefore this needs to be iterative. - */ - } while (unmarkedPhi && changed); + // 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); + } - // 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); + 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); - } - } - } - - 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); - } + 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"); } } } - 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); - } + if (blockToNodesMap.get(b) != null) { + for (Node n : nodesFor(b)) { + printNode(n); } } 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()); - } + 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 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) { + + StructuredGraph structuredGraph = (StructuredGraph) graph; + scheduleResult = structuredGraph.getLastSchedule(); + if (scheduleResult == null) { - 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) { + // 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(); }