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

Side by Side Diff: test/cctest/compiler/test-osr.cc

Issue 898353002: [turbofan] Use heavy-handed graph duplication to do loop peeling for OSR. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 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 | « src/compiler/pipeline.cc ('k') | test/mjsunit/compiler/osr-backedges1.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/codegen.h" 5 #include "src/codegen.h"
6 #include "src/compiler/common-operator.h" 6 #include "src/compiler/common-operator.h"
7 #include "src/compiler/diamond.h" 7 #include "src/compiler/diamond.h"
8 #include "src/compiler/graph.h" 8 #include "src/compiler/graph.h"
9 #include "src/compiler/js-graph.h" 9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/js-operator.h" 10 #include "src/compiler/js-operator.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
42 class OsrDeconstructorTester : public HandleAndZoneScope { 42 class OsrDeconstructorTester : public HandleAndZoneScope {
43 public: 43 public:
44 explicit OsrDeconstructorTester(int num_values) 44 explicit OsrDeconstructorTester(int num_values)
45 : isolate(main_isolate()), 45 : isolate(main_isolate()),
46 common(main_zone()), 46 common(main_zone()),
47 graph(main_zone()), 47 graph(main_zone()),
48 jsgraph(main_isolate(), &graph, &common, NULL, NULL), 48 jsgraph(main_isolate(), &graph, &common, NULL, NULL),
49 start(graph.NewNode(common.Start(1))), 49 start(graph.NewNode(common.Start(1))),
50 p0(graph.NewNode(common.Parameter(0), start)), 50 p0(graph.NewNode(common.Parameter(0), start)),
51 end(graph.NewNode(common.End(), start)), 51 end(graph.NewNode(common.End(), start)),
52 osr_normal_entry(graph.NewNode(common.OsrNormalEntry(), start)), 52 osr_normal_entry(graph.NewNode(common.OsrNormalEntry(), start, start)),
53 osr_loop_entry(graph.NewNode(common.OsrLoopEntry(), start)), 53 osr_loop_entry(graph.NewNode(common.OsrLoopEntry(), start, start)),
54 self(graph.NewNode(common.Int32Constant(0xaabbccdd))) { 54 self(graph.NewNode(common.Int32Constant(0xaabbccdd))) {
55 CHECK(num_values <= kMaxOsrValues); 55 CHECK(num_values <= kMaxOsrValues);
56 graph.SetStart(start); 56 graph.SetStart(start);
57 for (int i = 0; i < num_values; i++) { 57 for (int i = 0; i < num_values; i++) {
58 osr_values[i] = graph.NewNode(common.OsrValue(i), osr_loop_entry); 58 osr_values[i] = graph.NewNode(common.OsrValue(i), osr_loop_entry);
59 } 59 }
60 } 60 }
61 61
62 Isolate* isolate; 62 Isolate* isolate;
63 CommonOperatorBuilder common; 63 CommonOperatorBuilder common;
(...skipping 19 matching lines...) Expand all
83 Node* inputs[6]; 83 Node* inputs[6];
84 inputs[0] = incoming; 84 inputs[0] = incoming;
85 inputs[1] = osr_values[osr_value]; 85 inputs[1] = osr_values[osr_value];
86 if (count > 2) inputs[2] = back1; 86 if (count > 2) inputs[2] = back1;
87 if (count > 3) inputs[3] = back2; 87 if (count > 3) inputs[3] = back2;
88 if (count > 4) inputs[4] = back3; 88 if (count > 4) inputs[4] = back3;
89 inputs[count] = loop; 89 inputs[count] = loop;
90 return graph.NewNode(common.Phi(kMachAnyTagged, count), count + 1, inputs); 90 return graph.NewNode(common.Phi(kMachAnyTagged, count), count + 1, inputs);
91 } 91 }
92 92
93 Node* NewOsrLoop(int num_backedges, Node* entry = NULL) { 93 Node* NewLoop(bool is_osr, int num_backedges, Node* entry = NULL) {
94 CHECK_LT(num_backedges, 4); 94 CHECK_LT(num_backedges, 4);
95 CHECK_GE(num_backedges, 0); 95 CHECK_GE(num_backedges, 0);
96 int count = 2 + num_backedges; 96 int count = 1 + num_backedges;
97 if (entry == NULL) entry = osr_normal_entry; 97 if (entry == NULL) entry = osr_normal_entry;
98 Node* inputs[5] = {entry, osr_loop_entry, self, self, self}; 98 Node* inputs[5] = {entry, self, self, self, self};
99 if (is_osr) {
100 count = 2 + num_backedges;
101 inputs[1] = osr_loop_entry;
102 }
99 103
100 Node* loop = graph.NewNode(common.Loop(count), count, inputs); 104 Node* loop = graph.NewNode(common.Loop(count), count, inputs);
101 for (int i = 0; i < num_backedges; i++) { 105 for (int i = 0; i < loop->InputCount(); i++) {
102 loop->ReplaceInput(2 + i, loop); 106 if (loop->InputAt(i) == self) loop->ReplaceInput(i, loop);
103 } 107 }
104 108
105 return loop; 109 return loop;
106 } 110 }
111
112 Node* NewOsrLoop(int num_backedges, Node* entry = NULL) {
113 return NewLoop(true, num_backedges, entry);
114 }
107 }; 115 };
108 116
109 117
110 TEST(Deconstruct_osr0) { 118 TEST(Deconstruct_osr0) {
111 OsrDeconstructorTester T(0); 119 OsrDeconstructorTester T(0);
112 120
113 Node* loop = T.NewOsrLoop(1); 121 Node* loop = T.NewOsrLoop(1);
114 122
115 T.graph.SetEnd(loop); 123 T.graph.SetEnd(loop);
116 124
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 CheckInputs(branch2, T.p0, if_true1); 273 CheckInputs(branch2, T.p0, if_true1);
266 CheckInputs(if_true1, branch1); 274 CheckInputs(if_true1, branch1);
267 CheckInputs(if_false1, branch1); 275 CheckInputs(if_false1, branch1);
268 CheckInputs(if_true2, branch2); 276 CheckInputs(if_true2, branch2);
269 CheckInputs(if_false2, branch2); 277 CheckInputs(if_false2, branch2);
270 278
271 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), 279 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(),
272 T.jsgraph.ZeroConstant(), loop); 280 T.jsgraph.ZeroConstant(), loop);
273 CheckInputs(ret, osr_phi, T.start, if_false2); 281 CheckInputs(ret, osr_phi, T.start, if_false2);
274 } 282 }
283
284
285 struct While {
286 OsrDeconstructorTester& t;
287 Node* branch;
288 Node* if_true;
289 Node* exit;
290 Node* loop;
291
292 While(OsrDeconstructorTester& R, Node* cond, bool is_osr, int backedges = 1)
293 : t(R) {
294 loop = t.NewLoop(is_osr, backedges);
295 branch = t.graph.NewNode(t.common.Branch(), cond, loop);
296 if_true = t.graph.NewNode(t.common.IfTrue(), branch);
297 exit = t.graph.NewNode(t.common.IfFalse(), branch);
298 loop->ReplaceInput(loop->InputCount() - 1, if_true);
299 }
300
301 void Nest(While& that) {
302 that.loop->ReplaceInput(that.loop->InputCount() - 1, exit);
303 this->loop->ReplaceInput(0, that.if_true);
304 }
305
306 Node* Phi(Node* i1, Node* i2, Node* i3) {
307 if (loop->InputCount() == 2) {
308 return t.graph.NewNode(t.common.Phi(kMachAnyTagged, 2), i1, i2, loop);
309 } else {
310 return t.graph.NewNode(t.common.Phi(kMachAnyTagged, 3), i1, i2, i3, loop);
311 }
312 }
313 };
314
315
316 static Node* FindSuccessor(Node* node, IrOpcode::Value opcode) {
317 for (Node* use : node->uses()) {
318 if (use->opcode() == opcode) return use;
319 }
320 UNREACHABLE(); // should have been found.
321 return nullptr;
322 }
323
324
325 TEST(Deconstruct_osr_nested1) {
326 OsrDeconstructorTester T(1);
327
328 While outer(T, T.p0, false);
329 While inner(T, T.p0, true);
330 inner.Nest(outer);
331
332 Node* outer_phi = outer.Phi(T.p0, T.p0, nullptr);
333 outer.branch->ReplaceInput(0, outer_phi);
334
335 Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0],
336 T.jsgraph.ZeroConstant());
337 inner.branch->ReplaceInput(0, osr_phi);
338 outer_phi->ReplaceInput(1, osr_phi);
339
340 Node* ret =
341 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit);
342 Node* end = T.graph.NewNode(T.common.End(), ret);
343 T.graph.SetEnd(end);
344
345 OsrHelper helper(0, 0);
346 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
347
348 // Check structure of deconstructed graph.
349 // Check inner OSR loop is directly connected to start.
350 CheckInputs(inner.loop, T.start, inner.if_true);
351 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop);
352
353 // Check control transfer to copy of outer loop.
354 Node* new_outer_loop = FindSuccessor(inner.exit, IrOpcode::kLoop);
355 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi);
356 CHECK_NE(new_outer_loop, outer.loop);
357 CHECK_NE(new_outer_phi, outer_phi);
358
359 CheckInputs(new_outer_loop, inner.exit, new_outer_loop->InputAt(1));
360
361 // Check structure of outer loop.
362 Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch);
363 CHECK_NE(new_outer_branch, outer.branch);
364 CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop);
365 Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse);
366 Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue);
367
368 // Check structure of return.
369 end = T.graph.end();
370 Node* new_ret = end->InputAt(0);
371 CHECK_EQ(IrOpcode::kReturn, new_ret->opcode());
372 CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit);
373
374 // Check structure of inner loop.
375 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop);
376 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi);
377
378 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(),
379 new_inner_loop);
380 CheckInputs(new_outer_phi, osr_phi, new_inner_phi, new_outer_loop);
381 }
382
383
384 TEST(Deconstruct_osr_nested2) {
385 OsrDeconstructorTester T(1);
386
387 // Test multiple backedge outer loop.
388 While outer(T, T.p0, false, 2);
389 While inner(T, T.p0, true);
390 inner.Nest(outer);
391
392 Node* outer_phi = outer.Phi(T.p0, T.p0, T.p0);
393 outer.branch->ReplaceInput(0, outer_phi);
394
395 Node* osr_phi = inner.Phi(T.jsgraph.OneConstant(), T.osr_values[0],
396 T.jsgraph.ZeroConstant());
397 inner.branch->ReplaceInput(0, osr_phi);
398 outer_phi->ReplaceInput(1, osr_phi);
399 outer_phi->ReplaceInput(2, T.jsgraph.ZeroConstant());
400
401 Node* x_branch = T.graph.NewNode(T.common.Branch(), osr_phi, inner.exit);
402 Node* x_true = T.graph.NewNode(T.common.IfTrue(), x_branch);
403 Node* x_false = T.graph.NewNode(T.common.IfFalse(), x_branch);
404
405 outer.loop->ReplaceInput(1, x_true);
406 outer.loop->ReplaceInput(2, x_false);
407
408 Node* ret =
409 T.graph.NewNode(T.common.Return(), outer_phi, T.start, outer.exit);
410 Node* end = T.graph.NewNode(T.common.End(), ret);
411 T.graph.SetEnd(end);
412
413 OsrHelper helper(0, 0);
414 helper.Deconstruct(&T.jsgraph, &T.common, T.main_zone());
415
416 // Check structure of deconstructed graph.
417 // Check inner OSR loop is directly connected to start.
418 CheckInputs(inner.loop, T.start, inner.if_true);
419 CheckInputs(osr_phi, T.osr_values[0], T.jsgraph.ZeroConstant(), inner.loop);
420
421 // Check control transfer to copy of outer loop.
422 Node* new_merge = FindSuccessor(x_true, IrOpcode::kMerge);
423 CHECK_EQ(new_merge, FindSuccessor(x_false, IrOpcode::kMerge));
424 CheckInputs(new_merge, x_true, x_false);
425
426 Node* new_outer_loop = FindSuccessor(new_merge, IrOpcode::kLoop);
427 Node* new_outer_phi = FindSuccessor(new_outer_loop, IrOpcode::kPhi);
428 CHECK_NE(new_outer_loop, outer.loop);
429 CHECK_NE(new_outer_phi, outer_phi);
430
431 Node* new_entry_phi = FindSuccessor(new_merge, IrOpcode::kPhi);
432 CheckInputs(new_entry_phi, osr_phi, T.jsgraph.ZeroConstant(), new_merge);
433
434 CHECK_EQ(new_merge, new_outer_loop->InputAt(0));
435
436 // Check structure of outer loop.
437 Node* new_outer_branch = FindSuccessor(new_outer_loop, IrOpcode::kBranch);
438 CHECK_NE(new_outer_branch, outer.branch);
439 CheckInputs(new_outer_branch, new_outer_phi, new_outer_loop);
440 Node* new_outer_exit = FindSuccessor(new_outer_branch, IrOpcode::kIfFalse);
441 Node* new_outer_if_true = FindSuccessor(new_outer_branch, IrOpcode::kIfTrue);
442
443 // Check structure of return.
444 end = T.graph.end();
445 Node* new_ret = end->InputAt(0);
446 CHECK_EQ(IrOpcode::kReturn, new_ret->opcode());
447 CheckInputs(new_ret, new_outer_phi, T.start, new_outer_exit);
448
449 // Check structure of inner loop.
450 Node* new_inner_loop = FindSuccessor(new_outer_if_true, IrOpcode::kLoop);
451 Node* new_inner_phi = FindSuccessor(new_inner_loop, IrOpcode::kPhi);
452
453 CheckInputs(new_inner_phi, T.jsgraph.OneConstant(), T.jsgraph.ZeroConstant(),
454 new_inner_loop);
455 CheckInputs(new_outer_phi, new_entry_phi, new_inner_phi,
456 T.jsgraph.ZeroConstant(), new_outer_loop);
457 }
OLDNEW
« no previous file with comments | « src/compiler/pipeline.cc ('k') | test/mjsunit/compiler/osr-backedges1.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698