Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 /** | 5 /** |
| 6 * The [LiveRange] class covers a range where an instruction is live. | 6 * The [LiveRange] class covers a range where an instruction is live. |
| 7 */ | 7 */ |
| 8 class LiveRange { | 8 class LiveRange { |
| 9 final int start; | 9 final int start; |
| 10 // [end] is not final because it can be updated due to loops. | 10 // [end] is not final because it can be updated due to loops. |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 174 assert(!loopMarkers.containsKey(header)); | 174 assert(!loopMarkers.containsKey(header)); |
| 175 loopMarkers[header] = id; | 175 loopMarkers[header] = id; |
| 176 } | 176 } |
| 177 | 177 |
| 178 void removeLoopMarker(HBasicBlock header) { | 178 void removeLoopMarker(HBasicBlock header) { |
| 179 assert(loopMarkers.containsKey(header)); | 179 assert(loopMarkers.containsKey(header)); |
| 180 loopMarkers.remove(header); | 180 loopMarkers.remove(header); |
| 181 } | 181 } |
| 182 | 182 |
| 183 bool isEmpty() => liveInstructions.isEmpty() && loopMarkers.isEmpty(); | 183 bool isEmpty() => liveInstructions.isEmpty() && loopMarkers.isEmpty(); |
| 184 bool contains(HInstruction instruction) => liveInstructions.containsKey(instru ction); | 184 bool contains(HInstruction instruction) => |
| 185 liveInstructions.containsKey(instruction); | |
| 185 String toString() => liveInstructions.toString(); | 186 String toString() => liveInstructions.toString(); |
| 186 } | 187 } |
| 187 | 188 |
| 188 /** | 189 /** |
| 189 * Builds the live intervals of each instruction. The algorithm visits | 190 * Builds the live intervals of each instruction. The algorithm visits |
| 190 * the graph post-dominator tree to find the last uses of an | 191 * the graph post-dominator tree to find the last uses of an |
| 191 * instruction, and computes the liveIns of each basic block. | 192 * instruction, and computes the liveIns of each basic block. |
| 192 */ | 193 */ |
| 193 class SsaLiveIntervalBuilder extends HBaseVisitor { | 194 class SsaLiveIntervalBuilder extends HBaseVisitor { |
| 194 final Compiler compiler; | 195 final Compiler compiler; |
| 196 final Set<HInstruction> generateAtUseSite; | |
| 195 | 197 |
| 196 /** | 198 /** |
| 197 * A counter to assign start and end ids to live ranges. The initial | 199 * A counter to assign start and end ids to live ranges. The initial |
| 198 * value is not relevant. Note that instructionId goes downward to ease | 200 * value is not relevant. Note that instructionId goes downward to ease |
| 199 * reasoning about live ranges (the first instruction of a graph has | 201 * reasoning about live ranges (the first instruction of a graph has |
| 200 * the lowest id). | 202 * the lowest id). |
| 201 */ | 203 */ |
| 202 int instructionId = 0; | 204 int instructionId = 0; |
| 203 | 205 |
| 204 /** | 206 /** |
| 205 * The liveIns of basic blocks. | 207 * The liveIns of basic blocks. |
| 206 */ | 208 */ |
| 207 final Map<HBasicBlock, LiveEnvironment> liveInstructions; | 209 final Map<HBasicBlock, LiveEnvironment> liveInstructions; |
| 208 | 210 |
| 209 /** | 211 /** |
| 210 * The live intervals of instructions. | 212 * The live intervals of instructions. |
| 211 */ | 213 */ |
| 212 final Map<HInstruction, LiveInterval> liveIntervals; | 214 final Map<HInstruction, LiveInterval> liveIntervals; |
| 213 | 215 |
| 214 SsaLiveIntervalBuilder(this.compiler) | 216 SsaLiveIntervalBuilder(this.compiler, this.generateAtUseSite) |
| 215 : liveInstructions = new Map<HBasicBlock, LiveEnvironment>(), | 217 : liveInstructions = new Map<HBasicBlock, LiveEnvironment>(), |
| 216 liveIntervals = new Map<HInstruction, LiveInterval>(); | 218 liveIntervals = new Map<HInstruction, LiveInterval>(); |
| 217 | 219 |
| 218 void visitGraph(HGraph graph) { | 220 void visitGraph(HGraph graph) { |
| 219 visitPostDominatorTree(graph); | 221 visitPostDominatorTree(graph); |
| 220 if (!liveInstructions[graph.entry].isEmpty()) { | 222 if (!liveInstructions[graph.entry].isEmpty()) { |
| 221 compiler.internalError('LiveIntervalBuilder', | 223 compiler.internalError('LiveIntervalBuilder', |
| 222 node: compiler.currentElement.parseNode(compiler)); | 224 node: compiler.currentElement.parseNode(compiler)); |
| 223 } | 225 } |
| 224 } | 226 } |
| 225 | 227 |
| 228 void markInputsAsLiveInEnvironment(HInstruction instruction, | |
| 229 LiveEnvironment environment) { | |
| 230 for (int i = 0, len = instruction.inputs.length; i < len; i++) { | |
| 231 markAsLiveInEnvironment(instruction.inputs[i], environment); | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 void markAsLiveInEnvironment(HInstruction instruction, | |
| 236 LiveEnvironment environment) { | |
| 237 if (environment.contains(instruction)) return; | |
| 238 environment.add(instruction, instructionId); | |
| 239 // HPhis are treated specially. | |
|
ngeoffray
2012/08/17 13:04:53
Do you remember if removing the HPhi check trigger
floitsch
2012/10/03 09:22:39
Sorry. Don't remember.
| |
| 240 if (generateAtUseSite.contains(instruction) && instruction is !HPhi) { | |
| 241 markInputsAsLiveInEnvironment(instruction, environment); | |
| 242 } | |
| 243 } | |
| 244 | |
| 226 void visitBasicBlock(HBasicBlock block) { | 245 void visitBasicBlock(HBasicBlock block) { |
| 227 LiveEnvironment environment = new LiveEnvironment(liveIntervals, instruction Id); | 246 LiveEnvironment environment = |
| 247 new LiveEnvironment(liveIntervals, instructionId); | |
| 228 | 248 |
| 229 // Add to the environment the liveIn of its successor, as well as | 249 // Add to the environment the liveIn of its successor, as well as |
| 230 // the inputs of the phis of the successor that flow from this block. | 250 // the inputs of the phis of the successor that flow from this block. |
| 231 for (int i = 0; i < block.successors.length; i++) { | 251 for (int i = 0; i < block.successors.length; i++) { |
| 232 HBasicBlock successor = block.successors[i]; | 252 HBasicBlock successor = block.successors[i]; |
| 233 LiveEnvironment successorEnv = liveInstructions[successor]; | 253 LiveEnvironment successorEnv = liveInstructions[successor]; |
| 234 if (successorEnv !== null) { | 254 if (successorEnv !== null) { |
| 235 environment.mergeWith(successorEnv); | 255 environment.mergeWith(successorEnv); |
| 236 } else { | 256 } else { |
| 237 environment.addLoopMarker(successor, instructionId); | 257 environment.addLoopMarker(successor, instructionId); |
| 238 } | 258 } |
| 239 | 259 |
| 240 int index = successor.predecessors.indexOf(block); | 260 int index = successor.predecessors.indexOf(block); |
| 241 for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) { | 261 for (HPhi phi = successor.phis.first; phi != null; phi = phi.next) { |
| 242 environment.add(phi.inputs[index], instructionId); | 262 markAsLiveInEnvironment(phi.inputs[index], environment); |
| 243 } | 263 } |
| 244 } | 264 } |
| 245 | 265 |
| 246 // Iterate over all instructions to remove an instruction from the | 266 // Iterate over all instructions to remove an instruction from the |
| 247 // environment and add its inputs. | 267 // environment and add its inputs. |
| 248 HInstruction instruction = block.last; | 268 HInstruction instruction = block.last; |
| 249 while (instruction != null) { | 269 while (instruction != null) { |
| 250 environment.remove(instruction, instructionId); | 270 environment.remove(instruction, instructionId); |
| 251 for (int i = 0, len = instruction.inputs.length; i < len; i++) { | 271 markInputsAsLiveInEnvironment(instruction, environment); |
| 252 environment.add(instruction.inputs[i], instructionId); | |
| 253 } | |
| 254 instruction = instruction.previous; | 272 instruction = instruction.previous; |
| 255 instructionId--; | 273 instructionId--; |
| 256 } | 274 } |
| 257 | 275 |
| 258 // We just remove the phis from the environment. The inputs of the | 276 // We just remove the phis from the environment. The inputs of the |
| 259 // phis will be put in the environment of the predecessors. | 277 // phis will be put in the environment of the predecessors. |
| 260 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) { | 278 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) { |
| 261 environment.remove(phi, instructionId); | 279 environment.remove(phi, instructionId); |
| 262 } | 280 } |
| 263 | 281 |
| (...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 if (!needsName(input)) { | 640 if (!needsName(input)) { |
| 623 names.addAssignment(predecessor, input, phi); | 641 names.addAssignment(predecessor, input, phi); |
| 624 } else { | 642 } else { |
| 625 names.addCopy(predecessor, input, phi); | 643 names.addCopy(predecessor, input, phi); |
| 626 } | 644 } |
| 627 } | 645 } |
| 628 | 646 |
| 629 namer.allocateName(phi); | 647 namer.allocateName(phi); |
| 630 } | 648 } |
| 631 } | 649 } |
| OLD | NEW |