| 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 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 577 if (s is Continue && t is Continue && s.target == t.target) { | 577 if (s is Continue && t is Continue && s.target == t.target) { |
| 578 --t.target.useCount; // Two continues become one. | 578 --t.target.useCount; // Two continues become one. |
| 579 return s; | 579 return s; |
| 580 } | 580 } |
| 581 if (s is Return && t is Return) { | 581 if (s is Return && t is Return) { |
| 582 Expression e = combineExpressions(s.value, t.value); | 582 Expression e = combineExpressions(s.value, t.value); |
| 583 if (e != null) { | 583 if (e != null) { |
| 584 return new Return(e); | 584 return new Return(e); |
| 585 } | 585 } |
| 586 } | 586 } |
| 587 if (s is Assign && t is Assign && |
| 588 s.variable == t.variable && |
| 589 isSameVariable(s.value, t.value)) { |
| 590 Statement next = combineStatements(s.next, t.next); |
| 591 if (next != null) { |
| 592 s.next = next; |
| 593 --t.variable.writeCount; |
| 594 --(t.value as VariableUse).variable.readCount; |
| 595 return s; |
| 596 } |
| 597 } |
| 587 return null; | 598 return null; |
| 588 } | 599 } |
| 589 | 600 |
| 590 /// Returns an expression equivalent to both [e1] and [e2]. | 601 /// Returns an expression equivalent to both [e1] and [e2]. |
| 591 /// If non-null is returned, the caller must discard [e1] and [e2] and use | 602 /// If non-null is returned, the caller must discard [e1] and [e2] and use |
| 592 /// the resulting expression in the tree. | 603 /// the resulting expression in the tree. |
| 593 static Expression combineExpressions(Expression e1, Expression e2) { | 604 static Expression combineExpressions(Expression e1, Expression e2) { |
| 594 if (e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable) { | 605 if (e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable) { |
| 595 --e1.variable.readCount; // Two references become one. | 606 --e1.variable.readCount; // Two references become one. |
| 596 return e1; | 607 return e1; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 647 if (tryCollapseIfAux(node, false, false)) { | 658 if (tryCollapseIfAux(node, false, false)) { |
| 648 changed = true; | 659 changed = true; |
| 649 } | 660 } |
| 650 } | 661 } |
| 651 } | 662 } |
| 652 | 663 |
| 653 bool tryCollapseIfAux(If outerIf, bool branch1, bool branch2) { | 664 bool tryCollapseIfAux(If outerIf, bool branch1, bool branch2) { |
| 654 // NOTE: We name variables here as if S is in the then-then position. | 665 // NOTE: We name variables here as if S is in the then-then position. |
| 655 Statement outerThen = getBranch(outerIf, branch1); | 666 Statement outerThen = getBranch(outerIf, branch1); |
| 656 Statement outerElse = getBranch(outerIf, !branch1); | 667 Statement outerElse = getBranch(outerIf, !branch1); |
| 657 if (outerThen is If && outerElse is Break) { | 668 if (outerThen is If) { |
| 658 If innerIf = outerThen; | 669 If innerIf = outerThen; |
| 659 Statement innerThen = getBranch(innerIf, branch2); | 670 Statement innerThen = getBranch(innerIf, branch2); |
| 660 Statement innerElse = getBranch(innerIf, !branch2); | 671 Statement innerElse = getBranch(innerIf, !branch2); |
| 661 if (innerElse is Break && innerElse.target == outerElse.target) { | 672 Statement combinedElse = combineStatements(innerElse, outerElse); |
| 673 if (combinedElse != null) { |
| 662 // We always put S in the then branch of the result, and adjust the | 674 // We always put S in the then branch of the result, and adjust the |
| 663 // condition expression if S was actually found in the else branch(es). | 675 // condition expression if S was actually found in the else branch(es). |
| 664 outerIf.condition = new LogicalOperator.and( | 676 outerIf.condition = new LogicalOperator.and( |
| 665 makeCondition(outerIf.condition, branch1), | 677 makeCondition(outerIf.condition, branch1), |
| 666 makeCondition(innerIf.condition, branch2)); | 678 makeCondition(innerIf.condition, branch2)); |
| 667 outerIf.thenStatement = innerThen; | 679 outerIf.thenStatement = innerThen; |
| 668 --innerElse.target.useCount; | |
| 669 | 680 |
| 670 // Try to inline the remaining break. Do not propagate assignments. | 681 // Try to inline the remaining break. Do not propagate assignments. |
| 671 inEmptyEnvironment(() { | 682 inEmptyEnvironment(() { |
| 672 outerIf.elseStatement = visitStatement(outerElse); | 683 // TODO(asgerf): Avoid quadratic cost from repeated processing. This |
| 684 // should be easier after we introduce basic blocks. |
| 685 outerIf.elseStatement = visitStatement(combinedElse); |
| 673 }); | 686 }); |
| 674 | 687 |
| 675 return outerIf.elseStatement is If && innerThen is Break; | 688 return outerIf.elseStatement is If; |
| 676 } | 689 } |
| 677 } | 690 } |
| 678 return false; | 691 return false; |
| 679 } | 692 } |
| 680 | 693 |
| 694 static bool isSameVariable(Expression e1, Expression e2) { |
| 695 return e1 is VariableUse && e2 is VariableUse && e1.variable == e2.variable; |
| 696 } |
| 697 |
| 681 Expression makeCondition(Expression e, bool polarity) { | 698 Expression makeCondition(Expression e, bool polarity) { |
| 682 return polarity ? e : new Not(e); | 699 return polarity ? e : new Not(e); |
| 683 } | 700 } |
| 684 | 701 |
| 685 Statement getBranch(If node, bool polarity) { | 702 Statement getBranch(If node, bool polarity) { |
| 686 return polarity ? node.thenStatement : node.elseStatement; | 703 return polarity ? node.thenStatement : node.elseStatement; |
| 687 } | 704 } |
| 688 } | 705 } |
| OLD | NEW |