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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/cps_ir/redundant_phi.dart

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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 dart2js.optimizers;
6
7 /// Eliminate redundant phis from the given [FunctionDefinition].
8 ///
9 /// Phis in this case are [Continuations] together with corresponding
10 /// [InvokeContinuation]s. A [Continuation] parameter at position i is redundant
11 /// if for all [InvokeContinuation]s, the parameter at position i is identical
12 /// (except for feedback). Redundant parameters are removed from the
13 /// continuation signature, all invocations, and replaced within the
14 /// continuation body.
15 class RedundantPhiEliminator extends RecursiveVisitor implements Pass {
16 final Set<Continuation> workSet = new Set<Continuation>();
17
18 void rewrite(final FunctionDefinition root) {
19 if (root.isAbstract) return;
20
21 // Set all parent pointers.
22 new _ParentVisitor().visit(root);
23
24 // Traverse the tree once to build the work set.
25 visit(root);
26
27 // Process each continuation one-by-one.
28 while (workSet.isNotEmpty) {
29 Continuation cont = workSet.first;
30 workSet.remove(cont);
31
32 if (cont.isReturnContinuation) {
33 continue; // Skip function return continuations.
34 }
35
36 _processContinuation(cont);
37 }
38 }
39
40 /// Called for each continuation on the work set. Modifies the IR graph if
41 /// [cont] is a candidate for redundant phi elimination.
42 void _processContinuation(Continuation cont) {
43 // Generate the list of all cont invocations. If cont is used in any other
44 // context (i.e. as a continuation of InvokeMethod), it is not possible to
45 // optimize.
46 List<InvokeContinuation> invokes = <InvokeContinuation>[];
47 for (Reference ref = cont.firstRef; ref != null; ref = ref.next) {
48 Node parent = ref.parent;
49 if (parent is InvokeContinuation && ref == parent.continuation) {
50 invokes.add(parent);
51 } else {
52 return; // Can't optimize.
53 }
54 }
55
56 if (invokes.isEmpty) {
57 return; // Continuation is never invoked, can't optimize.
58 }
59
60 /// Returns the unique definition of parameter i if it exists and null
61 /// otherwise. A definition is unique if it is the only value used to
62 /// invoke the continuation, excluding feedback.
63 Definition uniqueDefinitionOf(int i) {
64 Definition value = null;
65 for (InvokeContinuation invoke in invokes) {
66 Definition def = invoke.arguments[i].definition;
67
68 if (cont.parameters[i] == def) {
69 // Invocation param == param in LetCont (i.e. a recursive call).
70 continue;
71 } else if (value == null) {
72 value = def; // Set initial comparison value.
73 } else if (value != def) {
74 return null; // Differing invocation arguments.
75 }
76 }
77
78 return value;
79 }
80
81 // Check if individual parameters are always called with a unique
82 // definition, and remove them if that is the case. During each iteration,
83 // we read the current parameter/argument from index `src` and copy it
84 // to index `dst`.
85 int dst = 0;
86 for (int src = 0; src < cont.parameters.length; src++) {
87 // Is the current phi redundant?
88 Definition uniqueDefinition = uniqueDefinitionOf(src);
89 if (uniqueDefinition == null) {
90 // Reorganize parameters and arguments in case of deletions.
91 cont.parameters[dst] = cont.parameters[src];
92 for (InvokeContinuation invoke in invokes) {
93 invoke.arguments[dst] = invoke.arguments[src];
94 }
95
96 dst++;
97 continue;
98 }
99
100 Definition oldDefinition = cont.parameters[src];
101
102 // Add continuations of about-to-be modified invokes to worklist since
103 // we might introduce new optimization opportunities.
104 for (Reference ref = oldDefinition.firstRef; ref != null;
105 ref = ref.next) {
106 Node parent = ref.parent;
107 if (parent is InvokeContinuation) {
108 Continuation thatCont = parent.continuation.definition;
109 if (thatCont != cont) {
110 workSet.add(thatCont);
111 }
112 }
113 }
114
115 // Replace individual parameters:
116 // * In the continuation body, replace occurrence of param with value,
117 // * and implicitly remove param from continuation signature and
118 // invocations by not incrementing `dst`. References of removed
119 // arguments are unlinked to keep definition usages up to date.
120 uniqueDefinition.substituteFor(oldDefinition);
121 for (InvokeContinuation invoke in invokes) {
122 invoke.arguments[src].unlink();
123 }
124
125 // Finally, if the substituted definition is not in scope of the affected
126 // continuation, move the continuation binding. This is safe to do since
127 // the continuation is referenced only as the target in continuation
128 // invokes, and all such invokes must be within the scope of
129 // [uniqueDefinition]. Note that this is linear in the depth of
130 // the binding of [uniqueDefinition].
131 LetCont letCont = cont.parent;
132 assert(letCont != null);
133 _moveIntoScopeOf(letCont, uniqueDefinition);
134 }
135
136 // Remove trailing items from parameter and argument lists.
137 cont.parameters.length = dst;
138 for (InvokeContinuation invoke in invokes) {
139 invoke.arguments.length = dst;
140 }
141 }
142
143 void processLetCont(LetCont node) {
144 workSet.add(node.continuation);
145 }
146 }
147
148 /// Returns true, iff [letCont] is not scope of [definition].
149 /// Linear in the depth of definition within the IR graph.
150 bool _isInScopeOf(LetCont letCont, Definition definition) {
151 for (Node node = definition.parent; node != null; node = node.parent) {
152 if (node == letCont) {
153 return false;
154 }
155 }
156
157 return true;
158 }
159
160 /// Moves [letCont] below the binding of [definition] within the IR graph.
161 /// Does nothing if [letCont] is already within the scope of [definition].
162 /// Assumes that one argument is nested within the scope of the other
163 /// when this method is called.
164 void _moveIntoScopeOf(LetCont letCont, Definition definition) {
165 if (_isInScopeOf(letCont, definition)) return;
166
167 // Remove the continuation binding from its current spot.
168 InteriorNode parent = letCont.parent;
169 parent.body = letCont.body;
170 letCont.body.parent = parent;
171
172 // Insert it just below the binding of definition.
173 InteriorNode binding = definition.parent;
174
175 letCont.body = binding.body;
176 binding.body.parent = letCont;
177
178 binding.body = letCont;
179 letCont.parent = binding;
180 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698