| 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 * Instead of emitting each SSA instruction with a temporary variable | 6 * Instead of emitting each SSA instruction with a temporary variable |
| 7 * mark instructions that can be emitted at their use-site. | 7 * mark instructions that can be emitted at their use-site. |
| 8 * For example, in: | 8 * For example, in: |
| 9 * t0 = 4; | 9 * t0 = 4; |
| 10 * t1 = 3; | 10 * t1 = 3; |
| 11 * t2 = add(t0, t1); | 11 * t2 = add(t0, t1); |
| 12 * t0 and t1 would be marked and the resulting code would then be: | 12 * t0 and t1 would be marked and the resulting code would then be: |
| 13 * t2 = add(4, 3); | 13 * t2 = add(4, 3); |
| 14 */ | 14 */ |
| 15 class SsaInstructionMerger extends HBaseVisitor { | 15 class SsaInstructionMerger extends HBaseVisitor { |
| 16 HTypeMap types; | 16 HTypeMap types; |
| 17 List<HInstruction> expectedInputs; | 17 List<HInstruction> expectedInputs; |
| 18 Set<HInstruction> generateAtUseSite; | 18 Set<HInstruction> generateAtUseSite; |
| 19 | 19 |
| 20 void markAsGenerateAtUseSite(HInstruction instruction) { | 20 void markAsGenerateAtUseSite(HInstruction instruction) { |
| 21 assert(!instruction.isStatement(types)); | 21 assert(!instruction.isJsStatement(types)); |
| 22 generateAtUseSite.add(instruction); | 22 generateAtUseSite.add(instruction); |
| 23 } | 23 } |
| 24 | 24 |
| 25 SsaInstructionMerger(this.types, this.generateAtUseSite); | 25 SsaInstructionMerger(this.types, this.generateAtUseSite); |
| 26 | 26 |
| 27 void visitGraph(HGraph graph) { | 27 void visitGraph(HGraph graph) { |
| 28 visitDominatorTree(graph); | 28 visitDominatorTree(graph); |
| 29 } | 29 } |
| 30 | 30 |
| 31 void analyzeInput(HInstruction input) { | 31 void analyzeInput(HInstruction input) { |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 for (HInstruction instruction = block.last.previous; | 145 for (HInstruction instruction = block.last.previous; |
| 146 instruction !== null; | 146 instruction !== null; |
| 147 instruction = instruction.previous) { | 147 instruction = instruction.previous) { |
| 148 if (generateAtUseSite.contains(instruction)) { | 148 if (generateAtUseSite.contains(instruction)) { |
| 149 continue; | 149 continue; |
| 150 } | 150 } |
| 151 if (instruction.isCodeMotionInvariant()) { | 151 if (instruction.isCodeMotionInvariant()) { |
| 152 markAsGenerateAtUseSite(instruction); | 152 markAsGenerateAtUseSite(instruction); |
| 153 continue; | 153 continue; |
| 154 } | 154 } |
| 155 if (instruction.isStatement(types)) { | 155 if (instruction.isJsStatement(types)) { |
| 156 expectedInputs.clear(); | 156 expectedInputs.clear(); |
| 157 } | 157 } |
| 158 // See if the current instruction is the next non-trivial | 158 // See if the current instruction is the next non-trivial |
| 159 // expected input. | 159 // expected input. |
| 160 if (findInInputsAndPopNonMatching(instruction)) { | 160 if (findInInputsAndPopNonMatching(instruction)) { |
| 161 tryGenerateAtUseSite(instruction); | 161 tryGenerateAtUseSite(instruction); |
| 162 } else { | 162 } else { |
| 163 assert(expectedInputs.isEmpty()); | 163 assert(expectedInputs.isEmpty()); |
| 164 } | 164 } |
| 165 instruction.accept(this); | 165 instruction.accept(this); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 179 * Detect control flow arising from short-circuit logical and | 179 * Detect control flow arising from short-circuit logical and |
| 180 * conditional operators, and prepare the program to be generated | 180 * conditional operators, and prepare the program to be generated |
| 181 * using these operators instead of nested ifs and boolean variables. | 181 * using these operators instead of nested ifs and boolean variables. |
| 182 */ | 182 */ |
| 183 class SsaConditionMerger extends HGraphVisitor { | 183 class SsaConditionMerger extends HGraphVisitor { |
| 184 final HTypeMap types; | 184 final HTypeMap types; |
| 185 Set<HInstruction> generateAtUseSite; | 185 Set<HInstruction> generateAtUseSite; |
| 186 Set<HInstruction> controlFlowOperators; | 186 Set<HInstruction> controlFlowOperators; |
| 187 | 187 |
| 188 void markAsGenerateAtUseSite(HInstruction instruction) { | 188 void markAsGenerateAtUseSite(HInstruction instruction) { |
| 189 assert(!instruction.isStatement(types)); | 189 assert(!instruction.isJsStatement(types)); |
| 190 generateAtUseSite.add(instruction); | 190 generateAtUseSite.add(instruction); |
| 191 } | 191 } |
| 192 | 192 |
| 193 SsaConditionMerger(this.types, | 193 SsaConditionMerger(this.types, |
| 194 this.generateAtUseSite, | 194 this.generateAtUseSite, |
| 195 this.controlFlowOperators); | 195 this.controlFlowOperators); |
| 196 | 196 |
| 197 void visitGraph(HGraph graph) { | 197 void visitGraph(HGraph graph) { |
| 198 visitPostDominatorTree(graph); | 198 visitPostDominatorTree(graph); |
| 199 } | 199 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 | 275 |
| 276 if (end == null) return; | 276 if (end == null) return; |
| 277 if (end.phis.isEmpty()) return; | 277 if (end.phis.isEmpty()) return; |
| 278 if (end.phis.first !== end.phis.last) return; | 278 if (end.phis.first !== end.phis.last) return; |
| 279 HBasicBlock elseBlock = startIf.elseBlock; | 279 HBasicBlock elseBlock = startIf.elseBlock; |
| 280 | 280 |
| 281 if (end.predecessors[1] !== elseBlock) return; | 281 if (end.predecessors[1] !== elseBlock) return; |
| 282 HPhi phi = end.phis.first; | 282 HPhi phi = end.phis.first; |
| 283 HInstruction thenInput = phi.inputs[0]; | 283 HInstruction thenInput = phi.inputs[0]; |
| 284 HInstruction elseInput = phi.inputs[1]; | 284 HInstruction elseInput = phi.inputs[1]; |
| 285 if (thenInput.isStatement(types) || elseInput.isStatement(types)) return; | 285 if (thenInput.isJsStatement(types) || |
| 286 elseInput.isJsStatement(types)) return; |
| 286 | 287 |
| 287 if (hasAnyStatement(elseBlock, elseInput)) return; | 288 if (hasAnyStatement(elseBlock, elseInput)) return; |
| 288 assert(elseBlock.successors.length == 1); | 289 assert(elseBlock.successors.length == 1); |
| 289 assert(end.predecessors.length == 2); | 290 assert(end.predecessors.length == 2); |
| 290 | 291 |
| 291 HBasicBlock thenBlock = startIf.thenBlock; | 292 HBasicBlock thenBlock = startIf.thenBlock; |
| 292 // Skip trivial goto blocks. | 293 // Skip trivial goto blocks. |
| 293 while (thenBlock.successors[0] != end && thenBlock.first is HGoto) { | 294 while (thenBlock.successors[0] != end && thenBlock.first is HGoto) { |
| 294 thenBlock = thenBlock.successors[0]; | 295 thenBlock = thenBlock.successors[0]; |
| 295 } | 296 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 } | 337 } |
| 337 | 338 |
| 338 // If [thenInput] is defined in the first predecessor, then it is only used | 339 // If [thenInput] is defined in the first predecessor, then it is only used |
| 339 // by [phi] and can be generated at use site. | 340 // by [phi] and can be generated at use site. |
| 340 if (thenInput.block === end.predecessors[0]) { | 341 if (thenInput.block === end.predecessors[0]) { |
| 341 assert(thenInput.usedBy.length == 1); | 342 assert(thenInput.usedBy.length == 1); |
| 342 markAsGenerateAtUseSite(thenInput); | 343 markAsGenerateAtUseSite(thenInput); |
| 343 } | 344 } |
| 344 } | 345 } |
| 345 } | 346 } |
| OLD | NEW |