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 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
361 exp is VariableUse && constantEnvironment.containsKey(exp.variable); | 361 exp is VariableUse && constantEnvironment.containsKey(exp.variable); |
362 } | 362 } |
363 | 363 |
364 /// True if [node] is an assignment that can be propagated as a constant. | 364 /// True if [node] is an assignment that can be propagated as a constant. |
365 bool isEffectivelyConstantAssignment(Expression node) { | 365 bool isEffectivelyConstantAssignment(Expression node) { |
366 return node is Assign && | 366 return node is Assign && |
367 node.variable.writeCount == 1 && | 367 node.variable.writeCount == 1 && |
368 isEffectivelyConstant(node.value); | 368 isEffectivelyConstant(node.value); |
369 } | 369 } |
370 | 370 |
371 Statement visitExpressionStatement(ExpressionStatement stmt) { | 371 Statement visitExpressionStatement(ExpressionStatement inputNode) { |
floitsch
2015/07/22 14:21:42
Add comment, what this function does (and/or on an
asgerf
2015/07/22 14:32:25
Done. Also renamed analyze->process since it has s
| |
372 List<Function> stack = []; | |
373 Statement node = inputNode; | |
374 while (node is ExpressionStatement) { | |
375 stack.add(analyzeExpressionStatement(node)); | |
376 node = node.next; | |
377 } | |
378 Statement result = visitStatement(node); | |
379 for (Function fun in stack.reversed) { | |
380 result = fun(result); | |
381 } | |
382 return result; | |
383 } | |
384 | |
385 Function analyzeExpressionStatement(ExpressionStatement stmt) { | |
372 Variable leftHand = getLeftHand(stmt.expression); | 386 Variable leftHand = getLeftHand(stmt.expression); |
373 pushDominatingAssignment(leftHand); | 387 pushDominatingAssignment(leftHand); |
374 if (isEffectivelyConstantAssignment(stmt.expression) && | 388 if (isEffectivelyConstantAssignment(stmt.expression) && |
375 !usesRecentlyAssignedVariable(stmt.expression)) { | 389 !usesRecentlyAssignedVariable(stmt.expression)) { |
376 Assign assign = stmt.expression; | 390 Assign assign = stmt.expression; |
377 // Handle constant assignments specially. | 391 // Handle constant assignments specially. |
378 // They are always safe to propagate (though we should avoid duplication). | 392 // They are always safe to propagate (though we should avoid duplication). |
379 // Moreover, they should not prevent other expressions from propagating. | 393 // Moreover, they should not prevent other expressions from propagating. |
380 if (assign.variable.readCount == 1) { | 394 if (assign.variable.readCount == 1) { |
381 // A single-use constant should always be propagated to its use site. | 395 // A single-use constant should always be propagated to its use site. |
382 constantEnvironment[assign.variable] = assign.value; | 396 constantEnvironment[assign.variable] = assign.value; |
383 Statement next = visitStatement(stmt.next); | 397 return (Statement next) { |
384 popDominatingAssignment(leftHand); | 398 popDominatingAssignment(leftHand); |
385 if (assign.variable.readCount > 0) { | 399 if (assign.variable.readCount > 0) { |
386 // The assignment could not be propagated into the successor, either | 400 // The assignment could not be propagated into the successor, either |
387 // because it has an unsafe variable use (see [hasUnsafeVariableUse]) | 401 // because it has an unsafe variable use (see [hasUnsafeVariableUse] ) |
floitsch
2015/07/22 14:21:42
long line.
asgerf
2015/07/22 14:32:25
Done.
| |
388 // or because the use is outside the current try block, and we do | 402 // or because the use is outside the current try block, and we do |
389 // not currently support constant propagation out of a try block. | 403 // not currently support constant propagation out of a try block. |
390 constantEnvironment.remove(assign.variable); | 404 constantEnvironment.remove(assign.variable); |
391 assign.value = visitExpression(assign.value); | 405 assign.value = visitExpression(assign.value); |
392 stmt.next = next; | 406 stmt.next = next; |
393 return stmt; | 407 return stmt; |
394 } else { | 408 } else { |
395 --assign.variable.writeCount; | 409 --assign.variable.writeCount; |
396 return next; | 410 return next; |
397 } | 411 } |
412 }; | |
398 } else { | 413 } else { |
399 // With more than one use, we cannot propagate the constant. | 414 // With more than one use, we cannot propagate the constant. |
400 // Visit the following statement without polluting [environment] so | 415 // Visit the following statement without polluting [environment] so |
401 // that any preceding non-constant assignments might still propagate. | 416 // that any preceding non-constant assignments might still propagate. |
402 stmt.next = visitStatement(stmt.next); | 417 return (Statement next) { |
418 stmt.next = next; | |
419 popDominatingAssignment(leftHand); | |
420 assign.value = visitExpression(assign.value); | |
421 return stmt; | |
422 }; | |
423 } | |
424 } else { | |
425 // Try to propagate the expression, and block previous impure expressions | |
426 // until this has propagated. | |
427 environment.add(stmt.expression); | |
428 return (Statement next) { | |
429 stmt.next = next; | |
403 popDominatingAssignment(leftHand); | 430 popDominatingAssignment(leftHand); |
404 assign.value = visitExpression(assign.value); | 431 if (!environment.isEmpty && environment.last == stmt.expression) { |
405 return stmt; | 432 // Retain the expression statement. |
406 } | 433 environment.removeLast(); |
407 } | 434 stmt.expression = visitExpression(stmt.expression); |
408 // Try to propagate the expression, and block previous impure expressions | 435 return stmt; |
409 // until this has propagated. | 436 } else { |
410 environment.add(stmt.expression); | 437 // Expression was propagated into the successor. |
411 stmt.next = visitStatement(stmt.next); | 438 return stmt.next; |
412 popDominatingAssignment(leftHand); | 439 } |
413 if (!environment.isEmpty && environment.last == stmt.expression) { | 440 }; |
414 // Retain the expression statement. | |
415 environment.removeLast(); | |
416 stmt.expression = visitExpression(stmt.expression); | |
417 return stmt; | |
418 } else { | |
419 // Expression was propagated into the successor. | |
420 return stmt.next; | |
421 } | 441 } |
422 } | 442 } |
423 | 443 |
424 Expression visitAssign(Assign node) { | 444 Expression visitAssign(Assign node) { |
425 node.value = visitExpression(node.value); | 445 node.value = visitExpression(node.value); |
426 // Remove assignments to variables without any uses. This can happen | 446 // Remove assignments to variables without any uses. This can happen |
427 // because the assignment was propagated into its use, e.g: | 447 // because the assignment was propagated into its use, e.g: |
428 // | 448 // |
429 // { x = foo(); bar(x) } ==> bar(x = foo()) ==> bar(foo()) | 449 // { x = foo(); bar(x) } ==> bar(x = foo()) ==> bar(foo()) |
430 // | 450 // |
(...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1169 VariableUseVisitor(this.callback); | 1189 VariableUseVisitor(this.callback); |
1170 | 1190 |
1171 visitVariableUse(VariableUse use) => callback(use); | 1191 visitVariableUse(VariableUse use) => callback(use); |
1172 | 1192 |
1173 visitInnerFunction(FunctionDefinition node) {} | 1193 visitInnerFunction(FunctionDefinition node) {} |
1174 | 1194 |
1175 static void visit(Expression node, VariableUseCallback callback) { | 1195 static void visit(Expression node, VariableUseCallback callback) { |
1176 new VariableUseVisitor(callback).visitExpression(node); | 1196 new VariableUseVisitor(callback).visitExpression(node); |
1177 } | 1197 } |
1178 } | 1198 } |
OLD | NEW |