| 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 tree_ir.optimization.statement_rewriter; | 5 library tree_ir.optimization.statement_rewriter; |
| 6 | 6 |
| 7 import 'optimization.dart' show Pass; | 7 import 'optimization.dart' show Pass; |
| 8 import '../tree_ir_nodes.dart'; | 8 import '../tree_ir_nodes.dart'; |
| 9 import '../../io/source_information.dart'; | 9 import '../../io/source_information.dart'; |
| 10 | 10 |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 node = node.next; | 380 node = node.next; |
| 381 } | 381 } |
| 382 Statement result = visitStatement(node); | 382 Statement result = visitStatement(node); |
| 383 for (Function fun in stack.reversed) { | 383 for (Function fun in stack.reversed) { |
| 384 result = fun(result); | 384 result = fun(result); |
| 385 } | 385 } |
| 386 return result; | 386 return result; |
| 387 } | 387 } |
| 388 | 388 |
| 389 /// Attempts to propagate an assignment in an expression statement. | 389 /// Attempts to propagate an assignment in an expression statement. |
| 390 /// | 390 /// |
| 391 /// Returns a callback to be invoked after the sucessor statement has | 391 /// Returns a callback to be invoked after the sucessor statement has |
| 392 /// been processed. | 392 /// been processed. |
| 393 Function processExpressionStatement(ExpressionStatement stmt) { | 393 Function processExpressionStatement(ExpressionStatement stmt) { |
| 394 Variable leftHand = getLeftHand(stmt.expression); | 394 Variable leftHand = getLeftHand(stmt.expression); |
| 395 pushDominatingAssignment(leftHand); | 395 pushDominatingAssignment(leftHand); |
| 396 if (isEffectivelyConstantAssignment(stmt.expression) && | 396 if (isEffectivelyConstantAssignment(stmt.expression) && |
| 397 !usesRecentlyAssignedVariable(stmt.expression)) { | 397 !usesRecentlyAssignedVariable(stmt.expression)) { |
| 398 Assign assign = stmt.expression; | 398 Assign assign = stmt.expression; |
| 399 // Handle constant assignments specially. | 399 // Handle constant assignments specially. |
| 400 // They are always safe to propagate (though we should avoid duplication). | 400 // They are always safe to propagate (though we should avoid duplication). |
| 401 // Moreover, they should not prevent other expressions from propagating. | 401 // Moreover, they should not prevent other expressions from propagating. |
| 402 if (assign.variable.readCount == 1) { | 402 if (assign.variable.readCount == 1) { |
| 403 // A single-use constant should always be propagated to its use site. | 403 // A single-use constant should always be propagated to its use site. |
| 404 constantEnvironment[assign.variable] = assign.value; | 404 constantEnvironment[assign.variable] = assign.value; |
| 405 return (Statement next) { | 405 return (Statement next) { |
| 406 popDominatingAssignment(leftHand); | 406 popDominatingAssignment(leftHand); |
| 407 if (assign.variable.readCount > 0) { | 407 if (assign.variable.readCount > 0) { |
| 408 // The assignment could not be propagated into the successor, | 408 // The assignment could not be propagated into the successor, |
| 409 // either because it [hasUnsafeVariableUse] or because the | 409 // either because it [hasUnsafeVariableUse] or because the |
| 410 // use is outside the current try block, and we do not currently | 410 // use is outside the current try block, and we do not currently |
| 411 // support constant propagation out of a try block. | 411 // support constant propagation out of a try block. |
| 412 constantEnvironment.remove(assign.variable); | 412 constantEnvironment.remove(assign.variable); |
| 413 assign.value = visitExpression(assign.value); | 413 assign.value = visitExpression(assign.value); |
| 414 stmt.next = next; | 414 stmt.next = next; |
| 415 return stmt; | 415 return stmt; |
| 416 } else { | 416 } else { |
| 417 --assign.variable.writeCount; | 417 --assign.variable.writeCount; |
| 418 return next; | 418 return next; |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 834 if (environment.isEmpty || getLeftHand(environment.last) == null) { | 834 if (environment.isEmpty || getLeftHand(environment.last) == null) { |
| 835 // If there is no recent assignment that might propagate, so there is no | 835 // If there is no recent assignment that might propagate, so there is no |
| 836 // opportunity for optimization here. | 836 // opportunity for optimization here. |
| 837 _rewriteList(node.arguments); | 837 _rewriteList(node.arguments); |
| 838 return node; | 838 return node; |
| 839 } | 839 } |
| 840 Variable propagatableVariable = getLeftHand(environment.last); | 840 Variable propagatableVariable = getLeftHand(environment.last); |
| 841 BuiltinOperator commuted = commuteBinaryOperator(node.operator); | 841 BuiltinOperator commuted = commuteBinaryOperator(node.operator); |
| 842 if (commuted != null) { | 842 if (commuted != null) { |
| 843 assert(node.arguments.length == 2); // Only binary operators can commute. | 843 assert(node.arguments.length == 2); // Only binary operators can commute. |
| 844 VariableUse arg1 = node.arguments[0]; | 844 Expression left = node.arguments[0]; |
| 845 VariableUse arg2 = node.arguments[1]; | 845 if (left is VariableUse && propagatableVariable == left.variable) { |
| 846 if (propagatableVariable == arg1.variable && | 846 Expression right = node.arguments[1]; |
| 847 propagatableVariable != arg2.variable && | 847 if (right is This || |
| 848 !constantEnvironment.containsKey(arg2.variable)) { | 848 (right is VariableUse && |
| 849 // An assignment can be propagated if we commute the operator. | 849 propagatableVariable != right.variable && |
| 850 node.operator = commuted; | 850 !constantEnvironment.containsKey(right.variable))) { |
| 851 node.arguments[0] = arg2; | 851 // An assignment can be propagated if we commute the operator. |
| 852 node.arguments[1] = arg1; | 852 node.operator = commuted; |
| 853 node.arguments[0] = right; |
| 854 node.arguments[1] = left; |
| 855 } |
| 853 } | 856 } |
| 854 } | 857 } |
| 855 _rewriteList(node.arguments); | 858 _rewriteList(node.arguments); |
| 856 return node; | 859 return node; |
| 857 } | 860 } |
| 858 | 861 |
| 859 /// If [s] and [t] are similar statements we extract their subexpressions | 862 /// If [s] and [t] are similar statements we extract their subexpressions |
| 860 /// and returns a new statement of the same type using expressions combined | 863 /// and returns a new statement of the same type using expressions combined |
| 861 /// with the [combine] callback. For example: | 864 /// with the [combine] callback. For example: |
| 862 /// | 865 /// |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1217 VariableUseVisitor(this.callback); | 1220 VariableUseVisitor(this.callback); |
| 1218 | 1221 |
| 1219 visitVariableUse(VariableUse use) => callback(use); | 1222 visitVariableUse(VariableUse use) => callback(use); |
| 1220 | 1223 |
| 1221 visitInnerFunction(FunctionDefinition node) {} | 1224 visitInnerFunction(FunctionDefinition node) {} |
| 1222 | 1225 |
| 1223 static void visit(Expression node, VariableUseCallback callback) { | 1226 static void visit(Expression node, VariableUseCallback callback) { |
| 1224 new VariableUseVisitor(callback).visitExpression(node); | 1227 new VariableUseVisitor(callback).visitExpression(node); |
| 1225 } | 1228 } |
| 1226 } | 1229 } |
| OLD | NEW |