Index: dart/frog/leg/ssa/phi_eliminator.dart |
=================================================================== |
--- dart/frog/leg/ssa/phi_eliminator.dart (revision 2759) |
+++ dart/frog/leg/ssa/phi_eliminator.dart (working copy) |
@@ -125,11 +125,47 @@ |
currentBlock.rewrite(phi, load); |
currentBlock.removePhi(phi); |
- if (!currentBlock.isLoopHeader() || !hasLoopPhiAsInput(stores, loads)) { |
+ if (currentBlock.isLoopHeader()) { |
+ if (!hasLoopPhiAsInput(stores, loads) && |
+ !isPhiUsedInLoop(stores, load)) { |
+ load.setGenerateAtUseSite(); |
+ } |
+ } else { |
load.setGenerateAtUseSite(); |
} |
} |
+ bool isPhiUsedInLoop(List<HStore> stores, HLoad load) { |
+ // [stores] contains the stores of a specific phi. |
+ // [load] is the replacement of the loop phi. |
+ // We assume a loop header only has two predecessors: the entry |
+ // and the backedge. |
+ assert(stores.length == 2); |
+ HStore update = stores[1]; |
+ for (HInstruction instruction in load.usedBy) { |
+ if (instruction.block.parentLoopHeader != update.block.parentLoopHeader) { |
floitsch
2011/12/22 16:30:56
What about nested loops? Then the parentLoopHeader
|
+ continue; |
+ } |
+ if (instruction.block.id > update.block.id) return true; |
+ if (instruction.block == update.block && isBefore(update, instruction)) { |
+ return true; |
+ } |
+ } |
+ return false; |
+ } |
+ |
+ bool isBefore(HInstruction first, HInstruction second) { |
+ assert(first.block == second.block); |
+ HInstruction current = first.block.first; |
+ while (current != null) { |
+ if (current == first) return true; |
+ if (current == second) return false; |
+ current = current.next; |
+ } |
+ // In case the instructions are out of the block. |
+ return false; |
+ } |
+ |
bool hasLoopPhiAsInput(List<HStore> stores, List<HLoad> loads) { |
// [stores] contains the stores of a specific phi. |
// [loads] contains the phis that were converted to loads. |