| 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 interface OptimizationPhase { | 5 interface OptimizationPhase { |
| 6 String get name(); | 6 String get name(); |
| 7 void visitGraph(HGraph graph); | 7 void visitGraph(HGraph graph); |
| 8 } | 8 } |
| 9 | 9 |
| 10 class SsaOptimizerTask extends CompilerTask { | 10 class SsaOptimizerTask extends CompilerTask { |
| 11 SsaOptimizerTask(Compiler compiler) : super(compiler); | 11 SsaOptimizerTask(Compiler compiler) : super(compiler); |
| 12 String get name() => 'SSA optimizer'; | 12 String get name() => 'SSA optimizer'; |
| 13 | 13 |
| 14 void runPhases(HGraph graph, List<OptimizationPhase> phases) { | 14 void runPhases(HGraph graph, List<OptimizationPhase> phases) { |
| 15 for (OptimizationPhase phase in phases) { | 15 for (OptimizationPhase phase in phases) { |
| 16 phase.visitGraph(graph); | 16 phase.visitGraph(graph); |
| 17 compiler.tracer.traceGraph(phase.name, graph); | 17 compiler.tracer.traceGraph(phase.name, graph); |
| 18 } | 18 } |
| 19 } | 19 } |
| 20 | 20 |
| 21 void optimize(WorkItem work, HGraph graph) { | 21 void optimize(WorkItem work, HGraph graph) { |
| 22 measure(() { | 22 measure(() { |
| 23 List<OptimizationPhase> phases = <OptimizationPhase>[ | 23 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 24 new SsaTypePropagator(compiler), |
| 25 new SsaCheckInserter(compiler), |
| 24 new SsaConstantFolder(compiler), | 26 new SsaConstantFolder(compiler), |
| 25 new SsaRedundantPhiEliminator(), | 27 new SsaRedundantPhiEliminator(), |
| 26 new SsaDeadPhiEliminator(), | 28 new SsaDeadPhiEliminator(), |
| 27 new SsaGlobalValueNumberer(compiler), | 29 new SsaGlobalValueNumberer(compiler), |
| 28 new SsaCodeMotion(), | 30 new SsaCodeMotion(), |
| 29 new SsaDeadCodeEliminator()]; | 31 new SsaDeadCodeEliminator()]; |
| 30 runPhases(graph, phases); | 32 runPhases(graph, phases); |
| 31 }); | 33 }); |
| 32 } | 34 } |
| 33 | 35 |
| 34 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { | 36 bool trySpeculativeOptimizations(WorkItem work, HGraph graph) { |
| 35 return measure(() { | 37 return measure(() { |
| 36 // Run the phases that will generate type guards. We must also run | 38 // Run the phases that will generate type guards. We must also run |
| 37 // [SsaCheckInserter] because the type propagator also propagates | 39 // [SsaCheckInserter] because the type propagator also propagates |
| 38 // types non-speculatively. For example, it propagates the type | 40 // types non-speculatively. For example, it propagates the type |
| 39 // array for a call to the List constructor. | 41 // array for a call to the List constructor. |
| 40 List<OptimizationPhase> phases = <OptimizationPhase>[ | 42 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 41 new SsaTypePropagator(compiler), | 43 new SsaSpeculativeTypePropagator(compiler), |
| 42 new SsaTypeGuardBuilder(compiler, work), | 44 new SsaTypeGuardBuilder(compiler, work), |
| 43 new SsaCheckInserter(compiler)]; | 45 new SsaCheckInserter(compiler)]; |
| 44 runPhases(graph, phases); | 46 runPhases(graph, phases); |
| 45 return !work.guards.isEmpty(); | 47 return !work.guards.isEmpty(); |
| 46 }); | 48 }); |
| 47 } | 49 } |
| 48 | 50 |
| 49 void prepareForSpeculativeOptimizations(WorkItem work, HGraph graph) { | 51 void prepareForSpeculativeOptimizations(WorkItem work, HGraph graph) { |
| 50 measure(() { | 52 measure(() { |
| 51 // In order to generate correct code for the bailout version, we did not | 53 // In order to generate correct code for the bailout version, we did not |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 HInstruction replacement = instruction.accept(this); | 90 HInstruction replacement = instruction.accept(this); |
| 89 if (replacement !== instruction) { | 91 if (replacement !== instruction) { |
| 90 if (!replacement.isInBasicBlock()) { | 92 if (!replacement.isInBasicBlock()) { |
| 91 // The constant folding can return an instruction that is already | 93 // The constant folding can return an instruction that is already |
| 92 // part of the graph (like an input), so we only add the replacement | 94 // part of the graph (like an input), so we only add the replacement |
| 93 // if necessary. | 95 // if necessary. |
| 94 block.addAfter(instruction, replacement); | 96 block.addAfter(instruction, replacement); |
| 95 } | 97 } |
| 96 block.rewrite(instruction, replacement); | 98 block.rewrite(instruction, replacement); |
| 97 block.remove(instruction); | 99 block.remove(instruction); |
| 98 // Because the constant folder runs after type propagation, we | 100 // If the replacement instruction does not know its type yet, |
| 99 // must update the type of this instruction manually. Later | 101 // use the type of the instruction. |
| 100 // phases can then optimize this instruction based on its | 102 if (!replacement.type.isKnown()) { |
| 101 // type. | 103 replacement.type = instruction.type; |
| 102 replacement.updateType(); | 104 } |
| 103 } | 105 } |
| 104 instruction = next; | 106 instruction = next; |
| 105 } | 107 } |
| 106 } | 108 } |
| 107 | 109 |
| 108 HInstruction visitInstruction(HInstruction node) { | 110 HInstruction visitInstruction(HInstruction node) { |
| 109 return node; | 111 return node; |
| 110 } | 112 } |
| 111 | 113 |
| 112 HInstruction visitBoolify(HBoolify node) { | 114 HInstruction visitBoolify(HBoolify node) { |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 290 } | 292 } |
| 291 | 293 |
| 292 HIntegerCheck insertIntegerCheck(HInstruction node, HInstruction value) { | 294 HIntegerCheck insertIntegerCheck(HInstruction node, HInstruction value) { |
| 293 HIntegerCheck check = new HIntegerCheck(value); | 295 HIntegerCheck check = new HIntegerCheck(value); |
| 294 node.block.addBefore(node, check); | 296 node.block.addBefore(node, check); |
| 295 return check; | 297 return check; |
| 296 } | 298 } |
| 297 | 299 |
| 298 void visitIndex(HIndex node) { | 300 void visitIndex(HIndex node) { |
| 299 if (!node.builtin) return; | 301 if (!node.builtin) return; |
| 302 if (node.index is HBoundsCheck) return; |
| 300 HInstruction index = insertIntegerCheck(node, node.index); | 303 HInstruction index = insertIntegerCheck(node, node.index); |
| 301 index = insertBoundsCheck(node, node.receiver, index); | 304 index = insertBoundsCheck(node, node.receiver, index); |
| 302 HIndex newInstruction = new HIndex(node.target, node.receiver, index); | 305 HIndex newInstruction = new HIndex(node.target, node.receiver, index); |
| 303 node.block.addBefore(node, newInstruction); | 306 node.block.addBefore(node, newInstruction); |
| 304 node.block.rewrite(node, newInstruction); | 307 node.block.rewrite(node, newInstruction); |
| 305 node.block.remove(node); | 308 node.block.remove(node); |
| 306 } | 309 } |
| 307 | 310 |
| 308 void visitIndexAssign(HIndexAssign node) { | 311 void visitIndexAssign(HIndexAssign node) { |
| 309 if (!node.builtin) return; | 312 if (!node.builtin) return; |
| 313 if (node.index is HBoundsCheck) return; |
| 310 HInstruction index = insertIntegerCheck(node, node.index); | 314 HInstruction index = insertIntegerCheck(node, node.index); |
| 311 index = insertBoundsCheck(node, node.receiver, index); | 315 index = insertBoundsCheck(node, node.receiver, index); |
| 312 HIndexAssign newInstruction = | 316 HIndexAssign newInstruction = |
| 313 new HIndexAssign(node.target, node.receiver, index, node.value); | 317 new HIndexAssign(node.target, node.receiver, index, node.value); |
| 314 node.block.addBefore(node, newInstruction); | 318 node.block.addBefore(node, newInstruction); |
| 315 node.block.rewrite(node, newInstruction); | 319 node.block.rewrite(node, newInstruction); |
| 316 node.block.remove(node); | 320 node.block.remove(node); |
| 317 } | 321 } |
| 318 } | 322 } |
| 319 | 323 |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 700 } | 704 } |
| 701 } | 705 } |
| 702 if (!canBeMoved) continue; | 706 if (!canBeMoved) continue; |
| 703 | 707 |
| 704 // This is safe because we are running after GVN. | 708 // This is safe because we are running after GVN. |
| 705 // TODO(ngeoffray): ensure GVN has been run. | 709 // TODO(ngeoffray): ensure GVN has been run. |
| 706 set_.add(current); | 710 set_.add(current); |
| 707 } | 711 } |
| 708 } | 712 } |
| 709 } | 713 } |
| OLD | NEW |