| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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.shrinking_reductions; | 5 library dart2js.cps_ir.shrinking_reductions; |
| 6 | 6 |
| 7 import 'cps_ir_nodes.dart'; | 7 import 'cps_ir_nodes.dart'; |
| 8 import 'optimizers.dart'; | 8 import 'optimizers.dart'; |
| 9 import 'cps_fragment.dart'; | 9 import 'cps_fragment.dart'; |
| 10 import '../constants/values.dart' as values; | 10 import '../constants/values.dart' as values; |
| (...skipping 385 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 396 // constant time by using union-find data structure. | 396 // constant time by using union-find data structure. |
| 397 for (int i = 0; i < cont.parameters.length; i++) { | 397 for (int i = 0; i < cont.parameters.length; i++) { |
| 398 if (invoke.arguments[i].definition != cont.parameters[i]) { | 398 if (invoke.arguments[i].definition != cont.parameters[i]) { |
| 399 return false; | 399 return false; |
| 400 } | 400 } |
| 401 } | 401 } |
| 402 | 402 |
| 403 return true; | 403 return true; |
| 404 } | 404 } |
| 405 | 405 |
| 406 Expression _unfoldDeadRefinements(Expression node) { |
| 407 while (node is LetPrim) { |
| 408 LetPrim let = node; |
| 409 Primitive prim = let.primitive; |
| 410 if (prim.hasAtLeastOneUse || prim is! Refinement) return node; |
| 411 node = node.next; |
| 412 } |
| 413 return node; |
| 414 } |
| 415 |
| 406 bool _isBranchTargetOfUselessIf(Continuation cont) { | 416 bool _isBranchTargetOfUselessIf(Continuation cont) { |
| 407 // A useless-if has an empty then and else branch, e.g. `if (cond);`. | 417 // A useless-if has an empty then and else branch, e.g. `if (cond);`. |
| 408 // | 418 // |
| 409 // Detect T or F in | 419 // Detect T or F in |
| 410 // | 420 // |
| 411 // let cont Join() = ... | 421 // let cont Join() = ... |
| 412 // in let cont T() = Join() | 422 // in let cont T() = Join() |
| 413 // F() = Join() | 423 // F() = Join() |
| 414 // in branch condition T F | 424 // in branch condition T F |
| 415 // | 425 // |
| 416 if (!cont.hasExactlyOneUse) return false; | 426 if (!cont.hasExactlyOneUse) return false; |
| 417 if (cont.firstRef.parent is! Branch) return false; | 427 if (cont.firstRef.parent is! Branch) return false; |
| 418 Branch branch = cont.firstRef.parent; | 428 Branch branch = cont.firstRef.parent; |
| 429 |
| 430 // Are both continuations the same InvokeContinuation on a join? |
| 419 Continuation trueCont = branch.trueContinuation.definition; | 431 Continuation trueCont = branch.trueContinuation.definition; |
| 432 Expression trueBody = _unfoldDeadRefinements(trueCont.body); |
| 433 if (trueBody is! InvokeContinuation) return false; |
| 420 Continuation falseCont = branch.falseContinuation.definition; | 434 Continuation falseCont = branch.falseContinuation.definition; |
| 421 // Are both continuations the same InvokeContinuation on a join? | 435 Expression falseBody = _unfoldDeadRefinements(falseCont.body); |
| 422 if (trueCont.body is! InvokeContinuation) return false; | 436 if (falseBody is! InvokeContinuation) return false; |
| 423 if (falseCont.body is! InvokeContinuation) return false; | 437 InvokeContinuation trueInvoke = trueBody; |
| 424 InvokeContinuation trueInvoke = trueCont.body; | 438 InvokeContinuation falseInvoke = falseBody; |
| 425 InvokeContinuation falseInvoke = falseCont.body; | |
| 426 if (trueInvoke.continuation.definition != | 439 if (trueInvoke.continuation.definition != |
| 427 falseInvoke.continuation.definition) { | 440 falseInvoke.continuation.definition) { |
| 428 return false; | 441 return false; |
| 429 } | 442 } |
| 430 assert(trueInvoke.arguments.length == falseInvoke.arguments.length); | 443 assert(trueInvoke.arguments.length == falseInvoke.arguments.length); |
| 431 // Matching zero arguments should be adequate, since isomorphic true and false | 444 // Matching zero arguments should be adequate, since isomorphic true and false |
| 432 // invocations should result in redundant phis which are removed elsewhere. | 445 // invocations should result in redundant phis which are removed elsewhere. |
| 433 if (trueInvoke.arguments.isNotEmpty) return false; | 446 if (trueInvoke.arguments.isNotEmpty) return false; |
| 434 return true; | 447 return true; |
| 435 } | 448 } |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 | 622 |
| 610 String toString() => "$kind: $node"; | 623 String toString() => "$kind: $node"; |
| 611 } | 624 } |
| 612 | 625 |
| 613 /// A dummy class used solely to mark nodes as deleted once they are removed | 626 /// A dummy class used solely to mark nodes as deleted once they are removed |
| 614 /// from a term. | 627 /// from a term. |
| 615 class _DeletedNode extends Node { | 628 class _DeletedNode extends Node { |
| 616 accept(_) {} | 629 accept(_) {} |
| 617 setParentPointers() {} | 630 setParentPointers() {} |
| 618 } | 631 } |
| OLD | NEW |