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

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

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

Powered by Google App Engine
This is Rietveld 408576698