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