| 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 part of tree_ir.optimization; | 5 part of tree_ir.optimization; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Performs the following transformations on the tree: | 8 * Performs the following transformations on the tree: |
| 9 * - Assignment propagation | 9 * - Assignment propagation |
| 10 * - If-to-conditional conversion | 10 * - If-to-conditional conversion |
| (...skipping 377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 388 node.elseStatement = visitStatement(node.elseStatement); | 388 node.elseStatement = visitStatement(node.elseStatement); |
| 389 }); | 389 }); |
| 390 | 390 |
| 391 tryCollapseIf(node); | 391 tryCollapseIf(node); |
| 392 | 392 |
| 393 Statement reduced = combineStatementsWithSubexpressions( | 393 Statement reduced = combineStatementsWithSubexpressions( |
| 394 node.thenStatement, | 394 node.thenStatement, |
| 395 node.elseStatement, | 395 node.elseStatement, |
| 396 (t,f) => new Conditional(node.condition, t, f)..processed = true); | 396 (t,f) => new Conditional(node.condition, t, f)..processed = true); |
| 397 if (reduced != null) { | 397 if (reduced != null) { |
| 398 if (reduced.next is Break) { | 398 // TODO(asgerf): Avoid revisiting nodes or visiting nodes that we created. |
| 399 // In case the break can now be inlined. | 399 // This breaks the assumption that all subexpressions are |
| 400 reduced = visitStatement(reduced); | 400 // variable uses, and it can be expensive. |
| 401 } | 401 // Revisit in case the break can now be inlined. |
| 402 return reduced; | 402 return visitStatement(reduced); |
| 403 } | 403 } |
| 404 | 404 |
| 405 return node; | 405 return node; |
| 406 } | 406 } |
| 407 | 407 |
| 408 Statement visitWhileTrue(WhileTrue node) { | 408 Statement visitWhileTrue(WhileTrue node) { |
| 409 // Do not propagate assignments into loops. Doing so is not safe for | 409 // Do not propagate assignments into loops. Doing so is not safe for |
| 410 // variables modified in the loop (the initial value will be propagated). | 410 // variables modified in the loop (the initial value will be propagated). |
| 411 inEmptyEnvironment(() { | 411 inEmptyEnvironment(() { |
| 412 node.body = visitStatement(node.body); | 412 node.body = visitStatement(node.body); |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 if (s is Continue && t is Continue && s.target == t.target) { | 567 if (s is Continue && t is Continue && s.target == t.target) { |
| 568 --t.target.useCount; // Two continues become one. | 568 --t.target.useCount; // Two continues become one. |
| 569 return s; | 569 return s; |
| 570 } | 570 } |
| 571 if (s is Return && t is Return) { | 571 if (s is Return && t is Return) { |
| 572 Expression e = combineExpressions(s.value, t.value); | 572 Expression e = combineExpressions(s.value, t.value); |
| 573 if (e != null) { | 573 if (e != null) { |
| 574 return new Return(e); | 574 return new Return(e); |
| 575 } | 575 } |
| 576 } | 576 } |
| 577 if (s is Assign && t is Assign && |
| 578 s.variable == t.variable && |
| 579 isSameVariable(s.value, t.value)) { |
| 580 Statement next = combineStatements(s.next, t.next); |
| 581 if (next != null) { |
| 582 s.next = next; |
| 583 --t.variable.writeCount; |
| 584 --(t.value as VariableUse).variable.readCount; |
| 585 return s; |
| 586 } |
| 587 } |
| 577 return null; | 588 return null; |
| 578 } | 589 } |
| 579 | 590 |
| 580 /// Returns an expression equivalent to both [e1] and [e2]. | 591 /// Returns an expression equivalent to both [e1] and [e2]. |
| 581 /// If non-null is returned, the caller must discard [e1] and [e2] and use | 592 /// If non-null is returned, the caller must discard [e1] and [e2] and use |
| 582 /// the resulting expression in the tree. | 593 /// the resulting expression in the tree. |
| 583 static Expression combineExpressions(Expression e1, Expression e2) { | 594 static Expression combineExpressions(Expression e1, Expression e2) { |
| 584 if (e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable) { | 595 if (e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable) { |
| 585 --e1.variable.readCount; // Two references become one. | 596 --e1.variable.readCount; // Two references become one. |
| 586 return e1; | 597 return e1; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 637 if (tryCollapseIfAux(node, false, false)) { | 648 if (tryCollapseIfAux(node, false, false)) { |
| 638 changed = true; | 649 changed = true; |
| 639 } | 650 } |
| 640 } | 651 } |
| 641 } | 652 } |
| 642 | 653 |
| 643 bool tryCollapseIfAux(If outerIf, bool branch1, bool branch2) { | 654 bool tryCollapseIfAux(If outerIf, bool branch1, bool branch2) { |
| 644 // NOTE: We name variables here as if S is in the then-then position. | 655 // NOTE: We name variables here as if S is in the then-then position. |
| 645 Statement outerThen = getBranch(outerIf, branch1); | 656 Statement outerThen = getBranch(outerIf, branch1); |
| 646 Statement outerElse = getBranch(outerIf, !branch1); | 657 Statement outerElse = getBranch(outerIf, !branch1); |
| 647 if (outerThen is If && outerElse is Break) { | 658 if (outerThen is If) { |
| 648 If innerIf = outerThen; | 659 If innerIf = outerThen; |
| 649 Statement innerThen = getBranch(innerIf, branch2); | 660 Statement innerThen = getBranch(innerIf, branch2); |
| 650 Statement innerElse = getBranch(innerIf, !branch2); | 661 Statement innerElse = getBranch(innerIf, !branch2); |
| 651 if (innerElse is Break && innerElse.target == outerElse.target) { | 662 Statement combinedElse = combineStatements(innerElse, outerElse); |
| 663 if (combinedElse != null) { |
| 652 // We always put S in the then branch of the result, and adjust the | 664 // We always put S in the then branch of the result, and adjust the |
| 653 // condition expression if S was actually found in the else branch(es). | 665 // condition expression if S was actually found in the else branch(es). |
| 654 outerIf.condition = new LogicalOperator.and( | 666 outerIf.condition = new LogicalOperator.and( |
| 655 makeCondition(outerIf.condition, branch1), | 667 makeCondition(outerIf.condition, branch1), |
| 656 makeCondition(innerIf.condition, branch2)); | 668 makeCondition(innerIf.condition, branch2)); |
| 657 outerIf.thenStatement = innerThen; | 669 outerIf.thenStatement = innerThen; |
| 658 --innerElse.target.useCount; | |
| 659 | 670 |
| 660 // Try to inline the remaining break. Do not propagate assignments. | 671 // Try to inline the remaining break. Do not propagate assignments. |
| 661 inEmptyEnvironment(() { | 672 inEmptyEnvironment(() { |
| 662 outerIf.elseStatement = visitStatement(outerElse); | 673 // TODO(asgerf): Avoid quadratic cost from repeated processing. This |
| 674 // should be easier after we introduce basic blocks. |
| 675 outerIf.elseStatement = visitStatement(combinedElse); |
| 663 }); | 676 }); |
| 664 | 677 |
| 665 return outerIf.elseStatement is If && innerThen is Break; | 678 return outerIf.elseStatement is If; |
| 666 } | 679 } |
| 667 } | 680 } |
| 668 return false; | 681 return false; |
| 669 } | 682 } |
| 670 | 683 |
| 684 static bool isSameVariable(Expression e1, Expression e2) { |
| 685 return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable; |
| 686 } |
| 687 |
| 671 Expression makeCondition(Expression e, bool polarity) { | 688 Expression makeCondition(Expression e, bool polarity) { |
| 672 return polarity ? e : new Not(e); | 689 return polarity ? e : new Not(e); |
| 673 } | 690 } |
| 674 | 691 |
| 675 Statement getBranch(If node, bool polarity) { | 692 Statement getBranch(If node, bool polarity) { |
| 676 return polarity ? node.thenStatement : node.elseStatement; | 693 return polarity ? node.thenStatement : node.elseStatement; |
| 677 } | 694 } |
| 678 } | 695 } |
| OLD | NEW |