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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
73 if (!branchCont.hasMultipleUses) return; | 73 if (!branchCont.hasMultipleUses) return; |
74 | 74 |
75 // It might be beneficial to rewrite calls to recursive continuations, | 75 // It might be beneficial to rewrite calls to recursive continuations, |
76 // but we currently do not support this. | 76 // but we currently do not support this. |
77 if (branchCont.isRecursive) return; | 77 if (branchCont.isRecursive) return; |
78 | 78 |
79 // Check that the branching condition is a parameter on the | 79 // Check that the branching condition is a parameter on the |
80 // enclosing continuation. | 80 // enclosing continuation. |
81 // Note: Do not use the parent pointer for this check, because parameters | 81 // Note: Do not use the parent pointer for this check, because parameters |
82 // are temporarily shared between different continuations during this pass. | 82 // are temporarily shared between different continuations during this pass. |
83 Primitive condition = branch.condition.definition; | 83 Primitive condition = branch.condition; |
84 int parameterIndex = branchCont.parameters.indexOf(condition); | 84 int parameterIndex = branchCont.parameters.indexOf(condition); |
85 if (parameterIndex == -1) return; | 85 if (parameterIndex == -1) return; |
86 | 86 |
87 // Check that all callers hit a fixed branch, and count the number | 87 // Check that all callers hit a fixed branch, and count the number |
88 // of times each branch is hit. | 88 // of times each branch is hit. |
89 // We know all callers are InvokeContinuations because they are the only | 89 // We know all callers are InvokeContinuations because they are the only |
90 // valid uses of a multi-use continuation. | 90 // valid uses of a multi-use continuation. |
91 int trueHits = 0, falseHits = 0; | 91 int trueHits = 0, falseHits = 0; |
92 InvokeContinuation trueCall, falseCall; | 92 InvokeContinuation trueCall, falseCall; |
93 for (Reference ref = branchCont.firstRef; ref != null; ref = ref.next) { | 93 for (Reference ref = branchCont.firstRef; ref != null; ref = ref.next) { |
94 InvokeContinuation invoke = ref.parent; | 94 InvokeContinuation invoke = ref.parent; |
95 Primitive argument = invoke.arguments[parameterIndex].definition; | 95 Primitive argument = invoke.argument(parameterIndex); |
96 if (argument is! Constant) return; // Branching condition is unknown. | 96 if (argument is! Constant) return; // Branching condition is unknown. |
97 Constant constant = argument; | 97 Constant constant = argument; |
98 if (isTruthyConstant(constant.value, strict: branch.isStrictCheck)) { | 98 if (isTruthyConstant(constant.value, strict: branch.isStrictCheck)) { |
99 ++trueHits; | 99 ++trueHits; |
100 trueCall = invoke; | 100 trueCall = invoke; |
101 } else { | 101 } else { |
102 ++falseHits; | 102 ++falseHits; |
103 falseCall = invoke; | 103 falseCall = invoke; |
104 } | 104 } |
105 } | 105 } |
(...skipping 26 matching lines...) Expand all Loading... | |
132 // continuations. [AlphaRenamer] will clean up at the end of this pass. | 132 // continuations. [AlphaRenamer] will clean up at the end of this pass. |
133 LetCont outerLetCont = branchCont.parent; | 133 LetCont outerLetCont = branchCont.parent; |
134 while (branchCont.body is LetCont) { | 134 while (branchCont.body is LetCont) { |
135 LetCont innerLetCont = branchCont.body; | 135 LetCont innerLetCont = branchCont.body; |
136 for (Continuation innerCont in innerLetCont.continuations) { | 136 for (Continuation innerCont in innerLetCont.continuations) { |
137 innerCont.parameters.addAll(branchCont.parameters); | 137 innerCont.parameters.addAll(branchCont.parameters); |
138 for (Reference ref = innerCont.firstRef; ref != null; ref = ref.next) { | 138 for (Reference ref = innerCont.firstRef; ref != null; ref = ref.next) { |
139 Expression use = ref.parent; | 139 Expression use = ref.parent; |
140 if (use is InvokeContinuation) { | 140 if (use is InvokeContinuation) { |
141 for (Parameter param in branchCont.parameters) { | 141 for (Parameter param in branchCont.parameters) { |
142 use.arguments.add(new Reference<Primitive>(param)..parent = use); | 142 use.argumentRefs.add(new Reference<Primitive>(param)..parent = use ); |
Siggi Cherem (dart-lang)
2016/02/29 18:00:00
80 col
asgerf
2016/03/01 12:06:59
Done.
| |
143 } | 143 } |
144 } else { | 144 } else { |
145 // The branch will be eliminated, so don't worry about updating it. | 145 // The branch will be eliminated, so don't worry about updating it. |
146 assert(use == branch); | 146 assert(use == branch); |
147 } | 147 } |
148 } | 148 } |
149 } | 149 } |
150 innerLetCont.remove(); | 150 innerLetCont.remove(); |
151 innerLetCont.insertAbove(outerLetCont); | 151 innerLetCont.insertAbove(outerLetCont); |
152 } | 152 } |
153 | 153 |
154 assert(branchCont.body == branch); | 154 assert(branchCont.body == branch); |
155 | 155 |
156 Continuation trueCont = branch.trueContinuation.definition; | 156 Continuation trueCont = branch.trueContinuation; |
157 Continuation falseCont = branch.falseContinuation.definition; | 157 Continuation falseCont = branch.falseContinuation; |
158 | 158 |
159 assert(branchCont != trueCont); | 159 assert(branchCont != trueCont); |
160 assert(branchCont != falseCont); | 160 assert(branchCont != falseCont); |
161 | 161 |
162 // Rewrite every invocation of branchCont to call either the true or false | 162 // Rewrite every invocation of branchCont to call either the true or false |
163 // branch directly. Since these were lifted out above branchCont, they are | 163 // branch directly. Since these were lifted out above branchCont, they are |
164 // now in scope. | 164 // now in scope. |
165 // Since trueCont and falseCont were branch targets, they originally | 165 // Since trueCont and falseCont were branch targets, they originally |
166 // had no parameters, and so after the lifting, their parameters are | 166 // had no parameters, and so after the lifting, their parameters are |
167 // exactly the same as those accepted by branchCont. | 167 // exactly the same as those accepted by branchCont. |
168 while (branchCont.firstRef != null) { | 168 while (branchCont.firstRef != null) { |
169 Reference reference = branchCont.firstRef; | 169 Reference reference = branchCont.firstRef; |
170 InvokeContinuation invoke = branchCont.firstRef.parent; | 170 InvokeContinuation invoke = branchCont.firstRef.parent; |
171 Constant condition = invoke.arguments[parameterIndex].definition; | 171 Constant condition = invoke.argument(parameterIndex); |
172 if (isTruthyConstant(condition.value, strict: branch.isStrictCheck)) { | 172 if (isTruthyConstant(condition.value, strict: branch.isStrictCheck)) { |
173 invoke.continuation.changeTo(trueCont); | 173 invoke.continuationRef.changeTo(trueCont); |
174 } else { | 174 } else { |
175 invoke.continuation.changeTo(falseCont); | 175 invoke.continuationRef.changeTo(falseCont); |
176 } | 176 } |
177 assert(branchCont.firstRef != reference); | 177 assert(branchCont.firstRef != reference); |
178 } | 178 } |
179 | 179 |
180 // Remove the now-unused branchCont continuation. | 180 // Remove the now-unused branchCont continuation. |
181 assert(branchCont.hasNoUses); | 181 assert(branchCont.hasNoUses); |
182 branch.trueContinuation.unlink(); | 182 branch.trueContinuationRef.unlink(); |
183 branch.falseContinuation.unlink(); | 183 branch.falseContinuationRef.unlink(); |
184 outerLetCont.continuations.remove(branchCont); | 184 outerLetCont.continuations.remove(branchCont); |
185 if (outerLetCont.continuations.isEmpty) { | 185 if (outerLetCont.continuations.isEmpty) { |
186 outerLetCont.remove(); | 186 outerLetCont.remove(); |
187 } | 187 } |
188 | 188 |
189 // We may have created new redundant join points in the two branches. | 189 // We may have created new redundant join points in the two branches. |
190 enqueueContinuation(trueCont); | 190 enqueueContinuation(trueCont); |
191 enqueueContinuation(falseCont); | 191 enqueueContinuation(falseCont); |
192 } | 192 } |
193 | 193 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 }); | 251 }); |
252 } | 252 } |
253 | 253 |
254 processReference(Reference ref) { | 254 processReference(Reference ref) { |
255 Parameter target = renaming[ref.definition]; | 255 Parameter target = renaming[ref.definition]; |
256 if (target != null) { | 256 if (target != null) { |
257 ref.changeTo(target); | 257 ref.changeTo(target); |
258 } | 258 } |
259 } | 259 } |
260 } | 260 } |
OLD | NEW |