blob: 523c8ce9d4b59fd7e063b3afd1d00dbc411d850e [file] [log] [blame]
Ben Murdoch014dc512016-03-22 12:00:34 +00001// 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/common-operator.h"
7#include "src/compiler/graph.h"
8#include "src/compiler/graph-visualizer.h"
9#include "src/compiler/js-operator.h"
10#include "src/compiler/node.h"
11#include "src/compiler/opcodes.h"
12#include "src/compiler/operator.h"
13#include "src/compiler/schedule.h"
14#include "src/compiler/scheduler.h"
15#include "src/compiler/simplified-operator.h"
16#include "src/compiler/source-position.h"
17#include "src/compiler/verifier.h"
18#include "test/unittests/compiler/compiler-test-utils.h"
19#include "test/unittests/test-utils.h"
20#include "testing/gmock/include/gmock/gmock.h"
21
22using testing::AnyOf;
23
24namespace v8 {
25namespace internal {
26namespace compiler {
27
28class SchedulerTest : public TestWithIsolateAndZone {
29 public:
30 SchedulerTest()
31 : graph_(zone()), common_(zone()), simplified_(zone()), js_(zone()) {}
32
33 Schedule* ComputeAndVerifySchedule(size_t expected) {
34 if (FLAG_trace_turbo) {
35 OFStream os(stdout);
36 SourcePositionTable table(graph());
37 os << AsJSON(*graph(), &table);
38 }
39
40 Schedule* schedule =
41 Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kSplitNodes);
42
43 if (FLAG_trace_turbo_scheduler) {
44 OFStream os(stdout);
45 os << *schedule << std::endl;
46 }
47 ScheduleVerifier::Run(schedule);
48 EXPECT_EQ(expected, GetScheduledNodeCount(schedule));
49 return schedule;
50 }
51
52 size_t GetScheduledNodeCount(const Schedule* schedule) {
53 size_t node_count = 0;
54 for (auto block : *schedule->rpo_order()) {
55 node_count += block->NodeCount();
56 if (block->control() != BasicBlock::kNone) ++node_count;
57 }
58 return node_count;
59 }
60
61 Graph* graph() { return &graph_; }
62 CommonOperatorBuilder* common() { return &common_; }
63 SimplifiedOperatorBuilder* simplified() { return &simplified_; }
64 JSOperatorBuilder* js() { return &js_; }
65
66 private:
67 Graph graph_;
68 CommonOperatorBuilder common_;
69 SimplifiedOperatorBuilder simplified_;
70 JSOperatorBuilder js_;
71};
72
73
74class SchedulerRPOTest : public SchedulerTest {
75 public:
76 SchedulerRPOTest() {}
77
78 // TODO(titzer): pull RPO tests out to their own file.
79 void CheckRPONumbers(BasicBlockVector* order, size_t expected,
80 bool loops_allowed) {
81 CHECK(expected == order->size());
82 for (int i = 0; i < static_cast<int>(order->size()); i++) {
83 CHECK(order->at(i)->rpo_number() == i);
84 if (!loops_allowed) {
85 CHECK(!order->at(i)->loop_end());
86 CHECK(!order->at(i)->loop_header());
87 }
88 }
89 }
90
91 void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, int body_size) {
92 BasicBlock* header = blocks[0];
93 BasicBlock* end = header->loop_end();
94 CHECK(end);
95 CHECK_GT(end->rpo_number(), 0);
96 CHECK_EQ(body_size, end->rpo_number() - header->rpo_number());
97 for (int i = 0; i < body_size; i++) {
98 CHECK_GE(blocks[i]->rpo_number(), header->rpo_number());
99 CHECK_LT(blocks[i]->rpo_number(), end->rpo_number());
100 CHECK(header->LoopContains(blocks[i]));
101 CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header);
102 }
103 if (header->rpo_number() > 0) {
104 CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header);
105 }
106 if (end->rpo_number() < static_cast<int>(order->size())) {
107 CHECK_NE(order->at(end->rpo_number())->loop_header(), header);
108 }
109 }
110
111 struct TestLoop {
112 int count;
113 BasicBlock** nodes;
114 BasicBlock* header() { return nodes[0]; }
115 BasicBlock* last() { return nodes[count - 1]; }
116 ~TestLoop() { delete[] nodes; }
117 };
118
119 TestLoop* CreateLoop(Schedule* schedule, int count) {
120 TestLoop* loop = new TestLoop();
121 loop->count = count;
122 loop->nodes = new BasicBlock* [count];
123 for (int i = 0; i < count; i++) {
124 loop->nodes[i] = schedule->NewBasicBlock();
125 if (i > 0) {
126 schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]);
127 }
128 }
129 schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]);
130 return loop;
131 }
132};
133
134
135namespace {
136
137const Operator kHeapConstant(IrOpcode::kHeapConstant, Operator::kPure,
138 "HeapConstant", 0, 0, 0, 1, 0, 0);
139const Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0,
140 0, 1, 0, 0);
141const Operator kMockCall(IrOpcode::kCall, Operator::kNoProperties, "MockCall",
142 0, 0, 1, 1, 1, 2);
143const Operator kMockTailCall(IrOpcode::kTailCall, Operator::kNoProperties,
144 "MockTailCall", 1, 1, 1, 0, 0, 1);
145
146} // namespace
147
148
149// -----------------------------------------------------------------------------
150// Special reverse-post-order block ordering.
151
152
153TEST_F(SchedulerRPOTest, Degenerate1) {
154 Schedule schedule(zone());
155 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
156 CheckRPONumbers(order, 1, false);
157 EXPECT_EQ(schedule.start(), order->at(0));
158}
159
160
161TEST_F(SchedulerRPOTest, Degenerate2) {
162 Schedule schedule(zone());
163
164 schedule.AddGoto(schedule.start(), schedule.end());
165 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
166 CheckRPONumbers(order, 2, false);
167 EXPECT_EQ(schedule.start(), order->at(0));
168 EXPECT_EQ(schedule.end(), order->at(1));
169}
170
171
172TEST_F(SchedulerRPOTest, Line) {
173 for (int i = 0; i < 10; i++) {
174 Schedule schedule(zone());
175
176 BasicBlock* last = schedule.start();
177 for (int j = 0; j < i; j++) {
178 BasicBlock* block = schedule.NewBasicBlock();
179 block->set_deferred(i & 1);
180 schedule.AddGoto(last, block);
181 last = block;
182 }
183 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
184 CheckRPONumbers(order, 1 + i, false);
185
186 for (size_t i = 0; i < schedule.BasicBlockCount(); i++) {
187 BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i));
188 if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) {
189 EXPECT_EQ(block->rpo_number() + 1, block->SuccessorAt(0)->rpo_number());
190 }
191 }
192 }
193}
194
195
196TEST_F(SchedulerRPOTest, SelfLoop) {
197 Schedule schedule(zone());
198 schedule.AddSuccessorForTesting(schedule.start(), schedule.start());
199 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
200 CheckRPONumbers(order, 1, true);
201 BasicBlock* loop[] = {schedule.start()};
202 CheckLoop(order, loop, 1);
203}
204
205
206TEST_F(SchedulerRPOTest, EntryLoop) {
207 Schedule schedule(zone());
208 BasicBlock* body = schedule.NewBasicBlock();
209 schedule.AddSuccessorForTesting(schedule.start(), body);
210 schedule.AddSuccessorForTesting(body, schedule.start());
211 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
212 CheckRPONumbers(order, 2, true);
213 BasicBlock* loop[] = {schedule.start(), body};
214 CheckLoop(order, loop, 2);
215}
216
217
218TEST_F(SchedulerRPOTest, EndLoop) {
219 Schedule schedule(zone());
220 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
221 schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
222 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
223 CheckRPONumbers(order, 3, true);
224 CheckLoop(order, loop1->nodes, loop1->count);
225}
226
227
228TEST_F(SchedulerRPOTest, EndLoopNested) {
229 Schedule schedule(zone());
230 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
231 schedule.AddSuccessorForTesting(schedule.start(), loop1->header());
232 schedule.AddSuccessorForTesting(loop1->last(), schedule.start());
233 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
234 CheckRPONumbers(order, 3, true);
235 CheckLoop(order, loop1->nodes, loop1->count);
236}
237
238
239TEST_F(SchedulerRPOTest, Diamond) {
240 Schedule schedule(zone());
241
242 BasicBlock* A = schedule.start();
243 BasicBlock* B = schedule.NewBasicBlock();
244 BasicBlock* C = schedule.NewBasicBlock();
245 BasicBlock* D = schedule.end();
246
247 schedule.AddSuccessorForTesting(A, B);
248 schedule.AddSuccessorForTesting(A, C);
249 schedule.AddSuccessorForTesting(B, D);
250 schedule.AddSuccessorForTesting(C, D);
251
252 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
253 CheckRPONumbers(order, 4, false);
254
255 EXPECT_EQ(0, A->rpo_number());
256 EXPECT_THAT(B->rpo_number(), AnyOf(1, 2));
257 EXPECT_THAT(C->rpo_number(), AnyOf(1, 2));
258 EXPECT_EQ(3, D->rpo_number());
259}
260
261
262TEST_F(SchedulerRPOTest, Loop1) {
263 Schedule schedule(zone());
264
265 BasicBlock* A = schedule.start();
266 BasicBlock* B = schedule.NewBasicBlock();
267 BasicBlock* C = schedule.NewBasicBlock();
268 BasicBlock* D = schedule.end();
269
270 schedule.AddSuccessorForTesting(A, B);
271 schedule.AddSuccessorForTesting(B, C);
272 schedule.AddSuccessorForTesting(C, B);
273 schedule.AddSuccessorForTesting(C, D);
274
275 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
276 CheckRPONumbers(order, 4, true);
277 BasicBlock* loop[] = {B, C};
278 CheckLoop(order, loop, 2);
279}
280
281
282TEST_F(SchedulerRPOTest, Loop2) {
283 Schedule schedule(zone());
284
285 BasicBlock* A = schedule.start();
286 BasicBlock* B = schedule.NewBasicBlock();
287 BasicBlock* C = schedule.NewBasicBlock();
288 BasicBlock* D = schedule.end();
289
290 schedule.AddSuccessorForTesting(A, B);
291 schedule.AddSuccessorForTesting(B, C);
292 schedule.AddSuccessorForTesting(C, B);
293 schedule.AddSuccessorForTesting(B, D);
294
295 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
296 CheckRPONumbers(order, 4, true);
297 BasicBlock* loop[] = {B, C};
298 CheckLoop(order, loop, 2);
299}
300
301
302TEST_F(SchedulerRPOTest, LoopN) {
303 for (int i = 0; i < 11; i++) {
304 Schedule schedule(zone());
305 BasicBlock* A = schedule.start();
306 BasicBlock* B = schedule.NewBasicBlock();
307 BasicBlock* C = schedule.NewBasicBlock();
308 BasicBlock* D = schedule.NewBasicBlock();
309 BasicBlock* E = schedule.NewBasicBlock();
310 BasicBlock* F = schedule.NewBasicBlock();
311 BasicBlock* G = schedule.end();
312
313 schedule.AddSuccessorForTesting(A, B);
314 schedule.AddSuccessorForTesting(B, C);
315 schedule.AddSuccessorForTesting(C, D);
316 schedule.AddSuccessorForTesting(D, E);
317 schedule.AddSuccessorForTesting(E, F);
318 schedule.AddSuccessorForTesting(F, B);
319 schedule.AddSuccessorForTesting(B, G);
320
321 // Throw in extra backedges from time to time.
322 if (i == 1) schedule.AddSuccessorForTesting(B, B);
323 if (i == 2) schedule.AddSuccessorForTesting(C, B);
324 if (i == 3) schedule.AddSuccessorForTesting(D, B);
325 if (i == 4) schedule.AddSuccessorForTesting(E, B);
326 if (i == 5) schedule.AddSuccessorForTesting(F, B);
327
328 // Throw in extra loop exits from time to time.
329 if (i == 6) schedule.AddSuccessorForTesting(B, G);
330 if (i == 7) schedule.AddSuccessorForTesting(C, G);
331 if (i == 8) schedule.AddSuccessorForTesting(D, G);
332 if (i == 9) schedule.AddSuccessorForTesting(E, G);
333 if (i == 10) schedule.AddSuccessorForTesting(F, G);
334
335 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
336 CheckRPONumbers(order, 7, true);
337 BasicBlock* loop[] = {B, C, D, E, F};
338 CheckLoop(order, loop, 5);
339 }
340}
341
342
343TEST_F(SchedulerRPOTest, LoopNest1) {
344 Schedule schedule(zone());
345
346 BasicBlock* A = schedule.start();
347 BasicBlock* B = schedule.NewBasicBlock();
348 BasicBlock* C = schedule.NewBasicBlock();
349 BasicBlock* D = schedule.NewBasicBlock();
350 BasicBlock* E = schedule.NewBasicBlock();
351 BasicBlock* F = schedule.end();
352
353 schedule.AddSuccessorForTesting(A, B);
354 schedule.AddSuccessorForTesting(B, C);
355 schedule.AddSuccessorForTesting(C, D);
356 schedule.AddSuccessorForTesting(D, C);
357 schedule.AddSuccessorForTesting(D, E);
358 schedule.AddSuccessorForTesting(E, B);
359 schedule.AddSuccessorForTesting(E, F);
360
361 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
362 CheckRPONumbers(order, 6, true);
363 BasicBlock* loop1[] = {B, C, D, E};
364 CheckLoop(order, loop1, 4);
365
366 BasicBlock* loop2[] = {C, D};
367 CheckLoop(order, loop2, 2);
368}
369
370
371TEST_F(SchedulerRPOTest, LoopNest2) {
372 Schedule schedule(zone());
373
374 BasicBlock* A = schedule.start();
375 BasicBlock* B = schedule.NewBasicBlock();
376 BasicBlock* C = schedule.NewBasicBlock();
377 BasicBlock* D = schedule.NewBasicBlock();
378 BasicBlock* E = schedule.NewBasicBlock();
379 BasicBlock* F = schedule.NewBasicBlock();
380 BasicBlock* G = schedule.NewBasicBlock();
381 BasicBlock* H = schedule.end();
382
383 schedule.AddSuccessorForTesting(A, B);
384 schedule.AddSuccessorForTesting(B, C);
385 schedule.AddSuccessorForTesting(C, D);
386 schedule.AddSuccessorForTesting(D, E);
387 schedule.AddSuccessorForTesting(E, F);
388 schedule.AddSuccessorForTesting(F, G);
389 schedule.AddSuccessorForTesting(G, H);
390
391 schedule.AddSuccessorForTesting(E, D);
392 schedule.AddSuccessorForTesting(F, C);
393 schedule.AddSuccessorForTesting(G, B);
394
395 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
396 CheckRPONumbers(order, 8, true);
397 BasicBlock* loop1[] = {B, C, D, E, F, G};
398 CheckLoop(order, loop1, 6);
399
400 BasicBlock* loop2[] = {C, D, E, F};
401 CheckLoop(order, loop2, 4);
402
403 BasicBlock* loop3[] = {D, E};
404 CheckLoop(order, loop3, 2);
405}
406
407
408TEST_F(SchedulerRPOTest, LoopFollow1) {
409 Schedule schedule(zone());
410
411 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
412 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
413
414 BasicBlock* A = schedule.start();
415 BasicBlock* E = schedule.end();
416
417 schedule.AddSuccessorForTesting(A, loop1->header());
418 schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
419 schedule.AddSuccessorForTesting(loop2->last(), E);
420
421 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
422
423 EXPECT_EQ(schedule.BasicBlockCount(), order->size());
424 CheckLoop(order, loop1->nodes, loop1->count);
425 CheckLoop(order, loop2->nodes, loop2->count);
426}
427
428
429TEST_F(SchedulerRPOTest, LoopFollow2) {
430 Schedule schedule(zone());
431
432 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
433 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
434
435 BasicBlock* A = schedule.start();
436 BasicBlock* S = schedule.NewBasicBlock();
437 BasicBlock* E = schedule.end();
438
439 schedule.AddSuccessorForTesting(A, loop1->header());
440 schedule.AddSuccessorForTesting(loop1->header(), S);
441 schedule.AddSuccessorForTesting(S, loop2->header());
442 schedule.AddSuccessorForTesting(loop2->last(), E);
443
444 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
445
446 EXPECT_EQ(schedule.BasicBlockCount(), order->size());
447 CheckLoop(order, loop1->nodes, loop1->count);
448 CheckLoop(order, loop2->nodes, loop2->count);
449}
450
451
452TEST_F(SchedulerRPOTest, LoopFollowN) {
453 for (int size = 1; size < 5; size++) {
454 for (int exit = 0; exit < size; exit++) {
455 Schedule schedule(zone());
456 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
457 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size));
458 BasicBlock* A = schedule.start();
459 BasicBlock* E = schedule.end();
460
461 schedule.AddSuccessorForTesting(A, loop1->header());
462 schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header());
463 schedule.AddSuccessorForTesting(loop2->nodes[exit], E);
464 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
465
466 EXPECT_EQ(schedule.BasicBlockCount(), order->size());
467 CheckLoop(order, loop1->nodes, loop1->count);
468 CheckLoop(order, loop2->nodes, loop2->count);
469 }
470 }
471}
472
473
474TEST_F(SchedulerRPOTest, NestedLoopFollow1) {
475 Schedule schedule(zone());
476
477 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
478 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
479
480 BasicBlock* A = schedule.start();
481 BasicBlock* B = schedule.NewBasicBlock();
482 BasicBlock* C = schedule.NewBasicBlock();
483 BasicBlock* E = schedule.end();
484
485 schedule.AddSuccessorForTesting(A, B);
486 schedule.AddSuccessorForTesting(B, loop1->header());
487 schedule.AddSuccessorForTesting(loop1->header(), loop2->header());
488 schedule.AddSuccessorForTesting(loop2->last(), C);
489 schedule.AddSuccessorForTesting(C, E);
490 schedule.AddSuccessorForTesting(C, B);
491
492 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
493
494 EXPECT_EQ(schedule.BasicBlockCount(), order->size());
495 CheckLoop(order, loop1->nodes, loop1->count);
496 CheckLoop(order, loop2->nodes, loop2->count);
497
498 BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
499 CheckLoop(order, loop3, 4);
500}
501
502
503TEST_F(SchedulerRPOTest, LoopBackedges1) {
504 int size = 8;
505 for (int i = 0; i < size; i++) {
506 for (int j = 0; j < size; j++) {
507 Schedule schedule(zone());
508 BasicBlock* A = schedule.start();
509 BasicBlock* E = schedule.end();
510
511 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
512 schedule.AddSuccessorForTesting(A, loop1->header());
513 schedule.AddSuccessorForTesting(loop1->last(), E);
514
515 schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
516 schedule.AddSuccessorForTesting(loop1->nodes[j], E);
517
518 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
519 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
520 CheckLoop(order, loop1->nodes, loop1->count);
521 }
522 }
523}
524
525
526TEST_F(SchedulerRPOTest, LoopOutedges1) {
527 int size = 8;
528 for (int i = 0; i < size; i++) {
529 for (int j = 0; j < size; j++) {
530 Schedule schedule(zone());
531 BasicBlock* A = schedule.start();
532 BasicBlock* D = schedule.NewBasicBlock();
533 BasicBlock* E = schedule.end();
534
535 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
536 schedule.AddSuccessorForTesting(A, loop1->header());
537 schedule.AddSuccessorForTesting(loop1->last(), E);
538
539 schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header());
540 schedule.AddSuccessorForTesting(loop1->nodes[j], D);
541 schedule.AddSuccessorForTesting(D, E);
542
543 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
544 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
545 CheckLoop(order, loop1->nodes, loop1->count);
546 }
547 }
548}
549
550
551TEST_F(SchedulerRPOTest, LoopOutedges2) {
552 int size = 8;
553 for (int i = 0; i < size; i++) {
554 Schedule schedule(zone());
555 BasicBlock* A = schedule.start();
556 BasicBlock* E = schedule.end();
557
558 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
559 schedule.AddSuccessorForTesting(A, loop1->header());
560 schedule.AddSuccessorForTesting(loop1->last(), E);
561
562 for (int j = 0; j < size; j++) {
563 BasicBlock* O = schedule.NewBasicBlock();
564 schedule.AddSuccessorForTesting(loop1->nodes[j], O);
565 schedule.AddSuccessorForTesting(O, E);
566 }
567
568 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
569 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
570 CheckLoop(order, loop1->nodes, loop1->count);
571 }
572}
573
574
575TEST_F(SchedulerRPOTest, LoopOutloops1) {
576 int size = 8;
577 for (int i = 0; i < size; i++) {
578 Schedule schedule(zone());
579 BasicBlock* A = schedule.start();
580 BasicBlock* E = schedule.end();
581 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
582 schedule.AddSuccessorForTesting(A, loop1->header());
583 schedule.AddSuccessorForTesting(loop1->last(), E);
584
585 TestLoop** loopN = new TestLoop* [size];
586 for (int j = 0; j < size; j++) {
587 loopN[j] = CreateLoop(&schedule, 2);
588 schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header());
589 schedule.AddSuccessorForTesting(loopN[j]->last(), E);
590 }
591
592 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
593 CheckRPONumbers(order, schedule.BasicBlockCount(), true);
594 CheckLoop(order, loop1->nodes, loop1->count);
595
596 for (int j = 0; j < size; j++) {
597 CheckLoop(order, loopN[j]->nodes, loopN[j]->count);
598 delete loopN[j];
599 }
600 delete[] loopN;
601 }
602}
603
604
605TEST_F(SchedulerRPOTest, LoopMultibackedge) {
606 Schedule schedule(zone());
607
608 BasicBlock* A = schedule.start();
609 BasicBlock* B = schedule.NewBasicBlock();
610 BasicBlock* C = schedule.NewBasicBlock();
611 BasicBlock* D = schedule.NewBasicBlock();
612 BasicBlock* E = schedule.NewBasicBlock();
613
614 schedule.AddSuccessorForTesting(A, B);
615 schedule.AddSuccessorForTesting(B, C);
616 schedule.AddSuccessorForTesting(B, D);
617 schedule.AddSuccessorForTesting(B, E);
618 schedule.AddSuccessorForTesting(C, B);
619 schedule.AddSuccessorForTesting(D, B);
620 schedule.AddSuccessorForTesting(E, B);
621
622 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule);
623 CheckRPONumbers(order, 5, true);
624
625 BasicBlock* loop1[] = {B, C, D, E};
626 CheckLoop(order, loop1, 4);
627}
628
629
630// -----------------------------------------------------------------------------
631// Graph end-to-end scheduling.
632
633
634TEST_F(SchedulerTest, BuildScheduleEmpty) {
635 graph()->SetStart(graph()->NewNode(common()->Start(0)));
636 graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
637 USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
638}
639
640
641TEST_F(SchedulerTest, BuildScheduleOneParameter) {
642 graph()->SetStart(graph()->NewNode(common()->Start(0)));
643
644 Node* p1 = graph()->NewNode(common()->Parameter(0), graph()->start());
645 Node* ret = graph()->NewNode(common()->Return(), p1, graph()->start(),
646 graph()->start());
647
648 graph()->SetEnd(graph()->NewNode(common()->End(1), ret));
649
650 USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags));
651}
652
653
654namespace {
655
656Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, Node* cond) {
657 Node* tv = graph->NewNode(common->Int32Constant(6));
658 Node* fv = graph->NewNode(common->Int32Constant(7));
659 Node* br = graph->NewNode(common->Branch(), cond, graph->start());
660 Node* t = graph->NewNode(common->IfTrue(), br);
661 Node* f = graph->NewNode(common->IfFalse(), br);
662 Node* m = graph->NewNode(common->Merge(2), t, f);
663 Node* phi =
664 graph->NewNode(common->Phi(MachineRepresentation::kTagged, 2), tv, fv, m);
665 return phi;
666}
667
668} // namespace
669
670
671TARGET_TEST_F(SchedulerTest, FloatingDiamond1) {
672 Node* start = graph()->NewNode(common()->Start(1));
673 graph()->SetStart(start);
674
675 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
676 Node* d1 = CreateDiamond(graph(), common(), p0);
677 Node* ret = graph()->NewNode(common()->Return(), d1, start, start);
678 Node* end = graph()->NewNode(common()->End(1), ret);
679
680 graph()->SetEnd(end);
681
682 ComputeAndVerifySchedule(13);
683}
684
685
686TARGET_TEST_F(SchedulerTest, FloatingDiamond2) {
687 Node* start = graph()->NewNode(common()->Start(2));
688 graph()->SetStart(start);
689
690 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
691 Node* p1 = graph()->NewNode(common()->Parameter(1), start);
692 Node* d1 = CreateDiamond(graph(), common(), p0);
693 Node* d2 = CreateDiamond(graph(), common(), p1);
694 Node* add = graph()->NewNode(&kIntAdd, d1, d2);
695 Node* ret = graph()->NewNode(common()->Return(), add, start, start);
696 Node* end = graph()->NewNode(common()->End(1), ret);
697
698 graph()->SetEnd(end);
699
700 ComputeAndVerifySchedule(24);
701}
702
703
704TARGET_TEST_F(SchedulerTest, FloatingDiamond3) {
705 Node* start = graph()->NewNode(common()->Start(2));
706 graph()->SetStart(start);
707
708 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
709 Node* p1 = graph()->NewNode(common()->Parameter(1), start);
710 Node* d1 = CreateDiamond(graph(), common(), p0);
711 Node* d2 = CreateDiamond(graph(), common(), p1);
712 Node* add = graph()->NewNode(&kIntAdd, d1, d2);
713 Node* d3 = CreateDiamond(graph(), common(), add);
714 Node* ret = graph()->NewNode(common()->Return(), d3, start, start);
715 Node* end = graph()->NewNode(common()->End(1), ret);
716
717 graph()->SetEnd(end);
718
719 ComputeAndVerifySchedule(33);
720}
721
722
723TARGET_TEST_F(SchedulerTest, NestedFloatingDiamonds) {
724 Node* start = graph()->NewNode(common()->Start(2));
725 graph()->SetStart(start);
726
727 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
728
729 Node* fv = graph()->NewNode(common()->Int32Constant(7));
730 Node* br = graph()->NewNode(common()->Branch(), p0, graph()->start());
731 Node* t = graph()->NewNode(common()->IfTrue(), br);
732 Node* f = graph()->NewNode(common()->IfFalse(), br);
733
734 Node* map = graph()->NewNode(
735 simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), p0, p0,
736 start, f);
737 Node* br1 = graph()->NewNode(common()->Branch(), map, graph()->start());
738 Node* t1 = graph()->NewNode(common()->IfTrue(), br1);
739 Node* f1 = graph()->NewNode(common()->IfFalse(), br1);
740 Node* m1 = graph()->NewNode(common()->Merge(2), t1, f1);
741 Node* ttrue = graph()->NewNode(common()->Int32Constant(1));
742 Node* ffalse = graph()->NewNode(common()->Int32Constant(0));
743 Node* phi1 = graph()->NewNode(
744 common()->Phi(MachineRepresentation::kTagged, 2), ttrue, ffalse, m1);
745
746
747 Node* m = graph()->NewNode(common()->Merge(2), t, f);
748 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
749 fv, phi1, m);
750 Node* ephi1 = graph()->NewNode(common()->EffectPhi(2), start, map, m);
751
752 Node* ret = graph()->NewNode(common()->Return(), phi, ephi1, start);
753 Node* end = graph()->NewNode(common()->End(1), ret);
754
755 graph()->SetEnd(end);
756
757 ComputeAndVerifySchedule(23);
758}
759
760
761TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithChain) {
762 Node* start = graph()->NewNode(common()->Start(2));
763 graph()->SetStart(start);
764
765 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
766 Node* p1 = graph()->NewNode(common()->Parameter(1), start);
767 Node* c = graph()->NewNode(common()->Int32Constant(7));
768
769 Node* brA1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
770 Node* tA1 = graph()->NewNode(common()->IfTrue(), brA1);
771 Node* fA1 = graph()->NewNode(common()->IfFalse(), brA1);
772 Node* mA1 = graph()->NewNode(common()->Merge(2), tA1, fA1);
773 Node* phiA1 = graph()->NewNode(
774 common()->Phi(MachineRepresentation::kTagged, 2), p0, p1, mA1);
775
776 Node* brB1 = graph()->NewNode(common()->Branch(), p1, graph()->start());
777 Node* tB1 = graph()->NewNode(common()->IfTrue(), brB1);
778 Node* fB1 = graph()->NewNode(common()->IfFalse(), brB1);
779 Node* mB1 = graph()->NewNode(common()->Merge(2), tB1, fB1);
780 Node* phiB1 = graph()->NewNode(
781 common()->Phi(MachineRepresentation::kTagged, 2), p0, p1, mB1);
782
783 Node* brA2 = graph()->NewNode(common()->Branch(), phiB1, mA1);
784 Node* tA2 = graph()->NewNode(common()->IfTrue(), brA2);
785 Node* fA2 = graph()->NewNode(common()->IfFalse(), brA2);
786 Node* mA2 = graph()->NewNode(common()->Merge(2), tA2, fA2);
787 Node* phiA2 = graph()->NewNode(
788 common()->Phi(MachineRepresentation::kTagged, 2), phiB1, c, mA2);
789
790 Node* brB2 = graph()->NewNode(common()->Branch(), phiA1, mB1);
791 Node* tB2 = graph()->NewNode(common()->IfTrue(), brB2);
792 Node* fB2 = graph()->NewNode(common()->IfFalse(), brB2);
793 Node* mB2 = graph()->NewNode(common()->Merge(2), tB2, fB2);
794 Node* phiB2 = graph()->NewNode(
795 common()->Phi(MachineRepresentation::kTagged, 2), phiA1, c, mB2);
796
797 Node* add = graph()->NewNode(&kIntAdd, phiA2, phiB2);
798 Node* ret = graph()->NewNode(common()->Return(), add, start, start);
799 Node* end = graph()->NewNode(common()->End(1), ret);
800
801 graph()->SetEnd(end);
802
803 ComputeAndVerifySchedule(36);
804}
805
806
807TARGET_TEST_F(SchedulerTest, NestedFloatingDiamondWithLoop) {
808 Node* start = graph()->NewNode(common()->Start(2));
809 graph()->SetStart(start);
810
811 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
812
813 Node* fv = graph()->NewNode(common()->Int32Constant(7));
814 Node* br = graph()->NewNode(common()->Branch(), p0, graph()->start());
815 Node* t = graph()->NewNode(common()->IfTrue(), br);
816 Node* f = graph()->NewNode(common()->IfFalse(), br);
817
818 Node* loop = graph()->NewNode(common()->Loop(2), f, start);
819 Node* ind = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
820 p0, p0, loop);
821
822 Node* add = graph()->NewNode(&kIntAdd, ind, fv);
823 Node* br1 = graph()->NewNode(common()->Branch(), add, loop);
824 Node* t1 = graph()->NewNode(common()->IfTrue(), br1);
825 Node* f1 = graph()->NewNode(common()->IfFalse(), br1);
826
827 loop->ReplaceInput(1, t1); // close loop.
828 ind->ReplaceInput(1, ind); // close induction variable.
829
830 Node* m = graph()->NewNode(common()->Merge(2), t, f1);
831 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
832 fv, ind, m);
833
834 Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
835 Node* end = graph()->NewNode(common()->End(1), ret);
836
837 graph()->SetEnd(end);
838
839 ComputeAndVerifySchedule(20);
840}
841
842
843TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond1) {
844 Node* start = graph()->NewNode(common()->Start(2));
845 graph()->SetStart(start);
846
847 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
848
849 Node* c = graph()->NewNode(common()->Int32Constant(7));
850 Node* loop = graph()->NewNode(common()->Loop(2), start, start);
851 Node* ind = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
852 p0, p0, loop);
853 Node* add = graph()->NewNode(&kIntAdd, ind, c);
854
855 Node* br = graph()->NewNode(common()->Branch(), add, loop);
856 Node* t = graph()->NewNode(common()->IfTrue(), br);
857 Node* f = graph()->NewNode(common()->IfFalse(), br);
858
859 Node* br1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
860 Node* t1 = graph()->NewNode(common()->IfTrue(), br1);
861 Node* f1 = graph()->NewNode(common()->IfFalse(), br1);
862 Node* m1 = graph()->NewNode(common()->Merge(2), t1, f1);
863 Node* phi1 = graph()->NewNode(
864 common()->Phi(MachineRepresentation::kTagged, 2), add, p0, m1);
865
866 loop->ReplaceInput(1, t); // close loop.
867 ind->ReplaceInput(1, phi1); // close induction variable.
868
869 Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
870 Node* end = graph()->NewNode(common()->End(2), ret, f);
871
872 graph()->SetEnd(end);
873
874 ComputeAndVerifySchedule(20);
875}
876
877
878TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond2) {
879 Node* start = graph()->NewNode(common()->Start(2));
880 graph()->SetStart(start);
881
882 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
883
884 Node* c = graph()->NewNode(common()->Int32Constant(7));
885 Node* loop = graph()->NewNode(common()->Loop(2), start, start);
886 Node* ind = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
887 p0, p0, loop);
888
889 Node* br1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
890 Node* t1 = graph()->NewNode(common()->IfTrue(), br1);
891 Node* f1 = graph()->NewNode(common()->IfFalse(), br1);
892 Node* m1 = graph()->NewNode(common()->Merge(2), t1, f1);
893 Node* phi1 = graph()->NewNode(
894 common()->Phi(MachineRepresentation::kTagged, 2), c, ind, m1);
895
896 Node* add = graph()->NewNode(&kIntAdd, ind, phi1);
897
898 Node* br = graph()->NewNode(common()->Branch(), add, loop);
899 Node* t = graph()->NewNode(common()->IfTrue(), br);
900 Node* f = graph()->NewNode(common()->IfFalse(), br);
901
902 loop->ReplaceInput(1, t); // close loop.
903 ind->ReplaceInput(1, add); // close induction variable.
904
905 Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
906 Node* end = graph()->NewNode(common()->End(2), ret, f);
907
908 graph()->SetEnd(end);
909
910 ComputeAndVerifySchedule(20);
911}
912
913
914TARGET_TEST_F(SchedulerTest, LoopedFloatingDiamond3) {
915 Node* start = graph()->NewNode(common()->Start(2));
916 graph()->SetStart(start);
917
918 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
919
920 Node* c = graph()->NewNode(common()->Int32Constant(7));
921 Node* loop = graph()->NewNode(common()->Loop(2), start, start);
922 Node* ind = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
923 p0, p0, loop);
924
925 Node* br1 = graph()->NewNode(common()->Branch(), p0, graph()->start());
926 Node* t1 = graph()->NewNode(common()->IfTrue(), br1);
927 Node* f1 = graph()->NewNode(common()->IfFalse(), br1);
928
929 Node* loop1 = graph()->NewNode(common()->Loop(2), t1, start);
930 Node* ind1 = graph()->NewNode(
931 common()->Phi(MachineRepresentation::kTagged, 2), p0, p0, loop);
932
933 Node* add1 = graph()->NewNode(&kIntAdd, ind1, c);
934 Node* br2 = graph()->NewNode(common()->Branch(), add1, loop1);
935 Node* t2 = graph()->NewNode(common()->IfTrue(), br2);
936 Node* f2 = graph()->NewNode(common()->IfFalse(), br2);
937
938 loop1->ReplaceInput(1, t2); // close inner loop.
939 ind1->ReplaceInput(1, ind1); // close inner induction variable.
940
941 Node* m1 = graph()->NewNode(common()->Merge(2), f1, f2);
942 Node* phi1 = graph()->NewNode(
943 common()->Phi(MachineRepresentation::kTagged, 2), c, ind1, m1);
944
945 Node* add = graph()->NewNode(&kIntAdd, ind, phi1);
946
947 Node* br = graph()->NewNode(common()->Branch(), add, loop);
948 Node* t = graph()->NewNode(common()->IfTrue(), br);
949 Node* f = graph()->NewNode(common()->IfFalse(), br);
950
951 loop->ReplaceInput(1, t); // close loop.
952 ind->ReplaceInput(1, add); // close induction variable.
953
954 Node* ret = graph()->NewNode(common()->Return(), ind, start, f);
955 Node* end = graph()->NewNode(common()->End(2), ret, f);
956
957 graph()->SetEnd(end);
958
959 ComputeAndVerifySchedule(28);
960}
961
962
963TARGET_TEST_F(SchedulerTest, PhisPushedDownToDifferentBranches) {
964 Node* start = graph()->NewNode(common()->Start(2));
965 graph()->SetStart(start);
966
967 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
968 Node* p1 = graph()->NewNode(common()->Parameter(1), start);
969
970 Node* v1 = graph()->NewNode(common()->Int32Constant(1));
971 Node* v2 = graph()->NewNode(common()->Int32Constant(2));
972 Node* v3 = graph()->NewNode(common()->Int32Constant(3));
973 Node* v4 = graph()->NewNode(common()->Int32Constant(4));
974 Node* br = graph()->NewNode(common()->Branch(), p0, graph()->start());
975 Node* t = graph()->NewNode(common()->IfTrue(), br);
976 Node* f = graph()->NewNode(common()->IfFalse(), br);
977 Node* m = graph()->NewNode(common()->Merge(2), t, f);
978 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
979 v1, v2, m);
980 Node* phi2 = graph()->NewNode(
981 common()->Phi(MachineRepresentation::kTagged, 2), v3, v4, m);
982
983 Node* br2 = graph()->NewNode(common()->Branch(), p1, graph()->start());
984 Node* t2 = graph()->NewNode(common()->IfTrue(), br2);
985 Node* f2 = graph()->NewNode(common()->IfFalse(), br2);
986 Node* m2 = graph()->NewNode(common()->Merge(2), t2, f2);
987 Node* phi3 = graph()->NewNode(
988 common()->Phi(MachineRepresentation::kTagged, 2), phi, phi2, m2);
989
990 Node* ret = graph()->NewNode(common()->Return(), phi3, start, start);
991 Node* end = graph()->NewNode(common()->End(1), ret);
992
993 graph()->SetEnd(end);
994
995 ComputeAndVerifySchedule(24);
996}
997
998
999TARGET_TEST_F(SchedulerTest, BranchHintTrue) {
1000 Node* start = graph()->NewNode(common()->Start(1));
1001 graph()->SetStart(start);
1002
1003 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
1004 Node* tv = graph()->NewNode(common()->Int32Constant(6));
1005 Node* fv = graph()->NewNode(common()->Int32Constant(7));
1006 Node* br = graph()->NewNode(common()->Branch(BranchHint::kTrue), p0, start);
1007 Node* t = graph()->NewNode(common()->IfTrue(), br);
1008 Node* f = graph()->NewNode(common()->IfFalse(), br);
1009 Node* m = graph()->NewNode(common()->Merge(2), t, f);
1010 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1011 tv, fv, m);
1012 Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
1013 Node* end = graph()->NewNode(common()->End(1), ret);
1014
1015 graph()->SetEnd(end);
1016
1017 Schedule* schedule = ComputeAndVerifySchedule(13);
1018 // Make sure the false block is marked as deferred.
1019 EXPECT_FALSE(schedule->block(t)->deferred());
1020 EXPECT_TRUE(schedule->block(f)->deferred());
1021}
1022
1023
1024TARGET_TEST_F(SchedulerTest, BranchHintFalse) {
1025 Node* start = graph()->NewNode(common()->Start(1));
1026 graph()->SetStart(start);
1027
1028 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
1029 Node* tv = graph()->NewNode(common()->Int32Constant(6));
1030 Node* fv = graph()->NewNode(common()->Int32Constant(7));
1031 Node* br = graph()->NewNode(common()->Branch(BranchHint::kFalse), p0, start);
1032 Node* t = graph()->NewNode(common()->IfTrue(), br);
1033 Node* f = graph()->NewNode(common()->IfFalse(), br);
1034 Node* m = graph()->NewNode(common()->Merge(2), t, f);
1035 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1036 tv, fv, m);
1037 Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
1038 Node* end = graph()->NewNode(common()->End(1), ret);
1039
1040 graph()->SetEnd(end);
1041
1042 Schedule* schedule = ComputeAndVerifySchedule(13);
1043 // Make sure the true block is marked as deferred.
1044 EXPECT_TRUE(schedule->block(t)->deferred());
1045 EXPECT_FALSE(schedule->block(f)->deferred());
1046}
1047
1048
1049TARGET_TEST_F(SchedulerTest, CallException) {
1050 Node* start = graph()->NewNode(common()->Start(1));
1051 graph()->SetStart(start);
1052
1053 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
1054 Node* c1 = graph()->NewNode(&kMockCall, start);
1055 Node* ok1 = graph()->NewNode(common()->IfSuccess(), c1);
1056 Node* ex1 = graph()->NewNode(
1057 common()->IfException(IfExceptionHint::kLocallyUncaught), c1, c1);
1058 Node* c2 = graph()->NewNode(&kMockCall, ok1);
1059 Node* ok2 = graph()->NewNode(common()->IfSuccess(), c2);
1060 Node* ex2 = graph()->NewNode(
1061 common()->IfException(IfExceptionHint::kLocallyUncaught), c2, c2);
1062 Node* hdl = graph()->NewNode(common()->Merge(2), ex1, ex2);
1063 Node* m = graph()->NewNode(common()->Merge(2), ok2, hdl);
1064 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kTagged, 2),
1065 c2, p0, m);
1066 Node* ret = graph()->NewNode(common()->Return(), phi, start, m);
1067 Node* end = graph()->NewNode(common()->End(1), ret);
1068
1069 graph()->SetEnd(end);
1070
1071 Schedule* schedule = ComputeAndVerifySchedule(17);
1072 // Make sure the exception blocks as well as the handler are deferred.
1073 EXPECT_TRUE(schedule->block(ex1)->deferred());
1074 EXPECT_TRUE(schedule->block(ex2)->deferred());
1075 EXPECT_TRUE(schedule->block(hdl)->deferred());
1076 EXPECT_FALSE(schedule->block(m)->deferred());
1077}
1078
1079
1080TARGET_TEST_F(SchedulerTest, TailCall) {
1081 Node* start = graph()->NewNode(common()->Start(1));
1082 graph()->SetStart(start);
1083
1084 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
1085 Node* call = graph()->NewNode(&kMockTailCall, p0, start, start);
1086 Node* end = graph()->NewNode(common()->End(1), call);
1087
1088 graph()->SetEnd(end);
1089
1090 ComputeAndVerifySchedule(4);
1091}
1092
1093
1094TARGET_TEST_F(SchedulerTest, Switch) {
1095 Node* start = graph()->NewNode(common()->Start(1));
1096 graph()->SetStart(start);
1097
1098 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
1099 Node* sw = graph()->NewNode(common()->Switch(3), p0, start);
1100 Node* c0 = graph()->NewNode(common()->IfValue(0), sw);
1101 Node* v0 = graph()->NewNode(common()->Int32Constant(11));
1102 Node* c1 = graph()->NewNode(common()->IfValue(1), sw);
1103 Node* v1 = graph()->NewNode(common()->Int32Constant(22));
1104 Node* d = graph()->NewNode(common()->IfDefault(), sw);
1105 Node* vd = graph()->NewNode(common()->Int32Constant(33));
1106 Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d);
1107 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 3),
1108 v0, v1, vd, m);
1109 Node* ret = graph()->NewNode(common()->Return(), phi, start, m);
1110 Node* end = graph()->NewNode(common()->End(1), ret);
1111
1112 graph()->SetEnd(end);
1113
1114 ComputeAndVerifySchedule(16);
1115}
1116
1117
1118TARGET_TEST_F(SchedulerTest, FloatingSwitch) {
1119 Node* start = graph()->NewNode(common()->Start(1));
1120 graph()->SetStart(start);
1121
1122 Node* p0 = graph()->NewNode(common()->Parameter(0), start);
1123 Node* sw = graph()->NewNode(common()->Switch(3), p0, start);
1124 Node* c0 = graph()->NewNode(common()->IfValue(0), sw);
1125 Node* v0 = graph()->NewNode(common()->Int32Constant(11));
1126 Node* c1 = graph()->NewNode(common()->IfValue(1), sw);
1127 Node* v1 = graph()->NewNode(common()->Int32Constant(22));
1128 Node* d = graph()->NewNode(common()->IfDefault(), sw);
1129 Node* vd = graph()->NewNode(common()->Int32Constant(33));
1130 Node* m = graph()->NewNode(common()->Merge(3), c0, c1, d);
1131 Node* phi = graph()->NewNode(common()->Phi(MachineRepresentation::kWord32, 3),
1132 v0, v1, vd, m);
1133 Node* ret = graph()->NewNode(common()->Return(), phi, start, start);
1134 Node* end = graph()->NewNode(common()->End(1), ret);
1135
1136 graph()->SetEnd(end);
1137
1138 ComputeAndVerifySchedule(16);
1139}
1140
1141
1142TARGET_TEST_F(SchedulerTest, Terminate) {
1143 Node* start = graph()->NewNode(common()->Start(1));
1144 graph()->SetStart(start);
1145
1146 Node* loop = graph()->NewNode(common()->Loop(2), start, start);
1147 loop->ReplaceInput(1, loop); // self loop, NTL.
1148
1149 Node* effect = graph()->NewNode(common()->EffectPhi(2), start, start, loop);
1150 effect->ReplaceInput(1, effect); // self loop.
1151
1152 Node* terminate = graph()->NewNode(common()->Terminate(), effect, loop);
1153 Node* end = graph()->NewNode(common()->End(1), terminate);
1154 graph()->SetEnd(end);
1155
1156 Schedule* schedule = ComputeAndVerifySchedule(6);
1157 BasicBlock* block = schedule->block(loop);
1158 EXPECT_EQ(block, schedule->block(effect));
1159 EXPECT_GE(block->rpo_number(), 0);
1160}
1161
1162} // namespace compiler
1163} // namespace internal
1164} // namespace v8