OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 library dart2js.cps_ir.redundant_join_elimination; | 5 library dart2js.cps_ir.redundant_join_elimination; |
6 | 6 |
7 import 'cps_ir_nodes.dart'; | 7 import 'cps_ir_nodes.dart'; |
8 import 'optimizers.dart'; | 8 import 'optimizers.dart'; |
9 | 9 |
10 /// Eliminates redundant join points. | 10 /// Eliminates redundant join points. |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 // of times each branch is hit. | 102 // of times each branch is hit. |
103 // We know all callers are InvokeContinuations because they are the only | 103 // We know all callers are InvokeContinuations because they are the only |
104 // valid uses of a multi-use continuation. | 104 // valid uses of a multi-use continuation. |
105 int trueHits = 0, falseHits = 0; | 105 int trueHits = 0, falseHits = 0; |
106 InvokeContinuation trueCall, falseCall; | 106 InvokeContinuation trueCall, falseCall; |
107 for (Reference ref = branchCont.firstRef; ref != null; ref = ref.next) { | 107 for (Reference ref = branchCont.firstRef; ref != null; ref = ref.next) { |
108 InvokeContinuation invoke = ref.parent; | 108 InvokeContinuation invoke = ref.parent; |
109 Primitive argument = invoke.arguments[parameterIndex].definition; | 109 Primitive argument = invoke.arguments[parameterIndex].definition; |
110 if (argument is! Constant) return; // Branching condition is unknown. | 110 if (argument is! Constant) return; // Branching condition is unknown. |
111 Constant constant = argument; | 111 Constant constant = argument; |
112 if (isFalsyConstant(constant.value)) { | 112 if (isTruthyConstant(constant.value, strict: branch.isStrictCheck)) { |
| 113 ++trueHits; |
| 114 trueCall = invoke; |
| 115 } else { |
113 ++falseHits; | 116 ++falseHits; |
114 falseCall = invoke; | 117 falseCall = invoke; |
115 } else { | |
116 ++trueHits; | |
117 trueCall = invoke; | |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 // The optimization is now known to be safe, but it only pays off if | 121 // The optimization is now known to be safe, but it only pays off if |
122 // one of the callers can inline its target, since otherwise we end up | 122 // one of the callers can inline its target, since otherwise we end up |
123 // replacing a boolean variable with a labeled break. | 123 // replacing a boolean variable with a labeled break. |
124 // TODO(asgerf): The labeled break might be better? Evaluate. | 124 // TODO(asgerf): The labeled break might be better? Evaluate. |
125 if (!(trueHits == 1 && !trueCall.isEscapingTry || | 125 if (!(trueHits == 1 && !trueCall.isEscapingTry || |
126 falseHits == 1 && !falseCall.isEscapingTry)) { | 126 falseHits == 1 && !falseCall.isEscapingTry)) { |
127 return; | 127 return; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 // Rewrite every invocation of branchCont to call either the true or false | 175 // Rewrite every invocation of branchCont to call either the true or false |
176 // branch directly. Since these were lifted out above branchCont, they are | 176 // branch directly. Since these were lifted out above branchCont, they are |
177 // now in scope. | 177 // now in scope. |
178 // Since trueCont and falseCont were branch targets, they originally | 178 // Since trueCont and falseCont were branch targets, they originally |
179 // had no parameters, and so after the lifting, their parameters are | 179 // had no parameters, and so after the lifting, their parameters are |
180 // exactly the same as those accepted by branchCont. | 180 // exactly the same as those accepted by branchCont. |
181 while (branchCont.firstRef != null) { | 181 while (branchCont.firstRef != null) { |
182 Reference reference = branchCont.firstRef; | 182 Reference reference = branchCont.firstRef; |
183 InvokeContinuation invoke = branchCont.firstRef.parent; | 183 InvokeContinuation invoke = branchCont.firstRef.parent; |
184 Constant condition = invoke.arguments[parameterIndex].definition; | 184 Constant condition = invoke.arguments[parameterIndex].definition; |
185 if (isFalsyConstant(condition.value)) { | 185 if (isTruthyConstant(condition.value, strict: branch.isStrictCheck)) { |
| 186 invoke.continuation.changeTo(trueCont); |
| 187 } else { |
186 invoke.continuation.changeTo(falseCont); | 188 invoke.continuation.changeTo(falseCont); |
187 } else { | |
188 invoke.continuation.changeTo(trueCont); | |
189 } | 189 } |
190 assert(branchCont.firstRef != reference); | 190 assert(branchCont.firstRef != reference); |
191 } | 191 } |
192 | 192 |
193 // Remove the now-unused branchCont continuation. | 193 // Remove the now-unused branchCont continuation. |
194 assert(branchCont.hasNoUses); | 194 assert(branchCont.hasNoUses); |
195 branch.trueContinuation.unlink(); | 195 branch.trueContinuation.unlink(); |
196 branch.falseContinuation.unlink(); | 196 branch.falseContinuation.unlink(); |
197 outerLetCont.continuations.remove(branchCont); | 197 outerLetCont.continuations.remove(branchCont); |
198 if (outerLetCont.continuations.isEmpty) { | 198 if (outerLetCont.continuations.isEmpty) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 }); | 265 }); |
266 } | 266 } |
267 | 267 |
268 processReference(Reference ref) { | 268 processReference(Reference ref) { |
269 Parameter target = renaming[ref.definition]; | 269 Parameter target = renaming[ref.definition]; |
270 if (target != null) { | 270 if (target != null) { |
271 ref.changeTo(target); | 271 ref.changeTo(target); |
272 } | 272 } |
273 } | 273 } |
274 } | 274 } |
OLD | NEW |