# HG changeset patch # User Bernhard Urban # Date 1384791750 -3600 # Node ID 6a7b6dcb7f67eb3228dd8452be1e2659c88fb4a1 # Parent d3f5a5b1d99cb2791b57bb21f8c6ebb6c8e39c4e NewMemoryAwareScheduling: fix out of loop for FloatingReadNodes diff -r d3f5a5b1d99c -r 6a7b6dcb7f67 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 Nov 18 17:02:48 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/schedule/SchedulePhase.java Mon Nov 18 17:22:30 2013 +0100 @@ -494,17 +494,21 @@ break; case LATEST: case LATEST_OUT_OF_LOOPS: - if (memsched == MemoryScheduling.OPTIMAL && node instanceof FloatingReadNode && ((FloatingReadNode) node).location().getLocationIdentity() != FINAL_LOCATION) { + boolean scheduleRead = memsched == MemoryScheduling.OPTIMAL && node instanceof FloatingReadNode && ((FloatingReadNode) node).location().getLocationIdentity() != FINAL_LOCATION; + if (scheduleRead) { block = optimalBlock((FloatingReadNode) node, strategy); } else { block = latestBlock(node, strategy); - if (block == null) { - block = earliestBlock; - } else if (strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS && !(node instanceof VirtualObjectNode)) { - // schedule at the latest position possible in the outermost loop possible - block = scheduleOutOfLoops(node, block, earliestBlock); - } } + if (block == null) { + block = earliestBlock; + } else if (strategy == SchedulingStrategy.LATEST_OUT_OF_LOOPS && !(node instanceof VirtualObjectNode)) { + // schedule at the latest position possible in the outermost loop possible + block = scheduleOutOfLoops(node, block, earliestBlock); + } + + assert !scheduleRead || forKillLocation(((FloatingReadNode) node).getLastLocationAccess()).dominates(block) : "out of loop violated memory semantics for " + node + ". moved to " + + block + ", but upper bound is " + forKillLocation(((FloatingReadNode) node).getLastLocationAccess()); break; default: throw new GraalInternalError("unknown scheduling strategy"); @@ -565,24 +569,7 @@ if (lastKill.equals(upperBound)) { // assign node to the block which kills the location - boolean outOfLoop = false; - - // schedule read out of the loop if possible, in terms of killMaps and earliest - // schedule - if (currentBlock != earliestBlock && previousBlock != earliestBlock) { - Block t = currentBlock; - while (t.getLoop() != null && t.getDominator() != null && earliestBlock.dominates(t)) { - Block dom = t.getDominator(); - if (dom.getLoopDepth() < currentBlock.getLoopDepth() && blockToKillMap.get(dom).get(locid) == upperBound && earliestBlock.dominates(dom)) { - printIterations(iterations, "moved out of loop, from " + currentBlock + " to " + dom); - previousBlock = currentBlock = dom; - outOfLoop = true; - } - t = dom; - } - } - - if (!outOfLoop && previousBlock.getBeginNode() instanceof MergeNode) { + if (previousBlock.getBeginNode() instanceof MergeNode) { // merges kill locations right at the beginning of a block. if a merge is the // killing node, we assign it to the dominating block. @@ -722,6 +709,16 @@ return earliest; } + /** + * Schedules a node out of loop based on its earliest schedule. Note that this movement is only + * valid if it's done for every other node in the schedule, otherwise this movement is + * not valid. + * + * @param n Node to schedule + * @param latestBlock latest possible schedule for {@code n} + * @param earliest earliest possible schedule for {@code n} + * @return block schedule for {@code n} which is not inside a loop (if possible) + */ private static Block scheduleOutOfLoops(Node n, Block latestBlock, Block earliest) { if (latestBlock == null) { throw new SchedulingError("no latest : %s", n);