| 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 inlining | 9 * - Assignment inlining |
| 10 * - Assignment expression propagation | 10 * - Assignment expression propagation |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 209 // We traverse the tree right-to-left, so when we have seen all uses, | 209 // We traverse the tree right-to-left, so when we have seen all uses, |
| 210 // it means we are looking at the first use. | 210 // it means we are looking at the first use. |
| 211 assert(seenUses[node.variable] <= node.variable.readCount); | 211 assert(seenUses[node.variable] <= node.variable.readCount); |
| 212 bool isFirstUse = seenUses[node.variable] == node.variable.readCount; | 212 bool isFirstUse = seenUses[node.variable] == node.variable.readCount; |
| 213 | 213 |
| 214 // Propagate constant to use site. | 214 // Propagate constant to use site. |
| 215 Expression constant = constantEnvironment[node.variable]; | 215 Expression constant = constantEnvironment[node.variable]; |
| 216 if (constant != null) { | 216 if (constant != null) { |
| 217 --node.variable.readCount; | 217 --node.variable.readCount; |
| 218 --seenUses[node.variable]; // Do not count the use we just destroyed. | 218 --seenUses[node.variable]; // Do not count the use we just destroyed. |
| 219 return constant; | 219 return visitExpression(constant); |
| 220 } | 220 } |
| 221 | 221 |
| 222 // Try to propagate another expression into this variable use. | 222 // Try to propagate another expression into this variable use. |
| 223 if (!environment.isEmpty) { | 223 if (!environment.isEmpty) { |
| 224 Expression binding = environment.last; | 224 Expression binding = environment.last; |
| 225 | 225 |
| 226 // Is this variable assigned by the most recently evaluated impure | 226 // Is this variable assigned by the most recently evaluated impure |
| 227 // expression? | 227 // expression? |
| 228 // | 228 // |
| 229 // If so, propagate the assignment, e.g: | 229 // If so, propagate the assignment, e.g: |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 263 | 263 |
| 264 /// Returns true if [exp] has no side effects and has a constant value within | 264 /// Returns true if [exp] has no side effects and has a constant value within |
| 265 /// any given activation of the enclosing method. | 265 /// any given activation of the enclosing method. |
| 266 bool isEffectivelyConstant(Expression exp) { | 266 bool isEffectivelyConstant(Expression exp) { |
| 267 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional | 267 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional |
| 268 // expressions recursively. Determine if that is a valuable optimization | 268 // expressions recursively. Determine if that is a valuable optimization |
| 269 // and/or if it is better handled at the CPS level. | 269 // and/or if it is better handled at the CPS level. |
| 270 return exp is Constant || | 270 return exp is Constant || |
| 271 exp is This || | 271 exp is This || |
| 272 exp is ReifyTypeVar || | 272 exp is ReifyTypeVar || |
| 273 exp is InvokeStatic && exp.isEffectivelyConstant || |
| 273 exp is VariableUse && constantEnvironment.containsKey(exp.variable); | 274 exp is VariableUse && constantEnvironment.containsKey(exp.variable); |
| 274 } | 275 } |
| 275 | 276 |
| 276 /// True if [node] is an assignment that can be propagated as a constant. | 277 /// True if [node] is an assignment that can be propagated as a constant. |
| 277 bool isEffectivelyConstantAssignment(Expression node) { | 278 bool isEffectivelyConstantAssignment(Expression node) { |
| 278 return node is Assign && | 279 return node is Assign && |
| 279 node.variable.writeCount == 1 && | 280 node.variable.writeCount == 1 && |
| 280 isEffectivelyConstant(node.value); | 281 isEffectivelyConstant(node.value); |
| 281 } | 282 } |
| 282 | 283 |
| 283 Statement visitExpressionStatement(ExpressionStatement stmt) { | 284 Statement visitExpressionStatement(ExpressionStatement stmt) { |
| 284 if (isEffectivelyConstantAssignment(stmt.expression)) { | 285 if (isEffectivelyConstantAssignment(stmt.expression)) { |
| 285 Assign assign = stmt.expression; | 286 Assign assign = stmt.expression; |
| 286 // Handle constant assignments specially. | 287 // Handle constant assignments specially. |
| 287 // They are always safe to propagate (though we should avoid duplication). | 288 // They are always safe to propagate (though we should avoid duplication). |
| 288 // Moreover, they should not prevent other expressions from propagating. | 289 // Moreover, they should not prevent other expressions from propagating. |
| 289 if (assign.variable.readCount <= 1) { | 290 if (assign.variable.readCount <= 1) { |
| 290 // A single-use constant should always be propagted to its use site. | 291 // A single-use constant should always be propagted to its use site. |
| 291 constantEnvironment[assign.variable] = visitExpression(assign.value); | 292 constantEnvironment[assign.variable] = assign.value; |
| 292 --assign.variable.writeCount; | 293 --assign.variable.writeCount; |
| 293 return visitStatement(stmt.next); | 294 return visitStatement(stmt.next); |
| 294 } else { | 295 } else { |
| 295 // With more than one use, we cannot propagate the constant. | 296 // With more than one use, we cannot propagate the constant. |
| 296 // Visit the following statement without polluting [environment] so | 297 // Visit the following statement without polluting [environment] so |
| 297 // that any preceding non-constant assignments might still propagate. | 298 // that any preceding non-constant assignments might still propagate. |
| 298 stmt.next = visitStatement(stmt.next); | 299 stmt.next = visitStatement(stmt.next); |
| 299 assign.value = visitExpression(assign.value); | 300 assign.value = visitExpression(assign.value); |
| 300 return stmt; | 301 return stmt; |
| 301 } | 302 } |
| (...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 } | 909 } |
| 909 | 910 |
| 910 /// Result of combining two expressions that do not affect reference counting. | 911 /// Result of combining two expressions that do not affect reference counting. |
| 911 class GenericCombinedExpressions implements CombinedExpressions { | 912 class GenericCombinedExpressions implements CombinedExpressions { |
| 912 Expression combined; | 913 Expression combined; |
| 913 | 914 |
| 914 GenericCombinedExpressions(this.combined); | 915 GenericCombinedExpressions(this.combined); |
| 915 | 916 |
| 916 void uncombine() {} | 917 void uncombine() {} |
| 917 } | 918 } |
| OLD | NEW |