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 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 6 import '../common/names.dart' show Selectors; | 6 import '../common/names.dart' show Selectors; |
| 7 import '../common/tasks.dart' show CompilerTask; | 7 import '../common/tasks.dart' show CompilerTask; |
| 8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
| 9 import '../constants/constant_system.dart'; | 9 import '../constants/constant_system.dart'; |
| 10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 45 super(backend.compiler.measurer); | 45 super(backend.compiler.measurer); |
| 46 | 46 |
| 47 String get name => 'SSA optimizer'; | 47 String get name => 'SSA optimizer'; |
| 48 | 48 |
| 49 Compiler get compiler => backend.compiler; | 49 Compiler get compiler => backend.compiler; |
| 50 | 50 |
| 51 void optimize(CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { | 51 void optimize(CodegenWorkItem work, HGraph graph, ClosedWorld closedWorld) { |
| 52 void runPhase(OptimizationPhase phase) { | 52 void runPhase(OptimizationPhase phase) { |
| 53 measureSubtask(phase.name, () => phase.visitGraph(graph)); | 53 measureSubtask(phase.name, () => phase.visitGraph(graph)); |
| 54 backend.tracer.traceGraph(phase.name, graph); | 54 backend.tracer.traceGraph(phase.name, graph); |
| 55 assert(graph.isValid()); | 55 assert(graph.isValid(), 'Graph not valid after ${phase.name}'); |
| 56 } | 56 } |
| 57 | 57 |
| 58 bool trustPrimitives = compiler.options.trustPrimitives; | 58 bool trustPrimitives = compiler.options.trustPrimitives; |
| 59 CodegenRegistry registry = work.registry; | 59 CodegenRegistry registry = work.registry; |
| 60 Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 60 Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| 61 SsaCodeMotion codeMotion; | 61 SsaCodeMotion codeMotion; |
| 62 measure(() { | 62 measure(() { |
| 63 List<OptimizationPhase> phases = <OptimizationPhase>[ | 63 List<OptimizationPhase> phases = <OptimizationPhase>[ |
| 64 // Run trivial instruction simplification first to optimize | 64 // Run trivial instruction simplification first to optimize |
| 65 // some patterns useful for type conversion. | 65 // some patterns useful for type conversion. |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 704 return null; | 704 return null; |
| 705 } | 705 } |
| 706 | 706 |
| 707 HInstruction visitIdentity(HIdentity node) { | 707 HInstruction visitIdentity(HIdentity node) { |
| 708 HInstruction newInstruction = handleIdentityCheck(node); | 708 HInstruction newInstruction = handleIdentityCheck(node); |
| 709 return newInstruction == null ? super.visitIdentity(node) : newInstruction; | 709 return newInstruction == null ? super.visitIdentity(node) : newInstruction; |
| 710 } | 710 } |
| 711 | 711 |
| 712 void simplifyCondition( | 712 void simplifyCondition( |
| 713 HBasicBlock block, HInstruction condition, bool value) { | 713 HBasicBlock block, HInstruction condition, bool value) { |
| 714 condition.dominatedUsers(block.first).forEach((user) { | 714 // `excludePhiOutEdges: true` prevents replacing a partially dominated phi |
| 715 HInstruction newCondition = graph.addConstantBool(value, closedWorld); | 715 // node input with a constant. This tends to add unnecessary assignments, by |
| 716 user.changeUse(condition, newCondition); | 716 // transforming the following, which has phi(false, x), |
| 717 }); | 717 // |
| 718 // if (x) { init(); x = false; } | |
| 719 // | |
| 720 // into this, which has phi(false, false) | |
| 721 // | |
| 722 // if (x) { init(); x = false; } else { x = false; } | |
| 723 // | |
| 724 // which is further simplifed to: | |
| 725 // | |
| 726 // if (x) { init(); } | |
| 727 // ... | |
| 728 // x = false; | |
| 729 // | |
| 730 // This is mostly harmless (if a little confusing) but does cause a lot of | |
| 731 // `x = false;` copies to be inserted when a loop body has many continue | |
| 732 // statements or ends with a switch. | |
|
Emily Fortuna
2017/04/03 20:48:46
👏👏👏 (that's a hand clapping emoji in case it's not
| |
| 733 var uses = | |
| 734 DominatedUses.of(condition, block.first, excludePhiOutEdges: true); | |
| 735 if (uses.isEmpty) return; | |
| 736 uses.replaceWith(graph.addConstantBool(value, closedWorld)); | |
| 718 } | 737 } |
| 719 | 738 |
| 720 HInstruction visitIf(HIf node) { | 739 HInstruction visitIf(HIf node) { |
| 721 HInstruction condition = node.condition; | 740 HInstruction condition = node.condition; |
| 722 if (condition.isConstant()) return node; | 741 if (condition.isConstant()) return node; |
| 723 bool isNegated = condition is HNot; | 742 bool isNegated = condition is HNot; |
| 724 | 743 |
| 725 if (isNegated) { | 744 if (isNegated) { |
| 726 condition = condition.inputs[0]; | 745 condition = condition.inputs[0]; |
| 727 } else { | 746 } else { |
| (...skipping 863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1591 // Find the index of the single live predecessor if it exists. | 1610 // Find the index of the single live predecessor if it exists. |
| 1592 int indexOfLive = -1; | 1611 int indexOfLive = -1; |
| 1593 for (int i = 0; i < predecessors.length; i++) { | 1612 for (int i = 0; i < predecessors.length; i++) { |
| 1594 if (predecessors[i].isLive) { | 1613 if (predecessors[i].isLive) { |
| 1595 if (indexOfLive >= 0) continue L; | 1614 if (indexOfLive >= 0) continue L; |
| 1596 indexOfLive = i; | 1615 indexOfLive = i; |
| 1597 } | 1616 } |
| 1598 } | 1617 } |
| 1599 // Run through the phis of the block and replace them with their input | 1618 // Run through the phis of the block and replace them with their input |
| 1600 // that comes from the only live predecessor if that dominates the phi. | 1619 // that comes from the only live predecessor if that dominates the phi. |
| 1620 // | |
| 1621 // TODO(sra): If the input is directly in the only live predecessor, it | |
| 1622 // might be possible to move it into [block] (e.g. all its inputs are | |
| 1623 // dominating.) | |
| 1601 block.forEachPhi((HPhi phi) { | 1624 block.forEachPhi((HPhi phi) { |
| 1602 HInstruction replacement = | 1625 HInstruction replacement = |
| 1603 (indexOfLive >= 0) ? phi.inputs[indexOfLive] : zapInstruction; | 1626 (indexOfLive >= 0) ? phi.inputs[indexOfLive] : zapInstruction; |
| 1604 if (replacement.dominates(phi)) { | 1627 if (replacement.dominates(phi)) { |
| 1605 block.rewrite(phi, replacement); | 1628 block.rewrite(phi, replacement); |
| 1606 block.removePhi(phi); | 1629 block.removePhi(phi); |
| 1607 } | 1630 } |
| 1608 }); | 1631 }); |
| 1609 } | 1632 } |
| 1610 } | 1633 } |
| (...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2139 void visitGraph(HGraph graph) { | 2162 void visitGraph(HGraph graph) { |
| 2140 visitDominatorTree(graph); | 2163 visitDominatorTree(graph); |
| 2141 } | 2164 } |
| 2142 | 2165 |
| 2143 // Update users of [input] that are dominated by [:dominator.first:] | 2166 // Update users of [input] that are dominated by [:dominator.first:] |
| 2144 // to use [TypeKnown] of [input] instead. As the type information depends | 2167 // to use [TypeKnown] of [input] instead. As the type information depends |
| 2145 // on the control flow, we mark the inserted [HTypeKnown] nodes as | 2168 // on the control flow, we mark the inserted [HTypeKnown] nodes as |
| 2146 // non-movable. | 2169 // non-movable. |
| 2147 void insertTypePropagationForDominatedUsers( | 2170 void insertTypePropagationForDominatedUsers( |
| 2148 HBasicBlock dominator, HInstruction input, TypeMask convertedType) { | 2171 HBasicBlock dominator, HInstruction input, TypeMask convertedType) { |
| 2149 Setlet<HInstruction> dominatedUsers = input.dominatedUsers(dominator.first); | 2172 DominatedUses dominatedUses = DominatedUses.of(input, dominator.first); |
| 2150 if (dominatedUsers.isEmpty) return; | 2173 if (dominatedUses.isEmpty) return; |
| 2151 | 2174 |
| 2152 HTypeKnown newInput = new HTypeKnown.pinned(convertedType, input); | 2175 HTypeKnown newInput = new HTypeKnown.pinned(convertedType, input); |
| 2153 dominator.addBefore(dominator.first, newInput); | 2176 dominator.addBefore(dominator.first, newInput); |
| 2154 dominatedUsers.forEach((HInstruction user) { | 2177 dominatedUses.replaceWith(newInput); |
| 2155 user.changeUse(input, newInput); | |
| 2156 }); | |
| 2157 } | 2178 } |
| 2158 | 2179 |
| 2159 void visitIs(HIs instruction) { | 2180 void visitIs(HIs instruction) { |
| 2160 ResolutionDartType type = instruction.typeExpression; | 2181 ResolutionDartType type = instruction.typeExpression; |
| 2161 if (!instruction.isRawCheck) { | 2182 if (!instruction.isRawCheck) { |
| 2162 return; | 2183 return; |
| 2163 } else if (type.isTypedef) { | 2184 } else if (type.isTypedef) { |
| 2164 return; | 2185 return; |
| 2165 } | 2186 } |
| 2166 ResolutionInterfaceType interfaceType = type; | 2187 ResolutionInterfaceType interfaceType = type; |
| (...skipping 621 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2788 | 2809 |
| 2789 keyedValues.forEach((receiver, values) { | 2810 keyedValues.forEach((receiver, values) { |
| 2790 result.keyedValues[receiver] = | 2811 result.keyedValues[receiver] = |
| 2791 new Map<HInstruction, HInstruction>.from(values); | 2812 new Map<HInstruction, HInstruction>.from(values); |
| 2792 }); | 2813 }); |
| 2793 | 2814 |
| 2794 result.nonEscapingReceivers.addAll(nonEscapingReceivers); | 2815 result.nonEscapingReceivers.addAll(nonEscapingReceivers); |
| 2795 return result; | 2816 return result; |
| 2796 } | 2817 } |
| 2797 } | 2818 } |
| OLD | NEW |