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

Side by Side Diff: test/unittests/compiler/loop-peeling-unittest.cc

Issue 816053002: [turbofan] First version of loop peeling. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 11 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 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "src/compiler/access-builder.h"
6 #include "src/compiler/graph.h"
7 #include "src/compiler/graph-visualizer.h"
8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/js-operator.h"
10 #include "src/compiler/js-typed-lowering.h"
11 #include "src/compiler/loop-peeling.h"
12 #include "src/compiler/machine-operator.h"
13 #include "src/compiler/node.h"
14 #include "src/compiler/node-properties-inl.h"
15 #include "test/unittests/compiler/compiler-test-utils.h"
16 #include "test/unittests/compiler/graph-unittest.h"
17 #include "test/unittests/compiler/node-test-utils.h"
18 #include "testing/gmock-support.h"
19
20 using testing::AllOf;
21 using testing::BitEq;
22 using testing::Capture;
23 using testing::CaptureEq;
24
25 namespace v8 {
26 namespace internal {
27 namespace compiler {
28
29 class LoopPeelingTest : public GraphTest {
30 public:
31 LoopPeelingTest() : GraphTest(1), machine_(zone()) {}
32 ~LoopPeelingTest() OVERRIDE {}
33
34 protected:
35 MachineOperatorBuilder machine_;
36
37 MachineOperatorBuilder* machine() { return &machine_; }
38
39 LoopTree* GetLoopTree() {
40 if (FLAG_trace_turbo_graph) {
41 OFStream os(stdout);
42 os << AsRPO(*graph());
43 }
44 Zone zone(isolate());
45 return LoopFinder::BuildLoopTree(graph(), &zone);
46 }
47
48
49 PeeledIteration* PeelOne() {
50 LoopTree* loop_tree = GetLoopTree();
51 return Peel(loop_tree, loop_tree->outer_loops()[0]);
52 }
53
54 PeeledIteration* Peel(LoopTree* loop_tree, LoopTree::Loop* loop) {
55 PeeledIteration* peeled =
56 LoopPeeler::Peel(graph(), common(), loop_tree, loop, zone());
57 if (FLAG_trace_turbo_graph) {
58 OFStream os(stdout);
59 os << AsRPO(*graph());
60 }
61 return peeled;
62 }
63
64 Node* InsertReturn(Node* val, Node* effect, Node* control) {
65 Node* r = graph()->NewNode(common()->Return(), val, effect, control);
66 graph()->SetEnd(r);
67 return r;
68 }
69
70 Node* ExpectPeeled(Node* node, PeeledIteration* iter) {
71 Node* p = iter->map(node);
72 EXPECT_NE(node, p);
73 return p;
74 }
75
76 void ExpectNotPeeled(Node* node, PeeledIteration* iter) {
77 EXPECT_EQ(node, iter->map(node));
78 }
79 };
80
81
82 TEST_F(LoopPeelingTest, SimpleLoop) {
83 Node* p0 = Parameter(0);
84 While w(this, p0);
85 Node* r = InsertReturn(p0, start(), w.exit);
86
87 PeeledIteration* peeled = PeelOne();
88
89 Node* br1 = ExpectPeeled(w.branch, peeled);
90 Node* if_true1 = ExpectPeeled(w.if_true, peeled);
91 Node* if_false1 = ExpectPeeled(w.exit, peeled);
92
93 EXPECT_THAT(br1, IsBranch(p0, start()));
94 EXPECT_THAT(if_true1, IsIfTrue(br1));
95 EXPECT_THAT(if_false1, IsIfFalse(br1));
96
97 EXPECT_THAT(w.loop, IsLoop(if_true1, w.if_true));
98 EXPECT_THAT(r, IsReturn(p0, start(), IsMerge(w.exit, if_false1)));
99 }
100
101
102 TEST_F(LoopPeelingTest, SimpleLoopWithCounter) {
103 Node* p0 = Parameter(0);
104 While w(this, p0);
105 Counter c(w, machine(), 0, 1);
106 Node* r = InsertReturn(c.phi, start(), w.exit);
107
108 PeeledIteration* peeled = PeelOne();
109
110 Node* br1 = ExpectPeeled(w.branch, peeled);
111 Node* if_true1 = ExpectPeeled(w.if_true, peeled);
112 Node* if_false1 = ExpectPeeled(w.exit, peeled);
113
114 EXPECT_THAT(br1, IsBranch(p0, start()));
115 EXPECT_THAT(if_true1, IsIfTrue(br1));
116 EXPECT_THAT(if_false1, IsIfFalse(br1));
117 EXPECT_THAT(w.loop, IsLoop(if_true1, w.if_true));
118
119 EXPECT_THAT(peeled->map(c.add), IsInt32Add(c.base, c.inc));
120
121 Capture<Node*> merge;
122 EXPECT_THAT(
123 r, IsReturn(IsPhi(kMachAnyTagged, c.phi, c.base,
124 AllOf(CaptureEq(&merge), IsMerge(w.exit, if_false1))),
125 start(), CaptureEq(&merge)));
126 }
127
128
129 TEST_F(LoopPeelingTest, SimpleNestedLoopWithCounter_peel_outer) {
130 Node* p0 = Parameter(0);
131 While outer(this, p0);
132 While inner(this, p0);
133 inner.Nest(&outer);
134
135 Counter c(outer, machine(), 0, 1);
136 Node* r = InsertReturn(c.phi, start(), outer.exit);
137
138 PeeledIteration* peeled = PeelOne();
139
140 Node* bro = ExpectPeeled(outer.branch, peeled);
141 Node* if_trueo = ExpectPeeled(outer.if_true, peeled);
142 Node* if_falseo = ExpectPeeled(outer.exit, peeled);
143
144 EXPECT_THAT(bro, IsBranch(p0, start()));
145 EXPECT_THAT(if_trueo, IsIfTrue(bro));
146 EXPECT_THAT(if_falseo, IsIfFalse(bro));
147
148 Node* bri = ExpectPeeled(inner.branch, peeled);
149 Node* if_truei = ExpectPeeled(inner.if_true, peeled);
150 Node* if_falsei = ExpectPeeled(inner.exit, peeled);
151
152 EXPECT_THAT(bri, IsBranch(p0, ExpectPeeled(inner.loop, peeled)));
153 EXPECT_THAT(if_truei, IsIfTrue(bri));
154 EXPECT_THAT(if_falsei, IsIfFalse(bri));
155
156 EXPECT_THAT(outer.loop, IsLoop(if_falsei, inner.exit));
157 EXPECT_THAT(peeled->map(c.add), IsInt32Add(c.base, c.inc));
158
159 Capture<Node*> merge;
160 EXPECT_THAT(
161 r,
162 IsReturn(IsPhi(kMachAnyTagged, c.phi, c.base,
163 AllOf(CaptureEq(&merge), IsMerge(outer.exit, if_falseo))),
164 start(), CaptureEq(&merge)));
165 }
166
167
168 TEST_F(LoopPeelingTest, SimpleNestedLoopWithCounter_peel_inner) {
169 Node* p0 = Parameter(0);
170 While outer(this, p0);
171 While inner(this, p0);
172 inner.Nest(&outer);
173
174 Counter c(outer, machine(), 0, 1);
175 Node* r = InsertReturn(c.phi, start(), outer.exit);
176
177 LoopTree* loop_tree = GetLoopTree();
178 LoopTree::Loop* loop = loop_tree->ContainingLoop(inner.loop);
179 EXPECT_NE(nullptr, loop);
180 EXPECT_EQ(1, loop->depth());
181
182 PeeledIteration* peeled = Peel(loop_tree, loop);
183
184 ExpectNotPeeled(outer.loop, peeled);
185 ExpectNotPeeled(outer.branch, peeled);
186 ExpectNotPeeled(outer.if_true, peeled);
187 ExpectNotPeeled(outer.exit, peeled);
188
189 Node* bri = ExpectPeeled(inner.branch, peeled);
190 Node* if_truei = ExpectPeeled(inner.if_true, peeled);
191 Node* if_falsei = ExpectPeeled(inner.exit, peeled);
192
193 EXPECT_THAT(bri, IsBranch(p0, ExpectPeeled(inner.loop, peeled)));
194 EXPECT_THAT(if_truei, IsIfTrue(bri));
195 EXPECT_THAT(if_falsei, IsIfFalse(bri));
196
197 EXPECT_THAT(outer.loop, IsLoop(start(), IsMerge(inner.exit, if_falsei)));
198 ExpectNotPeeled(c.add, peeled);
199
200 EXPECT_THAT(r, IsReturn(c.phi, start(), outer.exit));
201 }
202
203
204 TEST_F(LoopPeelingTest, SimpleInnerCounter_peel_inner) {
205 Node* p0 = Parameter(0);
206 While outer(this, p0);
207 While inner(this, p0);
208 inner.Nest(&outer);
209 Counter c(inner, machine(), 0, 1);
210 Node* phi = outer.Phi(Int32Constant(11), c.phi);
211
212 Node* r = InsertReturn(phi, start(), outer.exit);
213
214 LoopTree* loop_tree = GetLoopTree();
215 LoopTree::Loop* loop = loop_tree->ContainingLoop(inner.loop);
216 EXPECT_NE(nullptr, loop);
217 EXPECT_EQ(1, loop->depth());
218
219 PeeledIteration* peeled = Peel(loop_tree, loop);
220
221 ExpectNotPeeled(outer.loop, peeled);
222 ExpectNotPeeled(outer.branch, peeled);
223 ExpectNotPeeled(outer.if_true, peeled);
224 ExpectNotPeeled(outer.exit, peeled);
225
226 Node* bri = ExpectPeeled(inner.branch, peeled);
227 Node* if_truei = ExpectPeeled(inner.if_true, peeled);
228 Node* if_falsei = ExpectPeeled(inner.exit, peeled);
229
230 EXPECT_THAT(bri, IsBranch(p0, ExpectPeeled(inner.loop, peeled)));
231 EXPECT_THAT(if_truei, IsIfTrue(bri));
232 EXPECT_THAT(if_falsei, IsIfFalse(bri));
233
234 EXPECT_THAT(outer.loop, IsLoop(start(), IsMerge(inner.exit, if_falsei)));
235 EXPECT_THAT(peeled->map(c.add), IsInt32Add(c.base, c.inc));
236
237 Node* back = phi->InputAt(1);
238 EXPECT_THAT(back, IsPhi(kMachAnyTagged, c.phi, c.base,
239 IsMerge(inner.exit, if_falsei)));
240
241 EXPECT_THAT(phi,
242 IsPhi(kMachAnyTagged, IsInt32Constant(11), back, outer.loop));
243
244 EXPECT_THAT(r, IsReturn(phi, start(), outer.exit));
245 }
246
247
248 TEST_F(LoopPeelingTest, TwoBackedgeLoop) {
249 Node* p0 = Parameter(0);
250 Node* loop = graph()->NewNode(common()->Loop(3), start(), start(), start());
251 Branch b1(this, p0, loop);
252 Branch b2(this, p0, b1.if_true);
253
254 loop->ReplaceInput(1, b2.if_true);
255 loop->ReplaceInput(2, b2.if_false);
256
257 Node* r = InsertReturn(p0, start(), b1.if_false);
258
259 PeeledIteration* peeled = PeelOne();
260
261 Node* b1b = ExpectPeeled(b1.branch, peeled);
262 Node* b1t = ExpectPeeled(b1.if_true, peeled);
263 Node* b1f = ExpectPeeled(b1.if_false, peeled);
264
265 EXPECT_THAT(b1b, IsBranch(p0, start()));
266 EXPECT_THAT(ExpectPeeled(b1.if_true, peeled), IsIfTrue(b1b));
267 EXPECT_THAT(b1f, IsIfFalse(b1b));
268
269 Node* b2b = ExpectPeeled(b2.branch, peeled);
270 Node* b2t = ExpectPeeled(b2.if_true, peeled);
271 Node* b2f = ExpectPeeled(b2.if_false, peeled);
272
273 EXPECT_THAT(b2b, IsBranch(p0, b1t));
274 EXPECT_THAT(b2t, IsIfTrue(b2b));
275 EXPECT_THAT(b2f, IsIfFalse(b2b));
276
277 EXPECT_THAT(loop, IsLoop(IsMerge(b2t, b2f), b2.if_true, b2.if_false));
278 EXPECT_THAT(r, IsReturn(p0, start(), IsMerge(b1.if_false, b1f)));
279 }
280
281
282 TEST_F(LoopPeelingTest, TwoBackedgeLoopWithPhi) {
283 Node* p0 = Parameter(0);
284 Node* loop = graph()->NewNode(common()->Loop(3), start(), start(), start());
285 Branch b1(this, p0, loop);
286 Branch b2(this, p0, b1.if_true);
287 Node* phi =
288 graph()->NewNode(common()->Phi(kMachAnyTagged, 3), Int32Constant(0),
289 Int32Constant(1), Int32Constant(2), loop);
290
291 loop->ReplaceInput(1, b2.if_true);
292 loop->ReplaceInput(2, b2.if_false);
293
294 Node* r = InsertReturn(phi, start(), b1.if_false);
295
296 PeeledIteration* peeled = PeelOne();
297
298 Node* b1b = ExpectPeeled(b1.branch, peeled);
299 Node* b1t = ExpectPeeled(b1.if_true, peeled);
300 Node* b1f = ExpectPeeled(b1.if_false, peeled);
301
302 EXPECT_THAT(b1b, IsBranch(p0, start()));
303 EXPECT_THAT(ExpectPeeled(b1.if_true, peeled), IsIfTrue(b1b));
304 EXPECT_THAT(b1f, IsIfFalse(b1b));
305
306 Node* b2b = ExpectPeeled(b2.branch, peeled);
307 Node* b2t = ExpectPeeled(b2.if_true, peeled);
308 Node* b2f = ExpectPeeled(b2.if_false, peeled);
309
310 EXPECT_THAT(b2b, IsBranch(p0, b1t));
311 EXPECT_THAT(b2t, IsIfTrue(b2b));
312 EXPECT_THAT(b2f, IsIfFalse(b2b));
313
314 EXPECT_THAT(loop, IsLoop(IsMerge(b2t, b2f), b2.if_true, b2.if_false));
315
316 EXPECT_THAT(
317 phi, IsPhi(kMachAnyTagged, IsPhi(kMachAnyTagged, IsInt32Constant(1),
318 IsInt32Constant(2), IsMerge(b2t, b2f)),
319 IsInt32Constant(1), IsInt32Constant(2), loop));
320
321 Capture<Node*> merge;
322 EXPECT_THAT(
323 r, IsReturn(IsPhi(kMachAnyTagged, phi, IsInt32Constant(0),
324 AllOf(CaptureEq(&merge), IsMerge(b1.if_false, b1f))),
325 start(), CaptureEq(&merge)));
326 }
327
328
329 TEST_F(LoopPeelingTest, TwoBackedgeLoopWithCounter) {
330 Node* p0 = Parameter(0);
331 Node* loop = graph()->NewNode(common()->Loop(3), start(), start(), start());
332 Branch b1(this, p0, loop);
333 Branch b2(this, p0, b1.if_true);
334 Node* phi =
335 graph()->NewNode(common()->Phi(kMachAnyTagged, 3), Int32Constant(0),
336 Int32Constant(1), Int32Constant(2), loop);
337
338 phi->ReplaceInput(
339 1, graph()->NewNode(machine()->Int32Add(), phi, Int32Constant(1)));
340 phi->ReplaceInput(
341 2, graph()->NewNode(machine()->Int32Add(), phi, Int32Constant(2)));
342
343 loop->ReplaceInput(1, b2.if_true);
344 loop->ReplaceInput(2, b2.if_false);
345
346 Node* r = InsertReturn(phi, start(), b1.if_false);
347
348 PeeledIteration* peeled = PeelOne();
349
350 Node* b1b = ExpectPeeled(b1.branch, peeled);
351 Node* b1t = ExpectPeeled(b1.if_true, peeled);
352 Node* b1f = ExpectPeeled(b1.if_false, peeled);
353
354 EXPECT_THAT(b1b, IsBranch(p0, start()));
355 EXPECT_THAT(ExpectPeeled(b1.if_true, peeled), IsIfTrue(b1b));
356 EXPECT_THAT(b1f, IsIfFalse(b1b));
357
358 Node* b2b = ExpectPeeled(b2.branch, peeled);
359 Node* b2t = ExpectPeeled(b2.if_true, peeled);
360 Node* b2f = ExpectPeeled(b2.if_false, peeled);
361
362 EXPECT_THAT(b2b, IsBranch(p0, b1t));
363 EXPECT_THAT(b2t, IsIfTrue(b2b));
364 EXPECT_THAT(b2f, IsIfFalse(b2b));
365
366 Capture<Node*> entry;
367 EXPECT_THAT(loop, IsLoop(AllOf(CaptureEq(&entry), IsMerge(b2t, b2f)),
368 b2.if_true, b2.if_false));
369
370 Node* eval = phi->InputAt(0);
371
372 EXPECT_THAT(eval, IsPhi(kMachAnyTagged,
373 IsInt32Add(IsInt32Constant(0), IsInt32Constant(1)),
374 IsInt32Add(IsInt32Constant(0), IsInt32Constant(2)),
375 CaptureEq(&entry)));
376
377 EXPECT_THAT(phi,
378 IsPhi(kMachAnyTagged, eval, IsInt32Add(phi, IsInt32Constant(1)),
379 IsInt32Add(phi, IsInt32Constant(2)), loop));
380
381 Capture<Node*> merge;
382 EXPECT_THAT(
383 r, IsReturn(IsPhi(kMachAnyTagged, phi, IsInt32Constant(0),
384 AllOf(CaptureEq(&merge), IsMerge(b1.if_false, b1f))),
385 start(), CaptureEq(&merge)));
386 }
387
388
389 } // namespace compiler
390 } // namespace internal
391 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698