Chromium Code Reviews| 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 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 }); | 162 }); |
| 163 return node; | 163 return node; |
| 164 } | 164 } |
| 165 | 165 |
| 166 Expression visitExpression(Expression e) => e.processed ? e : e.accept(this); | 166 Expression visitExpression(Expression e) => e.processed ? e : e.accept(this); |
| 167 | 167 |
| 168 @override | 168 @override |
| 169 Expression visitVariableUse(VariableUse node) { | 169 Expression visitVariableUse(VariableUse node) { |
| 170 // Propagate constant to use site. | 170 // Propagate constant to use site. |
| 171 Expression constant = constantEnvironment[node.variable]; | 171 Expression constant = constantEnvironment[node.variable]; |
| 172 if (constant != null) return constant; | 172 if (constant != null) { |
| 173 node.variable.readCount--; | |
| 174 return constant; | |
| 175 } | |
| 173 | 176 |
| 174 // Propagate a variable's definition to its use site if: | 177 // Propagate a variable's definition to its use site if: |
| 175 // 1. It has a single use, to avoid code growth and potential duplication | 178 // 1. It has a single use, to avoid code growth and potential duplication |
| 176 // of side effects, AND | 179 // of side effects, AND |
| 177 // 2. It was the most recent expression evaluated so that we do not | 180 // 2. It was the most recent expression evaluated so that we do not |
| 178 // reorder expressions with side effects. | 181 // reorder expressions with side effects. |
| 179 if (!environment.isEmpty && | 182 if (!environment.isEmpty && |
| 180 environment.last.variable == node.variable && | 183 environment.last.variable == node.variable && |
| 181 environment.last.hasExactlyOneUse) { | 184 node.variable.readCount == 1) { |
| 185 node.variable.readCount--; | |
| 182 return visitExpression(environment.removeLast().definition); | 186 return visitExpression(environment.removeLast().definition); |
| 183 } | 187 } |
| 184 | 188 |
| 185 // If the definition could not be propagated, leave the variable use. | 189 // If the definition could not be propagated, leave the variable use. |
| 186 return node; | 190 return node; |
| 187 } | 191 } |
| 188 | 192 |
| 189 /// Returns true if [exp] has no side effects and has a constant value within | 193 /// Returns true if [exp] has no side effects and has a constant value within |
| 190 /// any given activation of the enclosing method. | 194 /// any given activation of the enclosing method. |
| 191 bool isEffectivelyConstant(Expression exp) { | 195 bool isEffectivelyConstant(Expression exp) { |
| 192 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional | 196 // TODO(asgerf): Can be made more aggressive e.g. by checking conditional |
| 193 // expressions recursively. Determine if that is a valuable optimization | 197 // expressions recursively. Determine if that is a valuable optimization |
| 194 // and/or if it is better handled at the CPS level. | 198 // and/or if it is better handled at the CPS level. |
| 195 return exp is Constant || | 199 return exp is Constant || |
| 196 exp is This || | 200 exp is This || |
| 197 exp is ReifyTypeVar || | 201 exp is ReifyTypeVar || |
| 198 exp is VariableUse && constantEnvironment.containsKey(exp.variable); | 202 exp is VariableUse && constantEnvironment.containsKey(exp.variable); |
| 199 } | 203 } |
| 200 | 204 |
| 201 Statement visitAssign(Assign node) { | 205 Statement visitAssign(Assign node) { |
| 202 if (isEffectivelyConstant(node.definition) && | 206 if (isEffectivelyConstant(node.definition) && |
| 203 node.variable.writeCount == 1) { | 207 node.variable.writeCount == 1) { |
| 204 // Handle constant assignments specially. | 208 // Handle constant assignments specially. |
| 205 // They are always safe to propagate (though we should avoid duplication). | 209 // They are always safe to propagate (though we should avoid duplication). |
| 206 // Moreover, they should not prevent other expressions from propagating. | 210 // Moreover, they should not prevent other expressions from propagating. |
| 207 if (node.variable.readCount <= 1) { | 211 if (node.variable.readCount <= 1) { |
| 208 // A single-use constant should always be propagted to its use site. | 212 // A single-use constant should always be propagted to its use site. |
| 209 constantEnvironment[node.variable] = visitExpression(node.definition); | 213 constantEnvironment[node.variable] = visitExpression(node.definition); |
| 214 node.variable.writeCount--; | |
| 210 return visitStatement(node.next); | 215 return visitStatement(node.next); |
| 211 } else { | 216 } else { |
| 212 // With more than one use, we cannot propagate the constant. | 217 // With more than one use, we cannot propagate the constant. |
| 213 // Visit the following statement without polluting [environment] so | 218 // Visit the following statement without polluting [environment] so |
| 214 // that any preceding non-constant assignments might still propagate. | 219 // that any preceding non-constant assignments might still propagate. |
| 215 node.next = visitStatement(node.next); | 220 node.next = visitStatement(node.next); |
| 216 node.definition = visitExpression(node.definition); | 221 node.definition = visitExpression(node.definition); |
| 217 return node; | 222 return node; |
| 218 } | 223 } |
| 219 } else { | 224 } else { |
| 220 // Try to propagate assignment, and block previous assignment until this | 225 // Try to propagate assignment, and block previous assignment until this |
| 221 // has propagated. | 226 // has propagated. |
| 222 environment.add(node); | 227 environment.add(node); |
| 223 Statement next = visitStatement(node.next); | 228 Statement next = visitStatement(node.next); |
| 224 if (!environment.isEmpty && environment.last == node) { | 229 if (!environment.isEmpty && environment.last == node) { |
| 225 // The definition could not be propagated. Residualize the let binding. | 230 // The definition could not be propagated. Residualize the let binding. |
| 226 node.next = next; | 231 node.next = next; |
| 227 environment.removeLast(); | 232 environment.removeLast(); |
| 228 node.definition = visitExpression(node.definition); | 233 node.definition = visitExpression(node.definition); |
| 229 return node; | 234 return node; |
| 230 } | 235 } |
| 231 assert(!environment.contains(node)); | 236 assert(!environment.contains(node)); |
| 237 node.variable.writeCount--; // This assignment was removed. | |
| 232 return next; | 238 return next; |
| 233 } | 239 } |
| 234 } | 240 } |
| 235 | 241 |
| 236 Expression visitInvokeStatic(InvokeStatic node) { | 242 Expression visitInvokeStatic(InvokeStatic node) { |
| 237 // Process arguments right-to-left, the opposite of evaluation order. | 243 // Process arguments right-to-left, the opposite of evaluation order. |
| 238 for (int i = node.arguments.length - 1; i >= 0; --i) { | 244 for (int i = node.arguments.length - 1; i >= 0; --i) { |
| 239 node.arguments[i] = visitExpression(node.arguments[i]); | 245 node.arguments[i] = visitExpression(node.arguments[i]); |
| 240 } | 246 } |
| 241 return node; | 247 return node; |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 static Statement combineStatementsWithSubexpressions( | 516 static Statement combineStatementsWithSubexpressions( |
| 511 Statement s, | 517 Statement s, |
| 512 Statement t, | 518 Statement t, |
| 513 Expression combine(Expression s, Expression t)) { | 519 Expression combine(Expression s, Expression t)) { |
| 514 if (s is Return && t is Return) { | 520 if (s is Return && t is Return) { |
| 515 return new Return(combine(s.value, t.value)); | 521 return new Return(combine(s.value, t.value)); |
| 516 } | 522 } |
| 517 if (s is Assign && t is Assign && s.variable == t.variable) { | 523 if (s is Assign && t is Assign && s.variable == t.variable) { |
| 518 Statement next = combineStatements(s.next, t.next); | 524 Statement next = combineStatements(s.next, t.next); |
| 519 if (next != null) { | 525 if (next != null) { |
| 520 --t.variable.writeCount; // Two assignments become one. | 526 // Destroy both original assignments to the variable. |
| 527 --s.variable.writeCount; | |
|
Kevin Millikin (Google)
2015/03/04 10:35:30
I guess we should be consistent within this file a
| |
| 528 --t.variable.writeCount; | |
| 529 // The Assign constructor will increment the reference count again. | |
| 521 return new Assign(s.variable, | 530 return new Assign(s.variable, |
| 522 combine(s.definition, t.definition), | 531 combine(s.definition, t.definition), |
| 523 next); | 532 next); |
| 524 } | 533 } |
| 525 } | 534 } |
| 526 if (s is ExpressionStatement && t is ExpressionStatement) { | 535 if (s is ExpressionStatement && t is ExpressionStatement) { |
| 527 Statement next = combineStatements(s.next, t.next); | 536 Statement next = combineStatements(s.next, t.next); |
| 528 if (next != null) { | 537 if (next != null) { |
| 529 return new ExpressionStatement(combine(s.expression, t.expression), | 538 return new ExpressionStatement(combine(s.expression, t.expression), |
| 530 next); | 539 next); |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 648 } | 657 } |
| 649 | 658 |
| 650 Expression makeCondition(Expression e, bool polarity) { | 659 Expression makeCondition(Expression e, bool polarity) { |
| 651 return polarity ? e : new Not(e); | 660 return polarity ? e : new Not(e); |
| 652 } | 661 } |
| 653 | 662 |
| 654 Statement getBranch(If node, bool polarity) { | 663 Statement getBranch(If node, bool polarity) { |
| 655 return polarity ? node.thenStatement : node.elseStatement; | 664 return polarity ? node.thenStatement : node.elseStatement; |
| 656 } | 665 } |
| 657 } | 666 } |
| OLD | NEW |