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/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 22 using testing::AnyOf; 23 24 namespace v8 { 25 namespace internal { 26 namespace compiler { 27 28 class 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 74 class 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 135 namespace { 136 137 const Operator kHeapConstant(IrOpcode::kHeapConstant, Operator::kPure, 138 "HeapConstant", 0, 0, 0, 1, 0, 0); 139 const Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, 140 0, 1, 0, 0); 141 const Operator kMockCall(IrOpcode::kCall, Operator::kNoProperties, "MockCall", 142 0, 0, 1, 1, 1, 2); 143 const 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 153 TEST_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 161 TEST_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 172 TEST_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 196 TEST_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 206 TEST_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 218 TEST_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 228 TEST_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 239 TEST_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 262 TEST_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 282 TEST_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 302 TEST_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 343 TEST_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 371 TEST_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 408 TEST_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 429 TEST_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 452 TEST_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 474 TEST_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 503 TEST_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 526 TEST_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 551 TEST_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 575 TEST_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 605 TEST_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 634 TEST_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 641 TEST_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 654 namespace { 655 656 Node* 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 671 TARGET_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 686 TARGET_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 704 TARGET_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 723 TARGET_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 761 TARGET_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 807 TARGET_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 843 TARGET_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 878 TARGET_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 914 TARGET_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 963 TARGET_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 999 TARGET_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 1024 TARGET_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 1049 TARGET_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 1080 TARGET_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 1094 TARGET_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 1118 TARGET_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 1142 TARGET_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 1165