Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: pkg/compiler/lib/src/tree_ir/optimization/variable_merger.dart

Issue 1068243002: Overhaul tree IR visitor and rename IR classes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add dummy use for RootVisitor and InitializerVisitor without arguments Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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.variable_merger; 5 library tree_ir.optimization.variable_merger;
6 6
7 import 'optimization.dart' show Pass, PassMixin; 7 import 'optimization.dart' show Pass, PassMixin;
8 import '../tree_ir_nodes.dart'; 8 import '../tree_ir_nodes.dart';
9 import '../../elements/elements.dart' show Local, ParameterElement; 9 import '../../elements/elements.dart' show Local, ParameterElement;
10 10
11 /// Merges variables based on liveness and source variable information. 11 /// Merges variables based on liveness and source variable information.
12 /// 12 ///
13 /// This phase cleans up artifacts introduced by the translation through CPS, 13 /// This phase cleans up artifacts introduced by the translation through CPS,
14 /// where each source variable is translated into several copies. The copies 14 /// where each source variable is translated into several copies. The copies
15 /// are merged again when they are not live simultaneously. 15 /// are merged again when they are not live simultaneously.
16 class VariableMerger extends RecursiveVisitor with PassMixin { 16 class VariableMerger extends RecursiveVisitor implements Pass {
17 String get passName => 'Variable merger'; 17 String get passName => 'Variable merger';
18 18
19 void rewrite(RootNode node) {
20 rewriteFunction(node);
21 node.forEachBody(visitStatement);
22 }
23
19 @override 24 @override
20 void rewriteExecutableDefinition(ExecutableDefinition node) { 25 void visitInnerFunction(FunctionDefinition node) {
21 visitExecutableDefinition(node); 26 rewriteFunction(node);
22 } 27 }
23 28
24 /// Rewrites the given function. 29 /// Rewrites the given function.
25 /// This is called for the outermost function and inner functions. 30 /// This is called for the outermost function and inner functions.
26 void rewriteFunction(ExecutableDefinition node) { 31 void rewriteFunction(RootNode node) {
27 BlockGraphBuilder builder = new BlockGraphBuilder(); 32 node.forEachBody((Statement body) {
28 builder.visitExecutableDefinition(node); 33 BlockGraphBuilder builder = new BlockGraphBuilder();
29 _computeLiveness(builder.blocks); 34 builder.build(node.parameters, body);
30 Map<Variable, Variable> subst = _computeRegisterAllocation(builder.blocks); 35 _computeLiveness(builder.blocks);
31 new SubstituteVariables(subst).visitExecutableDefinition(node); 36 Map<Variable, Variable> subst =
32 } 37 _computeRegisterAllocation(builder.blocks);
33 38 new SubstituteVariables(subst).apply(node);
34 visitFunctionDefinition(FunctionDefinition node) { 39 });
35 super.visitFunctionDefinition(node); // Recurse to visit inner functions.
36 rewriteFunction(node);
37 }
38
39 visitFieldDefinition(FieldDefinition node) {
40 super.visitFieldDefinition(node);
41 rewriteFunction(node);
42 }
43
44 visitConstructorDefinition(ConstructorDefinition node) {
45 super.visitConstructorDefinition(node);
46 rewriteFunction(node);
47 } 40 }
48 } 41 }
49 42
50 /// A read or write access to a variable. 43 /// A read or write access to a variable.
51 class VariableAccess { 44 class VariableAccess {
52 Variable variable; 45 Variable variable;
53 bool isRead; 46 bool isRead;
54 bool get isWrite => !isRead; 47 bool get isWrite => !isRead;
55 48
56 VariableAccess.read(this.variable) : isRead = true; 49 VariableAccess.read(this.variable) : isRead = true;
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 Map<Label, Block> _jumpTarget = <Label, Block>{}; 102 Map<Label, Block> _jumpTarget = <Label, Block>{};
110 Block _currentBlock; 103 Block _currentBlock;
111 List<Block> blocks = <Block>[]; 104 List<Block> blocks = <Block>[];
112 105
113 /// Variables with an assignment that should be treated as final. 106 /// Variables with an assignment that should be treated as final.
114 /// 107 ///
115 /// Such variables cannot be merged with any other variables, so we exclude 108 /// Such variables cannot be merged with any other variables, so we exclude
116 /// them from the control-flow graph entirely. 109 /// them from the control-flow graph entirely.
117 Set<Variable> _ignoredVariables = new Set<Variable>(); 110 Set<Variable> _ignoredVariables = new Set<Variable>();
118 111
119 BlockGraphBuilder() { 112 void build(List<Variable> parameters, Statement body) {
120 _currentBlock = newBlock(); 113 _currentBlock = newBlock();
114 parameters.forEach(write);
115 visitStatement(body);
116 }
117
118 @override
119 void visitInnerFunction(FunctionDefinition node) {
120 // Do nothing. Inner functions are traversed in VariableMerger.
121 } 121 }
122 122
123 /// Creates a new block with the current exception handler or [catchBlock] 123 /// Creates a new block with the current exception handler or [catchBlock]
124 /// if provided. 124 /// if provided.
125 Block newBlock({Block catchBlock}) { 125 Block newBlock({Block catchBlock}) {
126 if (catchBlock == null && _currentBlock != null) { 126 if (catchBlock == null && _currentBlock != null) {
127 catchBlock = _currentBlock.catchBlock; 127 catchBlock = _currentBlock.catchBlock;
128 } 128 }
129 Block block = new Block(catchBlock); 129 Block block = new Block(catchBlock);
130 blocks.add(block); 130 blocks.add(block);
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
237 visitExpression(node.left); 237 visitExpression(node.left);
238 // TODO(asgerf): When assignment expressions are added, this is no longer 238 // TODO(asgerf): When assignment expressions are added, this is no longer
239 // sound; then we need to handle as a branch. 239 // sound; then we need to handle as a branch.
240 visitExpression(node.right); 240 visitExpression(node.right);
241 } 241 }
242 242
243 visitFunctionDeclaration(FunctionDeclaration node) { 243 visitFunctionDeclaration(FunctionDeclaration node) {
244 // The function variable is final, hence cannot be merged. 244 // The function variable is final, hence cannot be merged.
245 ignoreVariable(node.variable); 245 ignoreVariable(node.variable);
246 visitStatement(node.next); 246 visitStatement(node.next);
247 // Do not traverse inner function.
248 }
249
250 visitFunctionExpression(FunctionExpression node) {
251 // Do not traverse inner function.
252 }
253
254 visitFunctionDefinition(FunctionDefinition node) {
255 // Function parameters are treated as write operations at the entry point,
256 // so they can potentially be merged with other copies of the parameter.
257 // Note that function parameters always have distinct source variables,
258 // so we don't risk accidentally merging two parameters.
259 node.parameters.forEach(write);
260 visitStatement(node.body);
261 }
262
263 visitConstructorDefinition(ConstructorDefinition node) {
264 node.parameters.forEach(write);
265 node.initializers.forEach(visitInitializer);
266 visitStatement(node.body);
267 } 247 }
268 } 248 }
269 249
270 /// Computes liveness information of the given control-flow graph. 250 /// Computes liveness information of the given control-flow graph.
271 /// 251 ///
272 /// The results are stored in [Block.liveIn] and [Block.liveOut]. 252 /// The results are stored in [Block.liveIn] and [Block.liveOut].
273 void _computeLiveness(List<Block> blocks) { 253 void _computeLiveness(List<Block> blocks) {
274 // We use a LIFO queue as worklist. Blocks are given in AST order, so by 254 // We use a LIFO queue as worklist. Blocks are given in AST order, so by
275 // inserting them in this order, we initially visit them backwards, which 255 // inserting them in this order, we initially visit them backwards, which
276 // is a good ordering. 256 // is a good ordering.
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 subst[v1] = v1; 447 subst[v1] = v1;
468 } else { 448 } else {
469 subst[v1] = potential.first; 449 subst[v1] = potential.first;
470 } 450 }
471 } 451 }
472 452
473 return subst; 453 return subst;
474 } 454 }
475 455
476 /// Performs variable substitution and removes redundant assignments. 456 /// Performs variable substitution and removes redundant assignments.
477 class SubstituteVariables extends RecursiveVisitor { 457 class SubstituteVariables extends RecursiveTransformer {
478 458
479 Map<Variable, Variable> mapping; 459 Map<Variable, Variable> mapping;
480 460
481 SubstituteVariables(this.mapping); 461 SubstituteVariables(this.mapping);
482 462
483 Variable replaceRead(Variable variable) { 463 Variable replaceRead(Variable variable) {
484 Variable w = mapping[variable]; 464 Variable w = mapping[variable];
485 if (w == null) return variable; // Skip ignored variables. 465 if (w == null) return variable; // Skip ignored variables.
486 w.readCount++; 466 w.readCount++;
487 variable.readCount--; 467 variable.readCount--;
488 return w; 468 return w;
489 } 469 }
490 470
491 Variable replaceWrite(Variable variable) { 471 Variable replaceWrite(Variable variable) {
492 Variable w = mapping[variable]; 472 Variable w = mapping[variable];
493 if (w == null) return variable; // Skip ignored variables. 473 if (w == null) return variable; // Skip ignored variables.
494 w.writeCount++; 474 w.writeCount++;
495 variable.writeCount--; 475 variable.writeCount--;
496 return w; 476 return w;
497 } 477 }
498 478
499 void replaceParameters(List<Variable> parameters) { 479 void apply(RootNode node) {
500 for (int i = 0; i < parameters.length; ++i) { 480 for (int i = 0; i < node.parameters.length; ++i) {
501 parameters[i] = replaceWrite(parameters[i]); 481 node.parameters[i] = replaceWrite(node.parameters[i]);
502 } 482 }
483 node.replaceEachBody(visitStatement);
503 } 484 }
504 485
505 visitVariableUse(VariableUse node) { 486 @override
506 node.variable = replaceRead(node.variable); 487 void visitInnerFunction(FunctionDefinition node) {
488 // Do nothing. Inner functions are traversed in VariableMerger.
507 } 489 }
508 490
509 visitFunctionDefinition(FunctionDefinition node) { 491 Expression visitVariableUse(VariableUse node) {
510 replaceParameters(node.parameters); 492 node.variable = replaceRead(node.variable);
511 node.body = visitStatement(node.body); 493 return node;
512 } 494 }
513 495
514 visitConstructorDefinition(ConstructorDefinition node) {
515 replaceParameters(node.parameters);
516 node.initializers.forEach(visitInitializer);
517 node.body = visitStatement(node.body);
518 }
519
520 visitFieldInitializer(FieldInitializer node) {
521 node.body = visitStatement(node.body);
522 }
523
524 visitSuperInitializer(SuperInitializer node) {
525 for (int i = 0; i<node.arguments.length; ++i) {
526 node.arguments[i] = visitStatement(node.arguments[i]);
527 }
528 }
529
530 // Statement visitors should return the transformed statement so we
531 // can remove redundant assignments.
532 Statement visitStatement(Statement node) => super.visitStatement(node);
533
534 Statement visitAssign(Assign node) { 496 Statement visitAssign(Assign node) {
535 node.variable = replaceWrite(node.variable); 497 node.variable = replaceWrite(node.variable);
536 498
537 visitExpression(node.value); 499 visitExpression(node.value);
538 node.next = visitStatement(node.next); 500 node.next = visitStatement(node.next);
539 501
540 // Remove assignments of form "x := x" 502 // Remove assignments of form "x := x"
541 if (node.value is VariableUse) { 503 if (node.value is VariableUse) {
542 VariableUse value = node.value; 504 VariableUse value = node.value;
543 if (value.variable == node.variable) { 505 if (value.variable == node.variable) {
544 value.variable.readCount--; 506 value.variable.readCount--;
545 node.variable.writeCount--; 507 node.variable.writeCount--;
546 return node.next; 508 return node.next;
547 } 509 }
548 } 510 }
549 511
550 return node; 512 return node;
551 } 513 }
552
553 Statement visitLabeledStatement(LabeledStatement node) {
554 node.body = visitStatement(node.body);
555 node.next = visitStatement(node.next);
556 return node;
557 }
558
559 Statement visitReturn(Return node) {
560 visitExpression(node.value);
561 return node;
562 }
563
564 Statement visitBreak(Break node) {
565 return node;
566 }
567
568 Statement visitContinue(Continue node) {
569 return node;
570 }
571
572 Statement visitIf(If node) {
573 visitExpression(node.condition);
574 node.thenStatement = visitStatement(node.thenStatement);
575 node.elseStatement = visitStatement(node.elseStatement);
576 return node;
577 }
578
579 Statement visitWhileTrue(WhileTrue node) {
580 node.body = visitStatement(node.body);
581 return node;
582 }
583
584 Statement visitWhileCondition(WhileCondition node) {
585 visitExpression(node.condition);
586 node.body = visitStatement(node.body);
587 node.next = visitStatement(node.next);
588 return node;
589 }
590
591 Statement visitFunctionDeclaration(FunctionDeclaration node) {
592 node.next = visitStatement(node.next);
593 return node;
594 }
595
596 Statement visitExpressionStatement(ExpressionStatement node) {
597 visitExpression(node.expression);
598 node.next = visitStatement(node.next);
599 return node;
600 }
601
602 Statement visitTry(Try node) {
603 node.tryBody = visitStatement(node.tryBody);
604 node.catchBody = visitStatement(node.catchBody);
605 return node;
606 }
607
608 Statement visitSetField(SetField node) {
609 visitExpression(node.object);
610 visitExpression(node.value);
611 node.next = visitStatement(node.next);
612 return node;
613 }
614 } 514 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/tree_ir/optimization/statement_rewriter.dart ('k') | pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698