Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 class SsaPhiEliminator extends HGraphVisitor { | 5 class SsaPhiEliminator extends HGraphVisitor { |
| 6 HBasicBlock entry; | 6 HBasicBlock entry; |
| 7 HBasicBlock currentBlock; | 7 HBasicBlock currentBlock; |
| 8 | 8 |
| 9 visitGraph(HGraph graph) { | 9 visitGraph(HGraph graph) { |
| 10 entry = graph.entry; | 10 entry = graph.entry; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 118 // We propagate the type of the phi to the load instruction rather | 118 // We propagate the type of the phi to the load instruction rather |
| 119 // than the local because we may end up sharing a single local | 119 // than the local because we may end up sharing a single local |
| 120 // between different phis of different types. | 120 // between different phis of different types. |
| 121 HLoad load = new HLoad(local, phi.type); | 121 HLoad load = new HLoad(local, phi.type); |
| 122 loads.add(load); | 122 loads.add(load); |
| 123 | 123 |
| 124 currentBlock.addAtEntry(load); | 124 currentBlock.addAtEntry(load); |
| 125 currentBlock.rewrite(phi, load); | 125 currentBlock.rewrite(phi, load); |
| 126 currentBlock.removePhi(phi); | 126 currentBlock.removePhi(phi); |
| 127 | 127 |
| 128 if (!currentBlock.isLoopHeader() || !hasLoopPhiAsInput(stores, loads)) { | 128 if (currentBlock.isLoopHeader()) { |
| 129 if (!hasLoopPhiAsInput(stores, loads) && | |
| 130 !isPhiUsedInLoop(stores, load)) { | |
| 131 load.setGenerateAtUseSite(); | |
| 132 } | |
| 133 } else { | |
| 129 load.setGenerateAtUseSite(); | 134 load.setGenerateAtUseSite(); |
| 130 } | 135 } |
| 131 } | 136 } |
| 132 | 137 |
| 138 bool isPhiUsedInLoop(List<HStore> stores, HLoad load) { | |
| 139 // [stores] contains the stores of a specific phi. | |
| 140 // [load] is the replacement of the loop phi. | |
| 141 // We assume a loop header only has two predecessors: the entry | |
| 142 // and the backedge. | |
| 143 assert(stores.length == 2); | |
| 144 HStore update = stores[1]; | |
| 145 for (HInstruction instruction in load.usedBy) { | |
| 146 if (instruction.block.parentLoopHeader != update.block.parentLoopHeader) { | |
|
floitsch
2011/12/22 16:30:56
What about nested loops? Then the parentLoopHeader
| |
| 147 continue; | |
| 148 } | |
| 149 if (instruction.block.id > update.block.id) return true; | |
| 150 if (instruction.block == update.block && isBefore(update, instruction)) { | |
| 151 return true; | |
| 152 } | |
| 153 } | |
| 154 return false; | |
| 155 } | |
| 156 | |
| 157 bool isBefore(HInstruction first, HInstruction second) { | |
| 158 assert(first.block == second.block); | |
| 159 HInstruction current = first.block.first; | |
| 160 while (current != null) { | |
| 161 if (current == first) return true; | |
| 162 if (current == second) return false; | |
| 163 current = current.next; | |
| 164 } | |
| 165 // In case the instructions are out of the block. | |
| 166 return false; | |
| 167 } | |
| 168 | |
| 133 bool hasLoopPhiAsInput(List<HStore> stores, List<HLoad> loads) { | 169 bool hasLoopPhiAsInput(List<HStore> stores, List<HLoad> loads) { |
| 134 // [stores] contains the stores of a specific phi. | 170 // [stores] contains the stores of a specific phi. |
| 135 // [loads] contains the phis that were converted to loads. | 171 // [loads] contains the phis that were converted to loads. |
| 136 assert(currentBlock.isLoopHeader()); | 172 assert(currentBlock.isLoopHeader()); |
| 137 for (HStore store in stores) { | 173 for (HStore store in stores) { |
| 138 HInstruction value = store.value; | 174 HInstruction value = store.value; |
| 139 if (value is HPhi && value.block == currentBlock) { | 175 if (value is HPhi && value.block == currentBlock) { |
| 140 return true; | 176 return true; |
| 141 } else if (value is HLoad && loads.indexOf(value) != -1) { | 177 } else if (value is HLoad && loads.indexOf(value) != -1) { |
| 142 return true; | 178 return true; |
| 143 } | 179 } |
| 144 } | 180 } |
| 145 return false; | 181 return false; |
| 146 } | 182 } |
| 147 } | 183 } |
| OLD | NEW |