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; |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 | 229 |
230 // We check that the structure is the following: | 230 // We check that the structure is the following: |
231 // If | 231 // If |
232 // / \ | 232 // / \ |
233 // / \ | 233 // / \ |
234 // 1 expr goto | 234 // 1 expr goto |
235 // goto / | 235 // goto / |
236 // \ / | 236 // \ / |
237 // \ / | 237 // \ / |
238 // phi(expr, true|false) | 238 // phi(expr, true|false) |
| 239 // |
| 240 // and the same for nested nodes: |
| 241 // |
| 242 // If |
| 243 // / \ |
| 244 // / \ |
| 245 // 1 expr1 \ |
| 246 // If \ |
| 247 // / \ \ |
| 248 // / \ goto |
| 249 // 1 expr2 | |
| 250 // goto goto | |
| 251 // \ / | |
| 252 // \ / | |
| 253 // phi1(expr2, true|false) |
| 254 // \ | |
| 255 // \ | |
| 256 // phi(phi1, true|false) |
| 257 |
239 if (end == null) return; | 258 if (end == null) return; |
240 if (end.phis.isEmpty()) return; | 259 if (end.phis.isEmpty()) return; |
241 if (end.phis.first !== end.phis.last) return; | 260 if (end.phis.first !== end.phis.last) return; |
242 HBasicBlock elseBlock = startIf.elseBlock; | 261 HBasicBlock elseBlock = startIf.elseBlock; |
243 | 262 |
244 if (end.predecessors[1] !== elseBlock) return; | 263 if (end.predecessors[1] !== elseBlock) return; |
245 HPhi phi = end.phis.first; | 264 HPhi phi = end.phis.first; |
246 HInstruction thenInput = phi.inputs[0]; | 265 HInstruction thenInput = phi.inputs[0]; |
247 HInstruction elseInput = phi.inputs[1]; | 266 HInstruction elseInput = phi.inputs[1]; |
248 if (thenInput.isStatement || elseInput.isStatement) return; | 267 if (thenInput.isStatement || elseInput.isStatement) return; |
249 | 268 |
250 if (hasAnyStatement(elseBlock, elseInput)) return; | 269 if (hasAnyStatement(elseBlock, elseInput)) return; |
251 assert(elseBlock.successors.length == 1); | 270 assert(elseBlock.successors.length == 1); |
252 assert(end.predecessors.length == 2); | 271 assert(end.predecessors.length == 2); |
253 | 272 |
254 HBasicBlock thenBlock = startIf.thenBlock; | 273 HBasicBlock thenBlock = startIf.thenBlock; |
255 // Skip trivial goto blocks. | 274 // Skip trivial goto blocks. |
256 while (thenBlock.successors[0] != end && thenBlock.first is HGoto) { | 275 while (thenBlock.successors[0] != end && thenBlock.first is HGoto) { |
257 thenBlock = thenBlock.successors[0]; | 276 thenBlock = thenBlock.successors[0]; |
258 } | 277 } |
259 | 278 |
260 // If the [thenBlock] is already a control flow operation, and does not | 279 // If the [thenBlock] is already a control flow operation, and does not |
261 // have any statement and its join block is [end], we can emit a | 280 // have any statement and its join block is [end], we can emit a |
262 // sequence of control flow operation. | 281 // sequence of control flow operation. |
263 if (controlFlowOperators.contains(thenBlock.last)) { | 282 if (controlFlowOperators.contains(thenBlock.last)) { |
264 HIf otherIf = thenBlock.last; | 283 HIf otherIf = thenBlock.last; |
265 if (otherIf.joinBlock !== end) return; | 284 if (otherIf.joinBlock !== end) { |
| 285 // This could be a join block that just feeds into our join block. |
| 286 HBasicBlock otherJoin = otherIf.joinBlock; |
| 287 if (otherJoin.successors.length != 1) return; |
| 288 if (otherJoin.successors[0] != end) return; |
| 289 if (otherJoin.phis.isEmpty()) return; |
| 290 if (otherJoin.phis.first !== otherJoin.phis.last) return; |
| 291 HPhi otherPhi = otherJoin.phis.first; |
| 292 if (thenInput != otherPhi) return; |
| 293 if (elseInput != otherPhi.inputs[1]) return; |
| 294 } |
266 if (hasAnyStatement(thenBlock, otherIf)) return; | 295 if (hasAnyStatement(thenBlock, otherIf)) return; |
267 } else { | 296 } else { |
268 if (end.predecessors[0] !== thenBlock) return; | 297 if (end.predecessors[0] !== thenBlock) return; |
269 if (hasAnyStatement(thenBlock, thenInput)) return; | 298 if (hasAnyStatement(thenBlock, thenInput)) return; |
270 assert(thenBlock.successors.length == 1); | 299 assert(thenBlock.successors.length == 1); |
271 } | 300 } |
272 | 301 |
273 // From now on, we have recognized a control flow operation built from | 302 // From now on, we have recognized a control flow operation built from |
274 // the builder. Mark the if instruction as such. | 303 // the builder. Mark the if instruction as such. |
275 controlFlowOperators.add(startIf); | 304 controlFlowOperators.add(startIf); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 }; | 399 }; |
371 } | 400 } |
372 | 401 |
373 class JSBinaryOperatorPrecedence { | 402 class JSBinaryOperatorPrecedence { |
374 final int left; | 403 final int left; |
375 final int right; | 404 final int right; |
376 const JSBinaryOperatorPrecedence(this.left, this.right); | 405 const JSBinaryOperatorPrecedence(this.left, this.right); |
377 // All binary operators (excluding assignment) are left associative. | 406 // All binary operators (excluding assignment) are left associative. |
378 int get precedence() => left; | 407 int get precedence() => left; |
379 } | 408 } |
OLD | NEW |