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

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

Issue 1007103003: cps-ir: Merge variables based on set-based liveness and graph coloring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 9 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of tree_ir.optimization;
6
7 /// Eliminates moving assignments, such as w := v, by assigning directly to w
8 /// at the definition of v.
9 ///
10 /// This compensates for suboptimal register allocation, and merges closure
11 /// variables with local temporaries that were left behind when translating
12 /// out of CPS (where closure variables live in a separate space).
13 class CopyPropagator extends RecursiveVisitor with PassMixin {
14 String get passName => 'Copy propagation';
15
16 /// After visitStatement returns, [move] maps a variable v to an
17 /// assignment A of form w := v, under the following conditions:
18 /// - there are no reads or writes of w before A
19 /// - A is the only use of v
20 Map<Variable, Assign> move = <Variable, Assign>{};
21
22 /// Like [move], except w is the key instead of v.
23 Map<Variable, Assign> inverseMove = <Variable, Assign>{};
24
25 ExecutableElement currentElement;
26
27 /// Number of try blocks enclosing the currently visited node.
28 int enclosingTrys = 0;
29
30 void rewriteExecutableDefinition(ExecutableDefinition root) {
31 currentElement = root.element;
32 root.body = visitStatement(root.body);
33 }
34
35 rewriteFunctionDefinition(FunctionDefinition node) {
36 if (node.isAbstract) return;
37 rewriteExecutableDefinition(node);
38
39 // Try to propagate moving assignments into function parameters.
40 // For example:
41 // foo(x) {
42 // var v1 = x;
43 // BODY
44 // }
45 // ==>
46 // foo(v1) {
47 // BODY
48 // }
49
50 // Variables must not occur more than once in the parameter list, so
51 // invalidate all moving assignments that would propagate a parameter
52 // into another parameter. For example:
53 // foo(x,y) {
54 // y = x;
55 // BODY
56 // }
57 // Cannot declare function as foo(x,x)!
58 node.parameters.forEach(invalidateMovingAssignment);
59
60 // Now do the propagation.
61 for (int i = 0; i < node.parameters.length; i++) {
62 Variable param = node.parameters[i];
63 Variable replacement = copyPropagateVariable(param);
64 replacement.element = param.element; // Preserve parameter name.
65 node.parameters[i] = replacement;
66 }
67 }
68
69 rewriteConstructorDefinition(ConstructorDefinition node) {
70 if (node.isAbstract) return;
71 node.initializers.forEach(visitExpression);
72 rewriteExecutableDefinition(node);
73
74
75 // Try to propagate moving assignments into function parameters.
76 // For example:
77 // foo(x) {
78 // var v1 = x;
79 // BODY
80 // }
81 // ==>
82 // foo(v1) {
83 // BODY
84 // }
85
86 // Variables must not occur more than once in the parameter list, so
87 // invalidate all moving assignments that would propagate a parameter
88 // into another parameter. For example:
89 // foo(x,y) {
90 // y = x;
91 // BODY
92 // }
93 // Cannot declare function as foo(x,x)!
94 node.parameters.forEach(invalidateMovingAssignment);
95
96 // Now do the propagation.
97 for (int i = 0; i < node.parameters.length; i++) {
98 Variable param = node.parameters[i];
99 Variable replacement = copyPropagateVariable(param);
100 replacement.element = param.element; // Preserve parameter name.
101 node.parameters[i] = replacement;
102 }
103
104 }
105
106
107 Statement visitBasicBlock(Statement node) {
108 node = visitStatement(node);
109 move.clear();
110 inverseMove.clear();
111 return node;
112 }
113
114 /// Remove an assignment of form [w] := v from the move maps.
115 void invalidateMovingAssignment(Variable w) {
116 Assign movingAssignment = inverseMove.remove(w);
117 if (movingAssignment != null) {
118 VariableUse value = movingAssignment.value;
119 move.remove(value.variable);
120 }
121 }
122
123 visitVariableUse(VariableUse node) {
124 // We found a use of w; we can't propagate assignments across this use.
125 invalidateMovingAssignment(node.variable);
126 }
127
128 /**
129 * Called when a definition of [v] is encountered.
130 * Attempts to propagate the assignment through a moving assignment.
131 * Returns the variable to be assigned into, defaulting to [v] itself if
132 * no optimization could be performed.
133 */
134 Variable copyPropagateVariable(Variable v) {
135 Assign movingAssign = move[v];
136 if (movingAssign != null) {
137 // We found the pattern:
138 // v := EXPR
139 // BLOCK (does not use w)
140 // w := v (only use of v)
141 //
142 // Rewrite to:
143 // w := EXPR
144 // BLOCK
145 // w := w (to be removed later)
146 Variable w = movingAssign.variable;
147
148 // Make w := w.
149 // We can't remove the statement from here because we don't have
150 // parent pointers. So just make it a no-op so it can be removed later.
151 movingAssign.value = new VariableUse(w);
152
153 // The intermediate variable 'v' should now be orphaned, so don't bother
154 // updating its read/write counters.
155
156 // Make w := EXPR
157 ++w.writeCount;
158 return w;
159 }
160 return v;
161 }
162
163 Statement visitAssign(Assign node) {
164 node.next = visitStatement(node.next);
165 node.variable = copyPropagateVariable(node.variable);
166
167 // If a moving assignment w := v exists later, and we assign to w here,
168 // the moving assignment is no longer a candidate for copy propagation.
169 invalidateMovingAssignment(node.variable);
170
171 visitExpression(node.value);
172
173 // If this is a moving assignment w := v, with this being the only use of v,
174 // try to propagate it backwards.
175 // Do not propagate assignments where w is captured or if where are inside a
176 // try block, because then we can't isolate the uses of w to a single block.
177 // We currently do not support propagation if the assignment is a
178 // declaration. To support this we would need to ensure that the target
179 // assignment is turned into a declaration as well.
180 if (node.value is VariableUse &&
181 !node.variable.isCaptured &&
182 enclosingTrys == 0 &&
183 !node.isDeclaration) {
184 VariableUse value = node.value;
185 if (value.variable.readCount == 1) {
186 move[value.variable] = node;
187 inverseMove[node.variable] = node;
188 }
189 }
190
191 return node;
192 }
193
194 Statement visitLabeledStatement(LabeledStatement node) {
195 node.next = visitBasicBlock(node.next);
196 node.body = visitStatement(node.body);
197 return node;
198 }
199
200 Statement visitReturn(Return node) {
201 visitExpression(node.value);
202 return node;
203 }
204
205 Statement visitBreak(Break node) {
206 return node;
207 }
208
209 Statement visitContinue(Continue node) {
210 return node;
211 }
212
213 Statement visitIf(If node) {
214 visitExpression(node.condition);
215 node.thenStatement = visitBasicBlock(node.thenStatement);
216 node.elseStatement = visitBasicBlock(node.elseStatement);
217 return node;
218 }
219
220 Statement visitWhileTrue(WhileTrue node) {
221 node.body = visitBasicBlock(node.body);
222 return node;
223 }
224
225 Statement visitWhileCondition(WhileCondition node) {
226 throw "WhileCondition before LoopRewriter";
227 }
228
229 Statement visitTry(Try node) {
230 enclosingTrys++;
231 node.tryBody = visitBasicBlock(node.tryBody);
232 enclosingTrys--;
233 node.catchBody = visitBasicBlock(node.catchBody);
234 return node;
235 }
236
237 Statement visitFunctionDeclaration(FunctionDeclaration node) {
238 // Unlike var declarations, function declarations are not hoisted, so we
239 // can't do copy propagation of the variable.
240 new CopyPropagator().rewrite(node.definition);
241 node.next = visitStatement(node.next);
242 return node;
243 }
244
245 Statement visitExpressionStatement(ExpressionStatement node) {
246 node.next = visitStatement(node.next);
247 visitExpression(node.expression);
248 return node;
249 }
250
251 Statement visitSetField(SetField node) {
252 node.next = visitStatement(node.next);
253 visitExpression(node.value);
254 visitExpression(node.object);
255 return node;
256 }
257
258 void visitFunctionExpression(FunctionExpression node) {
259 new CopyPropagator().rewrite(node.definition);
260 }
261
262 void visitFieldInitializer(FieldInitializer node) {
263 visitStatement(node.body);
264 }
265
266 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698