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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/path_based_optimizer.dart

Issue 2246623002: Delete CPS IR (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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
OLDNEW
(Empty)
1 // Copyright (c) 2016, 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 library dart2js.cps_ir.path_based_optimizer;
5
6 import '../js_backend/js_backend.dart';
7 import 'cps_fragment.dart';
8 import 'cps_ir_nodes.dart';
9 import 'optimizers.dart';
10 import 'type_mask_system.dart';
11
12 /// Optimizations based on intraprocedural forward dataflow analysis, taking
13 /// into account path information that is not expressed by [Refinement] nodes.
14 ///
15 /// ---
16 ///
17 /// Removes branches that branch on the same value as a previously seen branch.
18 /// For example:
19 ///
20 /// if (x == y) {
21 /// if (x == y) TRUE else FALSE
22 /// }
23 ///
24 /// ==> ([GVN] pass merges identical expressions)
25 ///
26 /// var b = (x == y)
27 /// if (b) {
28 /// if (b) TRUE else FALSE
29 /// }
30 ///
31 /// ==> (this pass removes the duplicate branch)
32 ///
33 /// var b = (x == y)
34 /// if (b) {
35 /// TRUE
36 /// }
37 ///
38 /// ---
39 ///
40 /// Removes interceptors for method calls whose receiver is known to be a
41 /// self-interceptor. For example:
42 ///
43 /// x.foo$1();
44 /// getInterceptor(x).$eq(x, y);
45 ///
46 /// ==> (`x` is a self-interceptor, remove the `getInterceptor` call)
47 ///
48 /// x.foo$1();
49 /// x.$eq(0, y);
50 ///
51 /// Although there is a [Refinement] node after the call to `x.foo$1()`, the
52 /// refined type cannot always be represented exactly, and type propagation
53 /// may therefore not see that `x` is a self-interceptor.
54 //
55 // TODO(asgerf): A kind of redundant join can arise where a branching condition
56 // is known to be true/false on all but one predecessor for a branch. We could
57 // try to reduce those.
58 //
59 // TODO(asgerf): Could be more precise if GVN shared expressions that are not
60 // in direct scope of one another, e.g. by using phis pass the shared value.
61 //
62 class PathBasedOptimizer extends TrampolineRecursiveVisitor implements Pass {
63 String get passName => 'Path-based optimizations';
64
65 // Classification of all values.
66 static const int TRUE = 1 << 0;
67 static const int SELF_INTERCEPTOR = 1 << 1;
68 static const int INTERCEPTED_TRUTHY = 1 << 2;
69 static const int FALSE = 1 << 3;
70 static const int OTHER_FALSY = 1 << 4;
71
72 static const int TRUTHY = TRUE | SELF_INTERCEPTOR | INTERCEPTED_TRUTHY;
73 static const int FALSY = FALSE | OTHER_FALSY;
74 static const int ANY = TRUTHY | FALSY;
75
76 final JavaScriptBackend backend;
77 final TypeMaskSystem typeSystem;
78
79 PathBasedOptimizer(this.backend, this.typeSystem);
80
81 /// The possible values of the given primitive (or ANY if absent) at the
82 /// current traversal position.
83 Map<Primitive, int> valueOf = <Primitive, int>{};
84
85 /// The possible values of each primitive at the entry to a continuation.
86 ///
87 /// Unreachable continuations are absent from the map.
88 final Map<Continuation, Map<Primitive, int>> valuesAt =
89 <Continuation, Map<Primitive, int>>{};
90
91 void rewrite(FunctionDefinition node) {
92 visit(node);
93 }
94
95 Map<Primitive, int> copy(Map<Primitive, int> map) {
96 return new Map<Primitive, int>.from(map);
97 }
98
99 Expression traverseLetHandler(LetHandler node) {
100 valuesAt[node.handler] = copy(valueOf);
101 push(node.handler);
102 return node.body;
103 }
104
105 Expression traverseContinuation(Continuation cont) {
106 valueOf = valuesAt[cont];
107 if (valueOf == null) {
108 // Do not go into unreachable code.
109 destroyAndReplace(cont.body, new Unreachable());
110 }
111 return cont.body;
112 }
113
114 void visitInvokeContinuation(InvokeContinuation node) {
115 Continuation cont = node.continuation;
116 if (cont.isReturnContinuation) return;
117 if (node.isRecursive) return;
118 Map<Primitive, int> target = valuesAt[cont];
119 if (target == null) {
120 valuesAt[cont] = valueOf;
121 } else {
122 for (Primitive prim in target.keys) {
123 target[prim] |= valueOf[prim] ?? ANY;
124 }
125 }
126 }
127
128 visitBranch(Branch node) {
129 Primitive condition = node.condition.effectiveDefinition;
130 Continuation trueCont = node.trueContinuation;
131 Continuation falseCont = node.falseContinuation;
132 if (condition.hasExactlyOneUse) {
133 // Handle common case specially. Do not add [condition] to the map if
134 // there are no other uses.
135 valuesAt[trueCont] = copy(valueOf);
136 valuesAt[falseCont] = valueOf;
137 return;
138 }
139 int values = valueOf[condition] ?? ANY;
140 int positiveValues = node.isStrictCheck ? TRUE : TRUTHY;
141 int negativeValues = (~positiveValues) & ANY;
142 if (values & positiveValues == 0) {
143 destroyAndReplace(node, new InvokeContinuation(falseCont, []));
144 valuesAt[falseCont] = valueOf;
145 } else if (values & negativeValues == 0) {
146 destroyAndReplace(node, new InvokeContinuation(trueCont, []));
147 valuesAt[trueCont] = valueOf;
148 } else {
149 valuesAt[trueCont] = copy(valueOf)..[condition] = values & positiveValues;
150 valuesAt[falseCont] = valueOf..[condition] = values & negativeValues;
151 }
152 }
153
154 void visitInvokeMethod(InvokeMethod node) {
155 int receiverValue = valueOf[node.receiver] ?? ANY;
156 if (!backend.isInterceptedSelector(node.selector)) {
157 // Only self-interceptors can respond to a non-intercepted selector.
158 valueOf[node.receiver] = receiverValue & SELF_INTERCEPTOR;
159 } else if (receiverValue & ~SELF_INTERCEPTOR == 0 &&
160 node.callingConvention == CallingConvention.Intercepted) {
161 // This is an intercepted call whose receiver is definitely a
162 // self-interceptor.
163 // TODO(25646): If TypeMasks could represent "any self-interceptor" this
164 // optimization should be subsumed by type propagation.
165 node.interceptorRef.changeTo(node.receiver);
166
167 // Replace the extra receiver argument with a dummy value if the
168 // target definitely does not use it.
169 if (typeSystem.targetIgnoresReceiverArgument(
170 node.receiver.type, node.selector)) {
171 node.makeDummyIntercepted();
172 }
173 }
174 }
175 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/parent_visitor.dart ('k') | pkg/compiler/lib/src/cps_ir/redundant_join.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698