OLD | NEW |
| (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 import 'sexpr_unstringifier.dart'; | |
6 import "package:expect/expect.dart"; | |
7 import 'package:compiler/src/cps_ir/cps_ir_nodes.dart'; | |
8 import 'package:compiler/src/cps_ir/cps_ir_nodes_sexpr.dart'; | |
9 import 'package:compiler/src/cps_ir/optimizers.dart'; | |
10 | |
11 // The 'read in loop' IR tests the most basic case of redundant phi removal | |
12 // and represents the following source code: | |
13 // | |
14 // void main() { | |
15 // int j = 42; | |
16 // for (int i = 0; i < 2; i++) { | |
17 // print(j.toString()); | |
18 // } | |
19 // } | |
20 | |
21 String READ_IN_LOOP_IN = """ | |
22 (FunctionDefinition main () () return | |
23 (LetPrim (v0 (Constant (Int 42))) | |
24 (LetPrim (v1 (Constant (Int 0))) | |
25 (LetCont | |
26 ((rec k0 (v2 v3) | |
27 (LetCont | |
28 ((k1 () | |
29 (LetPrim (v4 (Constant (Null))) | |
30 (InvokeContinuation return (v4)))) | |
31 (k2 () | |
32 (LetCont | |
33 ((k3 (v5) | |
34 (LetCont | |
35 ((k4 (v6) | |
36 (LetPrim (v7 (Constant (Int 1))) | |
37 (LetCont | |
38 ((k5 (v8) | |
39 (InvokeContinuation rec k0 (v2 v8)))) | |
40 (InvokeMethod v3 + (v7) k5))))) | |
41 (InvokeStatic print (v5) k4)))) | |
42 (InvokeMethod v2 toString () k3)))) | |
43 (LetPrim (v9 (Constant (Int 2))) | |
44 (LetCont | |
45 ((k6 (v10) | |
46 (Branch (IsTrue v10) k2 k1))) | |
47 (InvokeMethod v3 < (v9) k6)))))) | |
48 (InvokeContinuation k0 (v0 v1)))))) | |
49 """; | |
50 | |
51 String READ_IN_LOOP_OUT = """ | |
52 (FunctionDefinition main () () return | |
53 (LetPrim (v0 (Constant (Int 42))) | |
54 (LetPrim (v1 (Constant (Int 0))) | |
55 (LetCont | |
56 ((rec k0 (v2) | |
57 (LetCont | |
58 ((k1 () | |
59 (LetPrim (v3 (Constant (Null))) | |
60 (InvokeContinuation return (v3)))) | |
61 (k2 () | |
62 (LetCont | |
63 ((k3 (v4) | |
64 (LetCont | |
65 ((k4 (v5) | |
66 (LetPrim (v6 (Constant (Int 1))) | |
67 (LetCont | |
68 ((k5 (v7) | |
69 (InvokeContinuation rec k0 (v7)))) | |
70 (InvokeMethod v2 + (v6) k5))))) | |
71 (InvokeStatic print (v4) k4)))) | |
72 (InvokeMethod v0 toString () k3)))) | |
73 (LetPrim (v8 (Constant (Int 2))) | |
74 (LetCont | |
75 ((k6 (v9) | |
76 (Branch (IsTrue v9) k2 k1))) | |
77 (InvokeMethod v2 < (v8) k6)))))) | |
78 (InvokeContinuation k0 (v1)))))) | |
79 """; | |
80 | |
81 // The 'inner loop' IR represents the following source code: | |
82 // | |
83 // void main() { | |
84 // int j = 42; | |
85 // for (int i = 0; i < 2; i++) { | |
86 // for (int k = 0; k < 2; k++) { | |
87 // print(i.toString()); | |
88 // } | |
89 // } | |
90 // print(j.toString()); | |
91 // } | |
92 // | |
93 // This test case ensures that iterative optimization works: first, v8 and v9 | |
94 // are removed from k5, and only then can k0 be optimized as well. | |
95 | |
96 const String INNER_LOOP_IN = """ | |
97 (FunctionDefinition main () () return | |
98 (LetPrim (v0 (Constant (Int 42))) | |
99 (LetPrim (v1 (Constant (Int 0))) | |
100 (LetCont | |
101 ((rec k0 (v2 v3) | |
102 (LetCont | |
103 ((k1 () | |
104 (LetCont | |
105 ((k2 (v4) | |
106 (LetCont | |
107 ((k3 (v5) | |
108 (LetPrim (v6 (Constant (Null))) | |
109 (InvokeContinuation return (v6))))) | |
110 (InvokeStatic print (v4) k3)))) | |
111 (InvokeMethod v2 toString () k2))) | |
112 (k4 () | |
113 (LetPrim (v7 (Constant (Int 0))) | |
114 (LetCont | |
115 ((rec k5 (v8 v9 v10) | |
116 (LetCont | |
117 ((k6 () | |
118 (LetPrim (v11 (Constant (Int 1))) | |
119 (LetCont | |
120 ((k7 (v12) | |
121 (InvokeContinuation rec k0 (v8 v12)
))) | |
122 (InvokeMethod v9 + (v11) k7)))) | |
123 (k8 () | |
124 (LetCont | |
125 ((k9 (v13) | |
126 (LetCont | |
127 ((k10 (v14) | |
128 (LetPrim (v15 (Constant (Int 1
))) | |
129 (LetCont | |
130 ((k11 (v16) | |
131 (InvokeContinuation r
ec k5 (v8 v9 v16)))) | |
132 (InvokeMethod v10 + (v15)
k11))))) | |
133 (InvokeStatic print (v13) k10)))) | |
134 (InvokeMethod v9 toString () k9)))) | |
135 (LetPrim (v17 (Constant (Int 2))) | |
136 (LetCont | |
137 ((k12 (v18) | |
138 (Branch (IsTrue v18) k8 k6))) | |
139 (InvokeMethod v10 < (v17) k12)))))) | |
140 (InvokeContinuation k5 (v2 v3 v7)))))) | |
141 (LetPrim (v19 (Constant (Int 2))) | |
142 (LetCont | |
143 ((k13 (v20) | |
144 (Branch (IsTrue v20) k4 k1))) | |
145 (InvokeMethod v3 < (v19) k13)))))) | |
146 (InvokeContinuation k0 (v0 v1)))))) | |
147 """; | |
148 | |
149 const String INNER_LOOP_OUT = """ | |
150 (FunctionDefinition main () () return | |
151 (LetPrim (v0 (Constant (Int 42))) | |
152 (LetPrim (v1 (Constant (Int 0))) | |
153 (LetCont | |
154 ((rec k0 (v2) | |
155 (LetCont | |
156 ((k1 () | |
157 (LetCont | |
158 ((k2 (v3) | |
159 (LetCont | |
160 ((k3 (v4) | |
161 (LetPrim (v5 (Constant (Null))) | |
162 (InvokeContinuation return (v5))))) | |
163 (InvokeStatic print (v3) k3)))) | |
164 (InvokeMethod v0 toString () k2))) | |
165 (k4 () | |
166 (LetPrim (v6 (Constant (Int 0))) | |
167 (LetCont | |
168 ((rec k5 (v7) | |
169 (LetCont | |
170 ((k6 () | |
171 (LetPrim (v8 (Constant (Int 1))) | |
172 (LetCont | |
173 ((k7 (v9) | |
174 (InvokeContinuation rec k0 (v9)))) | |
175 (InvokeMethod v2 + (v8) k7)))) | |
176 (k8 () | |
177 (LetCont | |
178 ((k9 (v10) | |
179 (LetCont | |
180 ((k10 (v11) | |
181 (LetPrim (v12 (Constant (Int 1
))) | |
182 (LetCont | |
183 ((k11 (v13) | |
184 (InvokeContinuation r
ec k5 (v13)))) | |
185 (InvokeMethod v7 + (v12) k
11))))) | |
186 (InvokeStatic print (v10) k10)))) | |
187 (InvokeMethod v2 toString () k9)))) | |
188 (LetPrim (v14 (Constant (Int 2))) | |
189 (LetCont | |
190 ((k12 (v15) | |
191 (Branch (IsTrue v15) k8 k6))) | |
192 (InvokeMethod v7 < (v14) k12)))))) | |
193 (InvokeContinuation k5 (v6)))))) | |
194 (LetPrim (v16 (Constant (Int 2))) | |
195 (LetCont | |
196 ((k13 (v17) | |
197 (Branch (IsTrue v17) k4 k1))) | |
198 (InvokeMethod v2 < (v16) k13)))))) | |
199 (InvokeContinuation k0 (v1)))))) | |
200 """; | |
201 | |
202 // There are no redundant phis in the 'basic loop' IR, and this test ensures | |
203 // simply that the optimization does not alter the IR. It represents the | |
204 // following program: | |
205 // | |
206 // void main() { | |
207 // for (int i = 0; i < 2; i++) { | |
208 // print(i.toString()); | |
209 // } | |
210 // } | |
211 | |
212 String BASIC_LOOP_IN = """ | |
213 (FunctionDefinition main () () return | |
214 (LetPrim (v0 (Constant (Int 0))) | |
215 (LetCont | |
216 ((rec k0 (v1) | |
217 (LetCont | |
218 ((k1 () | |
219 (LetPrim (v2 (Constant (Null))) | |
220 (InvokeContinuation return (v2)))) | |
221 (k2 () | |
222 (LetCont | |
223 ((k3 (v3) | |
224 (LetCont | |
225 ((k4 (v4) | |
226 (LetPrim (v5 (Constant (Int 1))) | |
227 (LetCont | |
228 ((k5 (v6) | |
229 (InvokeContinuation rec k0 (v6)))) | |
230 (InvokeMethod v1 + (v5) k5))))) | |
231 (InvokeStatic print (v3) k4)))) | |
232 (InvokeMethod v1 toString () k3)))) | |
233 (LetPrim (v7 (Constant (Int 2))) | |
234 (LetCont | |
235 ((k6 (v8) | |
236 (Branch (IsTrue v8) k2 k1))) | |
237 (InvokeMethod v1 < (v7) k6)))))) | |
238 (InvokeContinuation k0 (v0))))) | |
239 """; | |
240 | |
241 String BASIC_LOOP_OUT = BASIC_LOOP_IN; | |
242 | |
243 // Ensures that proper scoping is preserved, i.e. that the optimized | |
244 // continuation body does reference out of scope primitives. | |
245 // IR written by hand since this case is currently not being generated. | |
246 | |
247 String SCOPING_IN = """ | |
248 (FunctionDefinition main () () return | |
249 (LetCont | |
250 ((k0 (v1) | |
251 (InvokeStatic print (v1) return))) | |
252 (LetPrim (v0 (Constant (Int 0))) | |
253 (LetPrim (v2 (Constant (Null))) | |
254 (InvokeContinuation k0 (v0)))))) | |
255 """; | |
256 | |
257 String SCOPING_OUT = """ | |
258 (FunctionDefinition main () () return | |
259 (LetPrim (v0 (Constant (Int 0))) | |
260 (LetCont | |
261 ((k0 () | |
262 (InvokeStatic print (v0) return))) | |
263 (LetPrim (v1 (Constant (Null))) | |
264 (InvokeContinuation k0 ()))))) | |
265 """; | |
266 | |
267 // Ensures that continuations which are never invoked are not optimized. | |
268 // IR written by hand. | |
269 | |
270 String NEVER_INVOKED_IN = """ | |
271 (FunctionDefinition main () () return | |
272 (LetPrim (v0 (Constant (Int 0))) | |
273 (LetCont | |
274 ((k0 (v1) | |
275 (InvokeStatic print (v1) return))) | |
276 (InvokeContinuation return (v0))))) | |
277 """; | |
278 | |
279 String NEVER_INVOKED_OUT = NEVER_INVOKED_IN; | |
280 | |
281 /// Normalizes whitespace by replacing all whitespace sequences by a single | |
282 /// space and trimming leading and trailing whitespace. | |
283 String normalizeSExpr(String input) { | |
284 return input.replaceAll(new RegExp(r'[ \n\t]+'), ' ').trim(); | |
285 } | |
286 | |
287 /// Parses the given input IR, runs a redundant phi pass over it, and compares | |
288 /// the stringification of the result against the expected output. | |
289 void testRedundantPhi(String input, String expectedOutput) { | |
290 final unstringifier = new SExpressionUnstringifier(); | |
291 final stringifier = new SExpressionStringifier(); | |
292 final optimizer = new RedundantPhiEliminator(); | |
293 | |
294 FunctionDefinition f = unstringifier.unstringify(input); | |
295 optimizer.rewrite(f); | |
296 | |
297 String expected = normalizeSExpr(expectedOutput); | |
298 String actual = normalizeSExpr(stringifier.visit(f)); | |
299 | |
300 Expect.equals(expected, actual, "Actual:\n$actual"); | |
301 } | |
302 | |
303 void main() { | |
304 testRedundantPhi(READ_IN_LOOP_IN, READ_IN_LOOP_OUT); | |
305 testRedundantPhi(INNER_LOOP_IN, INNER_LOOP_OUT); | |
306 testRedundantPhi(BASIC_LOOP_IN, BASIC_LOOP_OUT); | |
307 testRedundantPhi(SCOPING_IN, SCOPING_OUT); | |
308 testRedundantPhi(NEVER_INVOKED_IN, NEVER_INVOKED_OUT); | |
309 } | |
OLD | NEW |