| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2014 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/v8.h" |  | 
| 6 |  | 
| 7 #include "src/compiler/access-builder.h" |  | 
| 8 #include "src/compiler/common-operator.h" |  | 
| 9 #include "src/compiler/graph.h" |  | 
| 10 #include "src/compiler/graph-visualizer.h" |  | 
| 11 #include "src/compiler/js-operator.h" |  | 
| 12 #include "src/compiler/node.h" |  | 
| 13 #include "src/compiler/opcodes.h" |  | 
| 14 #include "src/compiler/operator.h" |  | 
| 15 #include "src/compiler/schedule.h" |  | 
| 16 #include "src/compiler/scheduler.h" |  | 
| 17 #include "src/compiler/simplified-operator.h" |  | 
| 18 #include "src/compiler/verifier.h" |  | 
| 19 #include "test/cctest/cctest.h" |  | 
| 20 |  | 
| 21 using namespace v8::internal; |  | 
| 22 using namespace v8::internal::compiler; |  | 
| 23 |  | 
| 24 Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, 0, 1, |  | 
| 25                  0, 0); |  | 
| 26 |  | 
| 27 // TODO(titzer): pull RPO tests out to their own file. |  | 
| 28 static void CheckRPONumbers(BasicBlockVector* order, size_t expected, |  | 
| 29                             bool loops_allowed) { |  | 
| 30   CHECK(expected == order->size()); |  | 
| 31   for (int i = 0; i < static_cast<int>(order->size()); i++) { |  | 
| 32     CHECK(order->at(i)->rpo_number() == i); |  | 
| 33     if (!loops_allowed) { |  | 
| 34       CHECK_EQ(NULL, order->at(i)->loop_end()); |  | 
| 35       CHECK_EQ(NULL, order->at(i)->loop_header()); |  | 
| 36     } |  | 
| 37   } |  | 
| 38 } |  | 
| 39 |  | 
| 40 |  | 
| 41 static void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, |  | 
| 42                       int body_size) { |  | 
| 43   BasicBlock* header = blocks[0]; |  | 
| 44   BasicBlock* end = header->loop_end(); |  | 
| 45   CHECK_NE(NULL, end); |  | 
| 46   CHECK_GT(end->rpo_number(), 0); |  | 
| 47   CHECK_EQ(body_size, end->rpo_number() - header->rpo_number()); |  | 
| 48   for (int i = 0; i < body_size; i++) { |  | 
| 49     CHECK_GE(blocks[i]->rpo_number(), header->rpo_number()); |  | 
| 50     CHECK_LT(blocks[i]->rpo_number(), end->rpo_number()); |  | 
| 51     CHECK(header->LoopContains(blocks[i])); |  | 
| 52     CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header); |  | 
| 53   } |  | 
| 54   if (header->rpo_number() > 0) { |  | 
| 55     CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header); |  | 
| 56   } |  | 
| 57   if (end->rpo_number() < static_cast<int>(order->size())) { |  | 
| 58     CHECK_NE(order->at(end->rpo_number())->loop_header(), header); |  | 
| 59   } |  | 
| 60 } |  | 
| 61 |  | 
| 62 |  | 
| 63 struct TestLoop { |  | 
| 64   int count; |  | 
| 65   BasicBlock** nodes; |  | 
| 66   BasicBlock* header() { return nodes[0]; } |  | 
| 67   BasicBlock* last() { return nodes[count - 1]; } |  | 
| 68   ~TestLoop() { delete[] nodes; } |  | 
| 69 |  | 
| 70   void Check(BasicBlockVector* order) { CheckLoop(order, nodes, count); } |  | 
| 71 }; |  | 
| 72 |  | 
| 73 |  | 
| 74 static TestLoop* CreateLoop(Schedule* schedule, int count) { |  | 
| 75   TestLoop* loop = new TestLoop(); |  | 
| 76   loop->count = count; |  | 
| 77   loop->nodes = new BasicBlock* [count]; |  | 
| 78   for (int i = 0; i < count; i++) { |  | 
| 79     loop->nodes[i] = schedule->NewBasicBlock(); |  | 
| 80     if (i > 0) { |  | 
| 81       schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]); |  | 
| 82     } |  | 
| 83   } |  | 
| 84   schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]); |  | 
| 85   return loop; |  | 
| 86 } |  | 
| 87 |  | 
| 88 |  | 
| 89 static int GetScheduledNodeCount(const Schedule* schedule) { |  | 
| 90   size_t node_count = 0; |  | 
| 91   for (auto block : *schedule->rpo_order()) { |  | 
| 92     node_count += block->NodeCount(); |  | 
| 93     if (block->control() != BasicBlock::kNone) ++node_count; |  | 
| 94   } |  | 
| 95   return static_cast<int>(node_count); |  | 
| 96 } |  | 
| 97 |  | 
| 98 |  | 
| 99 static Schedule* ComputeAndVerifySchedule(int expected, Graph* graph) { |  | 
| 100   if (FLAG_trace_turbo) { |  | 
| 101     OFStream os(stdout); |  | 
| 102     os << AsDOT(*graph); |  | 
| 103   } |  | 
| 104 |  | 
| 105   Schedule* schedule = Scheduler::ComputeSchedule(graph->zone(), graph); |  | 
| 106 |  | 
| 107   if (FLAG_trace_turbo_scheduler) { |  | 
| 108     OFStream os(stdout); |  | 
| 109     os << *schedule << std::endl; |  | 
| 110   } |  | 
| 111   ScheduleVerifier::Run(schedule); |  | 
| 112   CHECK_EQ(expected, GetScheduledNodeCount(schedule)); |  | 
| 113   return schedule; |  | 
| 114 } |  | 
| 115 |  | 
| 116 |  | 
| 117 TEST(RPODegenerate1) { |  | 
| 118   HandleAndZoneScope scope; |  | 
| 119   Schedule schedule(scope.main_zone()); |  | 
| 120 |  | 
| 121   BasicBlockVector* order = |  | 
| 122       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 123   CheckRPONumbers(order, 1, false); |  | 
| 124   CHECK_EQ(schedule.start(), order->at(0)); |  | 
| 125 } |  | 
| 126 |  | 
| 127 |  | 
| 128 TEST(RPODegenerate2) { |  | 
| 129   HandleAndZoneScope scope; |  | 
| 130   Schedule schedule(scope.main_zone()); |  | 
| 131 |  | 
| 132   schedule.AddGoto(schedule.start(), schedule.end()); |  | 
| 133   BasicBlockVector* order = |  | 
| 134       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 135   CheckRPONumbers(order, 2, false); |  | 
| 136   CHECK_EQ(schedule.start(), order->at(0)); |  | 
| 137   CHECK_EQ(schedule.end(), order->at(1)); |  | 
| 138 } |  | 
| 139 |  | 
| 140 |  | 
| 141 TEST(RPOLine) { |  | 
| 142   HandleAndZoneScope scope; |  | 
| 143 |  | 
| 144   for (int i = 0; i < 10; i++) { |  | 
| 145     Schedule schedule(scope.main_zone()); |  | 
| 146 |  | 
| 147     BasicBlock* last = schedule.start(); |  | 
| 148     for (int j = 0; j < i; j++) { |  | 
| 149       BasicBlock* block = schedule.NewBasicBlock(); |  | 
| 150       block->set_deferred(i & 1); |  | 
| 151       schedule.AddGoto(last, block); |  | 
| 152       last = block; |  | 
| 153     } |  | 
| 154     BasicBlockVector* order = |  | 
| 155         Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 156     CheckRPONumbers(order, 1 + i, false); |  | 
| 157 |  | 
| 158     for (size_t i = 0; i < schedule.BasicBlockCount(); i++) { |  | 
| 159       BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i)); |  | 
| 160       if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) { |  | 
| 161         CHECK(block->rpo_number() + 1 == block->SuccessorAt(0)->rpo_number()); |  | 
| 162       } |  | 
| 163     } |  | 
| 164   } |  | 
| 165 } |  | 
| 166 |  | 
| 167 |  | 
| 168 TEST(RPOSelfLoop) { |  | 
| 169   HandleAndZoneScope scope; |  | 
| 170   Schedule schedule(scope.main_zone()); |  | 
| 171   schedule.AddSuccessorForTesting(schedule.start(), schedule.start()); |  | 
| 172   BasicBlockVector* order = |  | 
| 173       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 174   CheckRPONumbers(order, 1, true); |  | 
| 175   BasicBlock* loop[] = {schedule.start()}; |  | 
| 176   CheckLoop(order, loop, 1); |  | 
| 177 } |  | 
| 178 |  | 
| 179 |  | 
| 180 TEST(RPOEntryLoop) { |  | 
| 181   HandleAndZoneScope scope; |  | 
| 182   Schedule schedule(scope.main_zone()); |  | 
| 183   BasicBlock* body = schedule.NewBasicBlock(); |  | 
| 184   schedule.AddSuccessorForTesting(schedule.start(), body); |  | 
| 185   schedule.AddSuccessorForTesting(body, schedule.start()); |  | 
| 186   BasicBlockVector* order = |  | 
| 187       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 188   CheckRPONumbers(order, 2, true); |  | 
| 189   BasicBlock* loop[] = {schedule.start(), body}; |  | 
| 190   CheckLoop(order, loop, 2); |  | 
| 191 } |  | 
| 192 |  | 
| 193 |  | 
| 194 TEST(RPOEndLoop) { |  | 
| 195   HandleAndZoneScope scope; |  | 
| 196   Schedule schedule(scope.main_zone()); |  | 
| 197   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2)); |  | 
| 198   schedule.AddSuccessorForTesting(schedule.start(), loop1->header()); |  | 
| 199   BasicBlockVector* order = |  | 
| 200       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 201   CheckRPONumbers(order, 3, true); |  | 
| 202   loop1->Check(order); |  | 
| 203 } |  | 
| 204 |  | 
| 205 |  | 
| 206 TEST(RPOEndLoopNested) { |  | 
| 207   HandleAndZoneScope scope; |  | 
| 208   Schedule schedule(scope.main_zone()); |  | 
| 209   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2)); |  | 
| 210   schedule.AddSuccessorForTesting(schedule.start(), loop1->header()); |  | 
| 211   schedule.AddSuccessorForTesting(loop1->last(), schedule.start()); |  | 
| 212   BasicBlockVector* order = |  | 
| 213       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 214   CheckRPONumbers(order, 3, true); |  | 
| 215   loop1->Check(order); |  | 
| 216 } |  | 
| 217 |  | 
| 218 |  | 
| 219 TEST(RPODiamond) { |  | 
| 220   HandleAndZoneScope scope; |  | 
| 221   Schedule schedule(scope.main_zone()); |  | 
| 222 |  | 
| 223   BasicBlock* A = schedule.start(); |  | 
| 224   BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 225   BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 226   BasicBlock* D = schedule.end(); |  | 
| 227 |  | 
| 228   schedule.AddSuccessorForTesting(A, B); |  | 
| 229   schedule.AddSuccessorForTesting(A, C); |  | 
| 230   schedule.AddSuccessorForTesting(B, D); |  | 
| 231   schedule.AddSuccessorForTesting(C, D); |  | 
| 232 |  | 
| 233   BasicBlockVector* order = |  | 
| 234       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 235   CheckRPONumbers(order, 4, false); |  | 
| 236 |  | 
| 237   CHECK_EQ(0, A->rpo_number()); |  | 
| 238   CHECK((B->rpo_number() == 1 && C->rpo_number() == 2) || |  | 
| 239         (B->rpo_number() == 2 && C->rpo_number() == 1)); |  | 
| 240   CHECK_EQ(3, D->rpo_number()); |  | 
| 241 } |  | 
| 242 |  | 
| 243 |  | 
| 244 TEST(RPOLoop1) { |  | 
| 245   HandleAndZoneScope scope; |  | 
| 246   Schedule schedule(scope.main_zone()); |  | 
| 247 |  | 
| 248   BasicBlock* A = schedule.start(); |  | 
| 249   BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 250   BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 251   BasicBlock* D = schedule.end(); |  | 
| 252 |  | 
| 253   schedule.AddSuccessorForTesting(A, B); |  | 
| 254   schedule.AddSuccessorForTesting(B, C); |  | 
| 255   schedule.AddSuccessorForTesting(C, B); |  | 
| 256   schedule.AddSuccessorForTesting(C, D); |  | 
| 257 |  | 
| 258   BasicBlockVector* order = |  | 
| 259       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 260   CheckRPONumbers(order, 4, true); |  | 
| 261   BasicBlock* loop[] = {B, C}; |  | 
| 262   CheckLoop(order, loop, 2); |  | 
| 263 } |  | 
| 264 |  | 
| 265 |  | 
| 266 TEST(RPOLoop2) { |  | 
| 267   HandleAndZoneScope scope; |  | 
| 268   Schedule schedule(scope.main_zone()); |  | 
| 269 |  | 
| 270   BasicBlock* A = schedule.start(); |  | 
| 271   BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 272   BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 273   BasicBlock* D = schedule.end(); |  | 
| 274 |  | 
| 275   schedule.AddSuccessorForTesting(A, B); |  | 
| 276   schedule.AddSuccessorForTesting(B, C); |  | 
| 277   schedule.AddSuccessorForTesting(C, B); |  | 
| 278   schedule.AddSuccessorForTesting(B, D); |  | 
| 279 |  | 
| 280   BasicBlockVector* order = |  | 
| 281       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 282   CheckRPONumbers(order, 4, true); |  | 
| 283   BasicBlock* loop[] = {B, C}; |  | 
| 284   CheckLoop(order, loop, 2); |  | 
| 285 } |  | 
| 286 |  | 
| 287 |  | 
| 288 TEST(RPOLoopN) { |  | 
| 289   HandleAndZoneScope scope; |  | 
| 290 |  | 
| 291   for (int i = 0; i < 11; i++) { |  | 
| 292     Schedule schedule(scope.main_zone()); |  | 
| 293     BasicBlock* A = schedule.start(); |  | 
| 294     BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 295     BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 296     BasicBlock* D = schedule.NewBasicBlock(); |  | 
| 297     BasicBlock* E = schedule.NewBasicBlock(); |  | 
| 298     BasicBlock* F = schedule.NewBasicBlock(); |  | 
| 299     BasicBlock* G = schedule.end(); |  | 
| 300 |  | 
| 301     schedule.AddSuccessorForTesting(A, B); |  | 
| 302     schedule.AddSuccessorForTesting(B, C); |  | 
| 303     schedule.AddSuccessorForTesting(C, D); |  | 
| 304     schedule.AddSuccessorForTesting(D, E); |  | 
| 305     schedule.AddSuccessorForTesting(E, F); |  | 
| 306     schedule.AddSuccessorForTesting(F, B); |  | 
| 307     schedule.AddSuccessorForTesting(B, G); |  | 
| 308 |  | 
| 309     // Throw in extra backedges from time to time. |  | 
| 310     if (i == 1) schedule.AddSuccessorForTesting(B, B); |  | 
| 311     if (i == 2) schedule.AddSuccessorForTesting(C, B); |  | 
| 312     if (i == 3) schedule.AddSuccessorForTesting(D, B); |  | 
| 313     if (i == 4) schedule.AddSuccessorForTesting(E, B); |  | 
| 314     if (i == 5) schedule.AddSuccessorForTesting(F, B); |  | 
| 315 |  | 
| 316     // Throw in extra loop exits from time to time. |  | 
| 317     if (i == 6) schedule.AddSuccessorForTesting(B, G); |  | 
| 318     if (i == 7) schedule.AddSuccessorForTesting(C, G); |  | 
| 319     if (i == 8) schedule.AddSuccessorForTesting(D, G); |  | 
| 320     if (i == 9) schedule.AddSuccessorForTesting(E, G); |  | 
| 321     if (i == 10) schedule.AddSuccessorForTesting(F, G); |  | 
| 322 |  | 
| 323     BasicBlockVector* order = |  | 
| 324         Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 325     CheckRPONumbers(order, 7, true); |  | 
| 326     BasicBlock* loop[] = {B, C, D, E, F}; |  | 
| 327     CheckLoop(order, loop, 5); |  | 
| 328   } |  | 
| 329 } |  | 
| 330 |  | 
| 331 |  | 
| 332 TEST(RPOLoopNest1) { |  | 
| 333   HandleAndZoneScope scope; |  | 
| 334   Schedule schedule(scope.main_zone()); |  | 
| 335 |  | 
| 336   BasicBlock* A = schedule.start(); |  | 
| 337   BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 338   BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 339   BasicBlock* D = schedule.NewBasicBlock(); |  | 
| 340   BasicBlock* E = schedule.NewBasicBlock(); |  | 
| 341   BasicBlock* F = schedule.end(); |  | 
| 342 |  | 
| 343   schedule.AddSuccessorForTesting(A, B); |  | 
| 344   schedule.AddSuccessorForTesting(B, C); |  | 
| 345   schedule.AddSuccessorForTesting(C, D); |  | 
| 346   schedule.AddSuccessorForTesting(D, C); |  | 
| 347   schedule.AddSuccessorForTesting(D, E); |  | 
| 348   schedule.AddSuccessorForTesting(E, B); |  | 
| 349   schedule.AddSuccessorForTesting(E, F); |  | 
| 350 |  | 
| 351   BasicBlockVector* order = |  | 
| 352       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 353   CheckRPONumbers(order, 6, true); |  | 
| 354   BasicBlock* loop1[] = {B, C, D, E}; |  | 
| 355   CheckLoop(order, loop1, 4); |  | 
| 356 |  | 
| 357   BasicBlock* loop2[] = {C, D}; |  | 
| 358   CheckLoop(order, loop2, 2); |  | 
| 359 } |  | 
| 360 |  | 
| 361 |  | 
| 362 TEST(RPOLoopNest2) { |  | 
| 363   HandleAndZoneScope scope; |  | 
| 364   Schedule schedule(scope.main_zone()); |  | 
| 365 |  | 
| 366   BasicBlock* A = schedule.start(); |  | 
| 367   BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 368   BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 369   BasicBlock* D = schedule.NewBasicBlock(); |  | 
| 370   BasicBlock* E = schedule.NewBasicBlock(); |  | 
| 371   BasicBlock* F = schedule.NewBasicBlock(); |  | 
| 372   BasicBlock* G = schedule.NewBasicBlock(); |  | 
| 373   BasicBlock* H = schedule.end(); |  | 
| 374 |  | 
| 375   schedule.AddSuccessorForTesting(A, B); |  | 
| 376   schedule.AddSuccessorForTesting(B, C); |  | 
| 377   schedule.AddSuccessorForTesting(C, D); |  | 
| 378   schedule.AddSuccessorForTesting(D, E); |  | 
| 379   schedule.AddSuccessorForTesting(E, F); |  | 
| 380   schedule.AddSuccessorForTesting(F, G); |  | 
| 381   schedule.AddSuccessorForTesting(G, H); |  | 
| 382 |  | 
| 383   schedule.AddSuccessorForTesting(E, D); |  | 
| 384   schedule.AddSuccessorForTesting(F, C); |  | 
| 385   schedule.AddSuccessorForTesting(G, B); |  | 
| 386 |  | 
| 387   BasicBlockVector* order = |  | 
| 388       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 389   CheckRPONumbers(order, 8, true); |  | 
| 390   BasicBlock* loop1[] = {B, C, D, E, F, G}; |  | 
| 391   CheckLoop(order, loop1, 6); |  | 
| 392 |  | 
| 393   BasicBlock* loop2[] = {C, D, E, F}; |  | 
| 394   CheckLoop(order, loop2, 4); |  | 
| 395 |  | 
| 396   BasicBlock* loop3[] = {D, E}; |  | 
| 397   CheckLoop(order, loop3, 2); |  | 
| 398 } |  | 
| 399 |  | 
| 400 |  | 
| 401 TEST(RPOLoopFollow1) { |  | 
| 402   HandleAndZoneScope scope; |  | 
| 403   Schedule schedule(scope.main_zone()); |  | 
| 404 |  | 
| 405   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); |  | 
| 406   SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); |  | 
| 407 |  | 
| 408   BasicBlock* A = schedule.start(); |  | 
| 409   BasicBlock* E = schedule.end(); |  | 
| 410 |  | 
| 411   schedule.AddSuccessorForTesting(A, loop1->header()); |  | 
| 412   schedule.AddSuccessorForTesting(loop1->header(), loop2->header()); |  | 
| 413   schedule.AddSuccessorForTesting(loop2->last(), E); |  | 
| 414 |  | 
| 415   BasicBlockVector* order = |  | 
| 416       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 417 |  | 
| 418   CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), |  | 
| 419            static_cast<int>(order->size())); |  | 
| 420 |  | 
| 421   loop1->Check(order); |  | 
| 422   loop2->Check(order); |  | 
| 423 } |  | 
| 424 |  | 
| 425 |  | 
| 426 TEST(RPOLoopFollow2) { |  | 
| 427   HandleAndZoneScope scope; |  | 
| 428   Schedule schedule(scope.main_zone()); |  | 
| 429 |  | 
| 430   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); |  | 
| 431   SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); |  | 
| 432 |  | 
| 433   BasicBlock* A = schedule.start(); |  | 
| 434   BasicBlock* S = schedule.NewBasicBlock(); |  | 
| 435   BasicBlock* E = schedule.end(); |  | 
| 436 |  | 
| 437   schedule.AddSuccessorForTesting(A, loop1->header()); |  | 
| 438   schedule.AddSuccessorForTesting(loop1->header(), S); |  | 
| 439   schedule.AddSuccessorForTesting(S, loop2->header()); |  | 
| 440   schedule.AddSuccessorForTesting(loop2->last(), E); |  | 
| 441 |  | 
| 442   BasicBlockVector* order = |  | 
| 443       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 444 |  | 
| 445   CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), |  | 
| 446            static_cast<int>(order->size())); |  | 
| 447   loop1->Check(order); |  | 
| 448   loop2->Check(order); |  | 
| 449 } |  | 
| 450 |  | 
| 451 |  | 
| 452 TEST(RPOLoopFollowN) { |  | 
| 453   HandleAndZoneScope scope; |  | 
| 454 |  | 
| 455   for (int size = 1; size < 5; size++) { |  | 
| 456     for (int exit = 0; exit < size; exit++) { |  | 
| 457       Schedule schedule(scope.main_zone()); |  | 
| 458       SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); |  | 
| 459       SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size)); |  | 
| 460       BasicBlock* A = schedule.start(); |  | 
| 461       BasicBlock* E = schedule.end(); |  | 
| 462 |  | 
| 463       schedule.AddSuccessorForTesting(A, loop1->header()); |  | 
| 464       schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header()); |  | 
| 465       schedule.AddSuccessorForTesting(loop2->nodes[exit], E); |  | 
| 466       BasicBlockVector* order = |  | 
| 467           Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 468 |  | 
| 469       CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), |  | 
| 470                static_cast<int>(order->size())); |  | 
| 471       loop1->Check(order); |  | 
| 472       loop2->Check(order); |  | 
| 473     } |  | 
| 474   } |  | 
| 475 } |  | 
| 476 |  | 
| 477 |  | 
| 478 TEST(RPONestedLoopFollow1) { |  | 
| 479   HandleAndZoneScope scope; |  | 
| 480   Schedule schedule(scope.main_zone()); |  | 
| 481 |  | 
| 482   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); |  | 
| 483   SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); |  | 
| 484 |  | 
| 485   BasicBlock* A = schedule.start(); |  | 
| 486   BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 487   BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 488   BasicBlock* E = schedule.end(); |  | 
| 489 |  | 
| 490   schedule.AddSuccessorForTesting(A, B); |  | 
| 491   schedule.AddSuccessorForTesting(B, loop1->header()); |  | 
| 492   schedule.AddSuccessorForTesting(loop1->header(), loop2->header()); |  | 
| 493   schedule.AddSuccessorForTesting(loop2->last(), C); |  | 
| 494   schedule.AddSuccessorForTesting(C, E); |  | 
| 495   schedule.AddSuccessorForTesting(C, B); |  | 
| 496 |  | 
| 497   BasicBlockVector* order = |  | 
| 498       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 499 |  | 
| 500   CHECK_EQ(static_cast<int>(schedule.BasicBlockCount()), |  | 
| 501            static_cast<int>(order->size())); |  | 
| 502   loop1->Check(order); |  | 
| 503   loop2->Check(order); |  | 
| 504 |  | 
| 505   BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C}; |  | 
| 506   CheckLoop(order, loop3, 4); |  | 
| 507 } |  | 
| 508 |  | 
| 509 |  | 
| 510 TEST(RPOLoopBackedges1) { |  | 
| 511   HandleAndZoneScope scope; |  | 
| 512 |  | 
| 513   int size = 8; |  | 
| 514   for (int i = 0; i < size; i++) { |  | 
| 515     for (int j = 0; j < size; j++) { |  | 
| 516       Schedule schedule(scope.main_zone()); |  | 
| 517       BasicBlock* A = schedule.start(); |  | 
| 518       BasicBlock* E = schedule.end(); |  | 
| 519 |  | 
| 520       SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); |  | 
| 521       schedule.AddSuccessorForTesting(A, loop1->header()); |  | 
| 522       schedule.AddSuccessorForTesting(loop1->last(), E); |  | 
| 523 |  | 
| 524       schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header()); |  | 
| 525       schedule.AddSuccessorForTesting(loop1->nodes[j], E); |  | 
| 526 |  | 
| 527       BasicBlockVector* order = |  | 
| 528           Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 529       CheckRPONumbers(order, schedule.BasicBlockCount(), true); |  | 
| 530       loop1->Check(order); |  | 
| 531     } |  | 
| 532   } |  | 
| 533 } |  | 
| 534 |  | 
| 535 |  | 
| 536 TEST(RPOLoopOutedges1) { |  | 
| 537   HandleAndZoneScope scope; |  | 
| 538 |  | 
| 539   int size = 8; |  | 
| 540   for (int i = 0; i < size; i++) { |  | 
| 541     for (int j = 0; j < size; j++) { |  | 
| 542       Schedule schedule(scope.main_zone()); |  | 
| 543       BasicBlock* A = schedule.start(); |  | 
| 544       BasicBlock* D = schedule.NewBasicBlock(); |  | 
| 545       BasicBlock* E = schedule.end(); |  | 
| 546 |  | 
| 547       SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); |  | 
| 548       schedule.AddSuccessorForTesting(A, loop1->header()); |  | 
| 549       schedule.AddSuccessorForTesting(loop1->last(), E); |  | 
| 550 |  | 
| 551       schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header()); |  | 
| 552       schedule.AddSuccessorForTesting(loop1->nodes[j], D); |  | 
| 553       schedule.AddSuccessorForTesting(D, E); |  | 
| 554 |  | 
| 555       BasicBlockVector* order = |  | 
| 556           Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 557       CheckRPONumbers(order, schedule.BasicBlockCount(), true); |  | 
| 558       loop1->Check(order); |  | 
| 559     } |  | 
| 560   } |  | 
| 561 } |  | 
| 562 |  | 
| 563 |  | 
| 564 TEST(RPOLoopOutedges2) { |  | 
| 565   HandleAndZoneScope scope; |  | 
| 566 |  | 
| 567   int size = 8; |  | 
| 568   for (int i = 0; i < size; i++) { |  | 
| 569     Schedule schedule(scope.main_zone()); |  | 
| 570     BasicBlock* A = schedule.start(); |  | 
| 571     BasicBlock* E = schedule.end(); |  | 
| 572 |  | 
| 573     SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); |  | 
| 574     schedule.AddSuccessorForTesting(A, loop1->header()); |  | 
| 575     schedule.AddSuccessorForTesting(loop1->last(), E); |  | 
| 576 |  | 
| 577     for (int j = 0; j < size; j++) { |  | 
| 578       BasicBlock* O = schedule.NewBasicBlock(); |  | 
| 579       schedule.AddSuccessorForTesting(loop1->nodes[j], O); |  | 
| 580       schedule.AddSuccessorForTesting(O, E); |  | 
| 581     } |  | 
| 582 |  | 
| 583     BasicBlockVector* order = |  | 
| 584         Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 585     CheckRPONumbers(order, schedule.BasicBlockCount(), true); |  | 
| 586     loop1->Check(order); |  | 
| 587   } |  | 
| 588 } |  | 
| 589 |  | 
| 590 |  | 
| 591 TEST(RPOLoopOutloops1) { |  | 
| 592   HandleAndZoneScope scope; |  | 
| 593 |  | 
| 594   int size = 8; |  | 
| 595   for (int i = 0; i < size; i++) { |  | 
| 596     Schedule schedule(scope.main_zone()); |  | 
| 597     BasicBlock* A = schedule.start(); |  | 
| 598     BasicBlock* E = schedule.end(); |  | 
| 599     SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); |  | 
| 600     schedule.AddSuccessorForTesting(A, loop1->header()); |  | 
| 601     schedule.AddSuccessorForTesting(loop1->last(), E); |  | 
| 602 |  | 
| 603     TestLoop** loopN = new TestLoop* [size]; |  | 
| 604     for (int j = 0; j < size; j++) { |  | 
| 605       loopN[j] = CreateLoop(&schedule, 2); |  | 
| 606       schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header()); |  | 
| 607       schedule.AddSuccessorForTesting(loopN[j]->last(), E); |  | 
| 608     } |  | 
| 609 |  | 
| 610     BasicBlockVector* order = |  | 
| 611         Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 612     CheckRPONumbers(order, schedule.BasicBlockCount(), true); |  | 
| 613     loop1->Check(order); |  | 
| 614 |  | 
| 615     for (int j = 0; j < size; j++) { |  | 
| 616       loopN[j]->Check(order); |  | 
| 617       delete loopN[j]; |  | 
| 618     } |  | 
| 619     delete[] loopN; |  | 
| 620   } |  | 
| 621 } |  | 
| 622 |  | 
| 623 |  | 
| 624 TEST(RPOLoopMultibackedge) { |  | 
| 625   HandleAndZoneScope scope; |  | 
| 626   Schedule schedule(scope.main_zone()); |  | 
| 627 |  | 
| 628   BasicBlock* A = schedule.start(); |  | 
| 629   BasicBlock* B = schedule.NewBasicBlock(); |  | 
| 630   BasicBlock* C = schedule.NewBasicBlock(); |  | 
| 631   BasicBlock* D = schedule.NewBasicBlock(); |  | 
| 632   BasicBlock* E = schedule.NewBasicBlock(); |  | 
| 633 |  | 
| 634   schedule.AddSuccessorForTesting(A, B); |  | 
| 635   schedule.AddSuccessorForTesting(B, C); |  | 
| 636   schedule.AddSuccessorForTesting(B, D); |  | 
| 637   schedule.AddSuccessorForTesting(B, E); |  | 
| 638   schedule.AddSuccessorForTesting(C, B); |  | 
| 639   schedule.AddSuccessorForTesting(D, B); |  | 
| 640   schedule.AddSuccessorForTesting(E, B); |  | 
| 641 |  | 
| 642   BasicBlockVector* order = |  | 
| 643       Scheduler::ComputeSpecialRPO(scope.main_zone(), &schedule); |  | 
| 644   CheckRPONumbers(order, 5, true); |  | 
| 645 |  | 
| 646   BasicBlock* loop1[] = {B, C, D, E}; |  | 
| 647   CheckLoop(order, loop1, 4); |  | 
| 648 } |  | 
| 649 |  | 
| 650 |  | 
| 651 TEST(BuildScheduleEmpty) { |  | 
| 652   HandleAndZoneScope scope; |  | 
| 653   Graph graph(scope.main_zone()); |  | 
| 654   CommonOperatorBuilder builder(scope.main_zone()); |  | 
| 655   graph.SetStart(graph.NewNode(builder.Start(0))); |  | 
| 656   graph.SetEnd(graph.NewNode(builder.End(), graph.start())); |  | 
| 657 |  | 
| 658   USE(Scheduler::ComputeSchedule(scope.main_zone(), &graph)); |  | 
| 659 } |  | 
| 660 |  | 
| 661 |  | 
| 662 TEST(BuildScheduleOneParameter) { |  | 
| 663   HandleAndZoneScope scope; |  | 
| 664   Graph graph(scope.main_zone()); |  | 
| 665   CommonOperatorBuilder builder(scope.main_zone()); |  | 
| 666   graph.SetStart(graph.NewNode(builder.Start(0))); |  | 
| 667 |  | 
| 668   Node* p1 = graph.NewNode(builder.Parameter(0), graph.start()); |  | 
| 669   Node* ret = graph.NewNode(builder.Return(), p1, graph.start(), graph.start()); |  | 
| 670 |  | 
| 671   graph.SetEnd(graph.NewNode(builder.End(), ret)); |  | 
| 672 |  | 
| 673   USE(Scheduler::ComputeSchedule(scope.main_zone(), &graph)); |  | 
| 674 } |  | 
| 675 |  | 
| 676 |  | 
| 677 TEST(BuildScheduleIfSplit) { |  | 
| 678   HandleAndZoneScope scope; |  | 
| 679   Graph graph(scope.main_zone()); |  | 
| 680   CommonOperatorBuilder builder(scope.main_zone()); |  | 
| 681   JSOperatorBuilder js_builder(scope.main_zone()); |  | 
| 682   graph.SetStart(graph.NewNode(builder.Start(3))); |  | 
| 683 |  | 
| 684   Node* p1 = graph.NewNode(builder.Parameter(0), graph.start()); |  | 
| 685   Node* p2 = graph.NewNode(builder.Parameter(1), graph.start()); |  | 
| 686   Node* p3 = graph.NewNode(builder.Parameter(2), graph.start()); |  | 
| 687   Node* p4 = graph.NewNode(builder.Parameter(3), graph.start()); |  | 
| 688   Node* p5 = graph.NewNode(builder.Parameter(4), graph.start()); |  | 
| 689   Node* cmp = graph.NewNode(js_builder.LessThanOrEqual(), p1, p2, p3, |  | 
| 690                             graph.start(), graph.start()); |  | 
| 691   Node* branch = graph.NewNode(builder.Branch(), cmp, graph.start()); |  | 
| 692   Node* true_branch = graph.NewNode(builder.IfTrue(), branch); |  | 
| 693   Node* false_branch = graph.NewNode(builder.IfFalse(), branch); |  | 
| 694 |  | 
| 695   Node* ret1 = graph.NewNode(builder.Return(), p4, graph.start(), true_branch); |  | 
| 696   Node* ret2 = graph.NewNode(builder.Return(), p5, graph.start(), false_branch); |  | 
| 697   Node* merge = graph.NewNode(builder.Merge(2), ret1, ret2); |  | 
| 698   graph.SetEnd(graph.NewNode(builder.End(), merge)); |  | 
| 699 |  | 
| 700   ComputeAndVerifySchedule(13, &graph); |  | 
| 701 } |  | 
| 702 |  | 
| 703 |  | 
| 704 TEST(BuildScheduleIfSplitWithEffects) { |  | 
| 705   HandleAndZoneScope scope; |  | 
| 706   Isolate* isolate = scope.main_isolate(); |  | 
| 707   Graph graph(scope.main_zone()); |  | 
| 708   CommonOperatorBuilder common_builder(scope.main_zone()); |  | 
| 709   JSOperatorBuilder js_builder(scope.main_zone()); |  | 
| 710   const Operator* op; |  | 
| 711 |  | 
| 712   Handle<HeapObject> object = |  | 
| 713       Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); |  | 
| 714   Unique<HeapObject> unique_constant = |  | 
| 715       Unique<HeapObject>::CreateUninitialized(object); |  | 
| 716 |  | 
| 717   // Manually transcripted code for: |  | 
| 718   // function turbo_fan_test(a, b, c, y) { |  | 
| 719   //   if (a < b) { |  | 
| 720   //     return a + b - c * c - a + y; |  | 
| 721   //   } else { |  | 
| 722   //     return c * c - a; |  | 
| 723   //   } |  | 
| 724   // } |  | 
| 725   op = common_builder.Start(0); |  | 
| 726   Node* n0 = graph.NewNode(op); |  | 
| 727   USE(n0); |  | 
| 728   Node* nil = graph.NewNode(common_builder.Dead()); |  | 
| 729   op = common_builder.End(); |  | 
| 730   Node* n23 = graph.NewNode(op, nil); |  | 
| 731   USE(n23); |  | 
| 732   op = common_builder.Merge(2); |  | 
| 733   Node* n22 = graph.NewNode(op, nil, nil); |  | 
| 734   USE(n22); |  | 
| 735   op = common_builder.Return(); |  | 
| 736   Node* n16 = graph.NewNode(op, nil, nil, nil); |  | 
| 737   USE(n16); |  | 
| 738   op = js_builder.Add(); |  | 
| 739   Node* n15 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 740   USE(n15); |  | 
| 741   op = js_builder.Subtract(); |  | 
| 742   Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 743   USE(n14); |  | 
| 744   op = js_builder.Subtract(); |  | 
| 745   Node* n13 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 746   USE(n13); |  | 
| 747   op = js_builder.Add(); |  | 
| 748   Node* n11 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 749   USE(n11); |  | 
| 750   op = common_builder.Parameter(0); |  | 
| 751   Node* n2 = graph.NewNode(op, n0); |  | 
| 752   USE(n2); |  | 
| 753   n11->ReplaceInput(0, n2); |  | 
| 754   op = common_builder.Parameter(0); |  | 
| 755   Node* n3 = graph.NewNode(op, n0); |  | 
| 756   USE(n3); |  | 
| 757   n11->ReplaceInput(1, n3); |  | 
| 758   op = common_builder.HeapConstant(unique_constant); |  | 
| 759   Node* n7 = graph.NewNode(op); |  | 
| 760   USE(n7); |  | 
| 761   n11->ReplaceInput(2, n7); |  | 
| 762   op = js_builder.LessThan(); |  | 
| 763   Node* n8 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 764   USE(n8); |  | 
| 765   n8->ReplaceInput(0, n2); |  | 
| 766   n8->ReplaceInput(1, n3); |  | 
| 767   n8->ReplaceInput(2, n7); |  | 
| 768   n8->ReplaceInput(3, n0); |  | 
| 769   n8->ReplaceInput(4, n0); |  | 
| 770   n11->ReplaceInput(3, n8); |  | 
| 771   op = common_builder.IfTrue(); |  | 
| 772   Node* n10 = graph.NewNode(op, nil); |  | 
| 773   USE(n10); |  | 
| 774   op = common_builder.Branch(); |  | 
| 775   Node* n9 = graph.NewNode(op, nil, nil); |  | 
| 776   USE(n9); |  | 
| 777   n9->ReplaceInput(0, n8); |  | 
| 778   n9->ReplaceInput(1, n0); |  | 
| 779   n10->ReplaceInput(0, n9); |  | 
| 780   n11->ReplaceInput(4, n10); |  | 
| 781   n13->ReplaceInput(0, n11); |  | 
| 782   op = js_builder.Multiply(); |  | 
| 783   Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 784   USE(n12); |  | 
| 785   op = common_builder.Parameter(0); |  | 
| 786   Node* n4 = graph.NewNode(op, n0); |  | 
| 787   USE(n4); |  | 
| 788   n12->ReplaceInput(0, n4); |  | 
| 789   n12->ReplaceInput(1, n4); |  | 
| 790   n12->ReplaceInput(2, n7); |  | 
| 791   n12->ReplaceInput(3, n11); |  | 
| 792   n12->ReplaceInput(4, n10); |  | 
| 793   n13->ReplaceInput(1, n12); |  | 
| 794   n13->ReplaceInput(2, n7); |  | 
| 795   n13->ReplaceInput(3, n12); |  | 
| 796   n13->ReplaceInput(4, n10); |  | 
| 797   n14->ReplaceInput(0, n13); |  | 
| 798   n14->ReplaceInput(1, n2); |  | 
| 799   n14->ReplaceInput(2, n7); |  | 
| 800   n14->ReplaceInput(3, n13); |  | 
| 801   n14->ReplaceInput(4, n10); |  | 
| 802   n15->ReplaceInput(0, n14); |  | 
| 803   op = common_builder.Parameter(0); |  | 
| 804   Node* n5 = graph.NewNode(op, n0); |  | 
| 805   USE(n5); |  | 
| 806   n15->ReplaceInput(1, n5); |  | 
| 807   n15->ReplaceInput(2, n7); |  | 
| 808   n15->ReplaceInput(3, n14); |  | 
| 809   n15->ReplaceInput(4, n10); |  | 
| 810   n16->ReplaceInput(0, n15); |  | 
| 811   n16->ReplaceInput(1, n15); |  | 
| 812   n16->ReplaceInput(2, n10); |  | 
| 813   n22->ReplaceInput(0, n16); |  | 
| 814   op = common_builder.Return(); |  | 
| 815   Node* n21 = graph.NewNode(op, nil, nil, nil); |  | 
| 816   USE(n21); |  | 
| 817   op = js_builder.Subtract(); |  | 
| 818   Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 819   USE(n20); |  | 
| 820   op = js_builder.Multiply(); |  | 
| 821   Node* n19 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 822   USE(n19); |  | 
| 823   n19->ReplaceInput(0, n4); |  | 
| 824   n19->ReplaceInput(1, n4); |  | 
| 825   n19->ReplaceInput(2, n7); |  | 
| 826   n19->ReplaceInput(3, n8); |  | 
| 827   op = common_builder.IfFalse(); |  | 
| 828   Node* n18 = graph.NewNode(op, nil); |  | 
| 829   USE(n18); |  | 
| 830   n18->ReplaceInput(0, n9); |  | 
| 831   n19->ReplaceInput(4, n18); |  | 
| 832   n20->ReplaceInput(0, n19); |  | 
| 833   n20->ReplaceInput(1, n2); |  | 
| 834   n20->ReplaceInput(2, n7); |  | 
| 835   n20->ReplaceInput(3, n19); |  | 
| 836   n20->ReplaceInput(4, n18); |  | 
| 837   n21->ReplaceInput(0, n20); |  | 
| 838   n21->ReplaceInput(1, n20); |  | 
| 839   n21->ReplaceInput(2, n18); |  | 
| 840   n22->ReplaceInput(1, n21); |  | 
| 841   n23->ReplaceInput(0, n22); |  | 
| 842 |  | 
| 843   graph.SetStart(n0); |  | 
| 844   graph.SetEnd(n23); |  | 
| 845 |  | 
| 846   ComputeAndVerifySchedule(20, &graph); |  | 
| 847 } |  | 
| 848 |  | 
| 849 |  | 
| 850 TEST(BuildScheduleSimpleLoop) { |  | 
| 851   HandleAndZoneScope scope; |  | 
| 852   Isolate* isolate = scope.main_isolate(); |  | 
| 853   Graph graph(scope.main_zone()); |  | 
| 854   CommonOperatorBuilder common_builder(scope.main_zone()); |  | 
| 855   JSOperatorBuilder js_builder(scope.main_zone()); |  | 
| 856   const Operator* op; |  | 
| 857 |  | 
| 858   Handle<HeapObject> object = |  | 
| 859       Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); |  | 
| 860   Unique<HeapObject> unique_constant = |  | 
| 861       Unique<HeapObject>::CreateUninitialized(object); |  | 
| 862 |  | 
| 863   // Manually transcripted code for: |  | 
| 864   // function turbo_fan_test(a, b) { |  | 
| 865   //   while (a < b) { |  | 
| 866   //     a++; |  | 
| 867   //   } |  | 
| 868   //   return a; |  | 
| 869   // } |  | 
| 870   op = common_builder.Start(0); |  | 
| 871   Node* n0 = graph.NewNode(op); |  | 
| 872   USE(n0); |  | 
| 873   Node* nil = graph.NewNode(common_builder.Dead()); |  | 
| 874   op = common_builder.End(); |  | 
| 875   Node* n20 = graph.NewNode(op, nil); |  | 
| 876   USE(n20); |  | 
| 877   op = common_builder.Return(); |  | 
| 878   Node* n19 = graph.NewNode(op, nil, nil, nil); |  | 
| 879   USE(n19); |  | 
| 880   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 881   Node* n8 = graph.NewNode(op, nil, nil, nil); |  | 
| 882   USE(n8); |  | 
| 883   op = common_builder.Parameter(0); |  | 
| 884   Node* n2 = graph.NewNode(op, n0); |  | 
| 885   USE(n2); |  | 
| 886   n8->ReplaceInput(0, n2); |  | 
| 887   op = js_builder.Add(); |  | 
| 888   Node* n18 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 889   USE(n18); |  | 
| 890   op = js_builder.ToNumber(); |  | 
| 891   Node* n16 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 892   USE(n16); |  | 
| 893   n16->ReplaceInput(0, n8); |  | 
| 894   op = common_builder.HeapConstant(unique_constant); |  | 
| 895   Node* n5 = graph.NewNode(op); |  | 
| 896   USE(n5); |  | 
| 897   n16->ReplaceInput(1, n5); |  | 
| 898   op = js_builder.LessThan(); |  | 
| 899   Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 900   USE(n12); |  | 
| 901   n12->ReplaceInput(0, n8); |  | 
| 902   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 903   Node* n9 = graph.NewNode(op, nil, nil, nil); |  | 
| 904   USE(n9); |  | 
| 905   op = common_builder.Parameter(0); |  | 
| 906   Node* n3 = graph.NewNode(op, n0); |  | 
| 907   USE(n3); |  | 
| 908   n9->ReplaceInput(0, n3); |  | 
| 909   n9->ReplaceInput(1, n9); |  | 
| 910   op = common_builder.Loop(2); |  | 
| 911   Node* n6 = graph.NewNode(op, nil, nil); |  | 
| 912   USE(n6); |  | 
| 913   n6->ReplaceInput(0, n0); |  | 
| 914   op = common_builder.IfTrue(); |  | 
| 915   Node* n14 = graph.NewNode(op, nil); |  | 
| 916   USE(n14); |  | 
| 917   op = common_builder.Branch(); |  | 
| 918   Node* n13 = graph.NewNode(op, nil, nil); |  | 
| 919   USE(n13); |  | 
| 920   n13->ReplaceInput(0, n12); |  | 
| 921   n13->ReplaceInput(1, n6); |  | 
| 922   n14->ReplaceInput(0, n13); |  | 
| 923   n6->ReplaceInput(1, n14); |  | 
| 924   n9->ReplaceInput(2, n6); |  | 
| 925   n12->ReplaceInput(1, n9); |  | 
| 926   n12->ReplaceInput(2, n5); |  | 
| 927   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 928   Node* n10 = graph.NewNode(op, nil, nil, nil); |  | 
| 929   USE(n10); |  | 
| 930   n10->ReplaceInput(0, n0); |  | 
| 931   n10->ReplaceInput(1, n18); |  | 
| 932   n10->ReplaceInput(2, n6); |  | 
| 933   n12->ReplaceInput(3, n10); |  | 
| 934   n12->ReplaceInput(4, n6); |  | 
| 935   n16->ReplaceInput(2, n12); |  | 
| 936   n16->ReplaceInput(3, n14); |  | 
| 937   n18->ReplaceInput(0, n16); |  | 
| 938   op = common_builder.NumberConstant(0); |  | 
| 939   Node* n17 = graph.NewNode(op); |  | 
| 940   USE(n17); |  | 
| 941   n18->ReplaceInput(1, n17); |  | 
| 942   n18->ReplaceInput(2, n5); |  | 
| 943   n18->ReplaceInput(3, n16); |  | 
| 944   n18->ReplaceInput(4, n14); |  | 
| 945   n8->ReplaceInput(1, n18); |  | 
| 946   n8->ReplaceInput(2, n6); |  | 
| 947   n19->ReplaceInput(0, n8); |  | 
| 948   n19->ReplaceInput(1, n12); |  | 
| 949   op = common_builder.IfFalse(); |  | 
| 950   Node* n15 = graph.NewNode(op, nil); |  | 
| 951   USE(n15); |  | 
| 952   n15->ReplaceInput(0, n13); |  | 
| 953   n19->ReplaceInput(2, n15); |  | 
| 954   n20->ReplaceInput(0, n19); |  | 
| 955 |  | 
| 956   graph.SetStart(n0); |  | 
| 957   graph.SetEnd(n20); |  | 
| 958 |  | 
| 959   ComputeAndVerifySchedule(19, &graph); |  | 
| 960 } |  | 
| 961 |  | 
| 962 |  | 
| 963 TEST(BuildScheduleComplexLoops) { |  | 
| 964   HandleAndZoneScope scope; |  | 
| 965   Isolate* isolate = scope.main_isolate(); |  | 
| 966   Graph graph(scope.main_zone()); |  | 
| 967   CommonOperatorBuilder common_builder(scope.main_zone()); |  | 
| 968   JSOperatorBuilder js_builder(scope.main_zone()); |  | 
| 969   const Operator* op; |  | 
| 970 |  | 
| 971   Handle<HeapObject> object = |  | 
| 972       Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); |  | 
| 973   Unique<HeapObject> unique_constant = |  | 
| 974       Unique<HeapObject>::CreateUninitialized(object); |  | 
| 975 |  | 
| 976   // Manually transcripted code for: |  | 
| 977   // function turbo_fan_test(a, b, c) { |  | 
| 978   //   while (a < b) { |  | 
| 979   //     a++; |  | 
| 980   //     while (c < b) { |  | 
| 981   //       c++; |  | 
| 982   //     } |  | 
| 983   //   } |  | 
| 984   //   while (a < b) { |  | 
| 985   //     a += 2; |  | 
| 986   //   } |  | 
| 987   //   return a; |  | 
| 988   // } |  | 
| 989   op = common_builder.Start(0); |  | 
| 990   Node* n0 = graph.NewNode(op); |  | 
| 991   USE(n0); |  | 
| 992   Node* nil = graph.NewNode(common_builder.Dead()); |  | 
| 993   op = common_builder.End(); |  | 
| 994   Node* n46 = graph.NewNode(op, nil); |  | 
| 995   USE(n46); |  | 
| 996   op = common_builder.Return(); |  | 
| 997   Node* n45 = graph.NewNode(op, nil, nil, nil); |  | 
| 998   USE(n45); |  | 
| 999   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1000   Node* n35 = graph.NewNode(op, nil, nil, nil); |  | 
| 1001   USE(n35); |  | 
| 1002   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1003   Node* n9 = graph.NewNode(op, nil, nil, nil); |  | 
| 1004   USE(n9); |  | 
| 1005   op = common_builder.Parameter(0); |  | 
| 1006   Node* n2 = graph.NewNode(op, n0); |  | 
| 1007   USE(n2); |  | 
| 1008   n9->ReplaceInput(0, n2); |  | 
| 1009   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1010   Node* n23 = graph.NewNode(op, nil, nil, nil); |  | 
| 1011   USE(n23); |  | 
| 1012   op = js_builder.Add(); |  | 
| 1013   Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1014   USE(n20); |  | 
| 1015   op = js_builder.ToNumber(); |  | 
| 1016   Node* n18 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 1017   USE(n18); |  | 
| 1018   n18->ReplaceInput(0, n9); |  | 
| 1019   op = common_builder.HeapConstant(unique_constant); |  | 
| 1020   Node* n6 = graph.NewNode(op); |  | 
| 1021   USE(n6); |  | 
| 1022   n18->ReplaceInput(1, n6); |  | 
| 1023   op = js_builder.LessThan(); |  | 
| 1024   Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1025   USE(n14); |  | 
| 1026   n14->ReplaceInput(0, n9); |  | 
| 1027   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1028   Node* n10 = graph.NewNode(op, nil, nil, nil); |  | 
| 1029   USE(n10); |  | 
| 1030   op = common_builder.Parameter(0); |  | 
| 1031   Node* n3 = graph.NewNode(op, n0); |  | 
| 1032   USE(n3); |  | 
| 1033   n10->ReplaceInput(0, n3); |  | 
| 1034   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1035   Node* n24 = graph.NewNode(op, nil, nil, nil); |  | 
| 1036   USE(n24); |  | 
| 1037   n24->ReplaceInput(0, n10); |  | 
| 1038   n24->ReplaceInput(1, n24); |  | 
| 1039   op = common_builder.Loop(2); |  | 
| 1040   Node* n21 = graph.NewNode(op, nil, nil); |  | 
| 1041   USE(n21); |  | 
| 1042   op = common_builder.IfTrue(); |  | 
| 1043   Node* n16 = graph.NewNode(op, nil); |  | 
| 1044   USE(n16); |  | 
| 1045   op = common_builder.Branch(); |  | 
| 1046   Node* n15 = graph.NewNode(op, nil, nil); |  | 
| 1047   USE(n15); |  | 
| 1048   n15->ReplaceInput(0, n14); |  | 
| 1049   op = common_builder.Loop(2); |  | 
| 1050   Node* n7 = graph.NewNode(op, nil, nil); |  | 
| 1051   USE(n7); |  | 
| 1052   n7->ReplaceInput(0, n0); |  | 
| 1053   op = common_builder.IfFalse(); |  | 
| 1054   Node* n30 = graph.NewNode(op, nil); |  | 
| 1055   USE(n30); |  | 
| 1056   op = common_builder.Branch(); |  | 
| 1057   Node* n28 = graph.NewNode(op, nil, nil); |  | 
| 1058   USE(n28); |  | 
| 1059   op = js_builder.LessThan(); |  | 
| 1060   Node* n27 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1061   USE(n27); |  | 
| 1062   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1063   Node* n25 = graph.NewNode(op, nil, nil, nil); |  | 
| 1064   USE(n25); |  | 
| 1065   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1066   Node* n11 = graph.NewNode(op, nil, nil, nil); |  | 
| 1067   USE(n11); |  | 
| 1068   op = common_builder.Parameter(0); |  | 
| 1069   Node* n4 = graph.NewNode(op, n0); |  | 
| 1070   USE(n4); |  | 
| 1071   n11->ReplaceInput(0, n4); |  | 
| 1072   n11->ReplaceInput(1, n25); |  | 
| 1073   n11->ReplaceInput(2, n7); |  | 
| 1074   n25->ReplaceInput(0, n11); |  | 
| 1075   op = js_builder.Add(); |  | 
| 1076   Node* n32 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1077   USE(n32); |  | 
| 1078   op = js_builder.ToNumber(); |  | 
| 1079   Node* n31 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 1080   USE(n31); |  | 
| 1081   n31->ReplaceInput(0, n25); |  | 
| 1082   n31->ReplaceInput(1, n6); |  | 
| 1083   n31->ReplaceInput(2, n27); |  | 
| 1084   op = common_builder.IfTrue(); |  | 
| 1085   Node* n29 = graph.NewNode(op, nil); |  | 
| 1086   USE(n29); |  | 
| 1087   n29->ReplaceInput(0, n28); |  | 
| 1088   n31->ReplaceInput(3, n29); |  | 
| 1089   n32->ReplaceInput(0, n31); |  | 
| 1090   op = common_builder.NumberConstant(0); |  | 
| 1091   Node* n19 = graph.NewNode(op); |  | 
| 1092   USE(n19); |  | 
| 1093   n32->ReplaceInput(1, n19); |  | 
| 1094   n32->ReplaceInput(2, n6); |  | 
| 1095   n32->ReplaceInput(3, n31); |  | 
| 1096   n32->ReplaceInput(4, n29); |  | 
| 1097   n25->ReplaceInput(1, n32); |  | 
| 1098   n25->ReplaceInput(2, n21); |  | 
| 1099   n27->ReplaceInput(0, n25); |  | 
| 1100   n27->ReplaceInput(1, n24); |  | 
| 1101   n27->ReplaceInput(2, n6); |  | 
| 1102   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1103   Node* n26 = graph.NewNode(op, nil, nil, nil); |  | 
| 1104   USE(n26); |  | 
| 1105   n26->ReplaceInput(0, n20); |  | 
| 1106   n26->ReplaceInput(1, n32); |  | 
| 1107   n26->ReplaceInput(2, n21); |  | 
| 1108   n27->ReplaceInput(3, n26); |  | 
| 1109   n27->ReplaceInput(4, n21); |  | 
| 1110   n28->ReplaceInput(0, n27); |  | 
| 1111   n28->ReplaceInput(1, n21); |  | 
| 1112   n30->ReplaceInput(0, n28); |  | 
| 1113   n7->ReplaceInput(1, n30); |  | 
| 1114   n15->ReplaceInput(1, n7); |  | 
| 1115   n16->ReplaceInput(0, n15); |  | 
| 1116   n21->ReplaceInput(0, n16); |  | 
| 1117   n21->ReplaceInput(1, n29); |  | 
| 1118   n24->ReplaceInput(2, n21); |  | 
| 1119   n10->ReplaceInput(1, n24); |  | 
| 1120   n10->ReplaceInput(2, n7); |  | 
| 1121   n14->ReplaceInput(1, n10); |  | 
| 1122   n14->ReplaceInput(2, n6); |  | 
| 1123   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1124   Node* n12 = graph.NewNode(op, nil, nil, nil); |  | 
| 1125   USE(n12); |  | 
| 1126   n12->ReplaceInput(0, n0); |  | 
| 1127   n12->ReplaceInput(1, n27); |  | 
| 1128   n12->ReplaceInput(2, n7); |  | 
| 1129   n14->ReplaceInput(3, n12); |  | 
| 1130   n14->ReplaceInput(4, n7); |  | 
| 1131   n18->ReplaceInput(2, n14); |  | 
| 1132   n18->ReplaceInput(3, n16); |  | 
| 1133   n20->ReplaceInput(0, n18); |  | 
| 1134   n20->ReplaceInput(1, n19); |  | 
| 1135   n20->ReplaceInput(2, n6); |  | 
| 1136   n20->ReplaceInput(3, n18); |  | 
| 1137   n20->ReplaceInput(4, n16); |  | 
| 1138   n23->ReplaceInput(0, n20); |  | 
| 1139   n23->ReplaceInput(1, n23); |  | 
| 1140   n23->ReplaceInput(2, n21); |  | 
| 1141   n9->ReplaceInput(1, n23); |  | 
| 1142   n9->ReplaceInput(2, n7); |  | 
| 1143   n35->ReplaceInput(0, n9); |  | 
| 1144   op = js_builder.Add(); |  | 
| 1145   Node* n44 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1146   USE(n44); |  | 
| 1147   n44->ReplaceInput(0, n35); |  | 
| 1148   op = common_builder.NumberConstant(0); |  | 
| 1149   Node* n43 = graph.NewNode(op); |  | 
| 1150   USE(n43); |  | 
| 1151   n44->ReplaceInput(1, n43); |  | 
| 1152   n44->ReplaceInput(2, n6); |  | 
| 1153   op = js_builder.LessThan(); |  | 
| 1154   Node* n39 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1155   USE(n39); |  | 
| 1156   n39->ReplaceInput(0, n35); |  | 
| 1157   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1158   Node* n36 = graph.NewNode(op, nil, nil, nil); |  | 
| 1159   USE(n36); |  | 
| 1160   n36->ReplaceInput(0, n10); |  | 
| 1161   n36->ReplaceInput(1, n36); |  | 
| 1162   op = common_builder.Loop(2); |  | 
| 1163   Node* n33 = graph.NewNode(op, nil, nil); |  | 
| 1164   USE(n33); |  | 
| 1165   op = common_builder.IfFalse(); |  | 
| 1166   Node* n17 = graph.NewNode(op, nil); |  | 
| 1167   USE(n17); |  | 
| 1168   n17->ReplaceInput(0, n15); |  | 
| 1169   n33->ReplaceInput(0, n17); |  | 
| 1170   op = common_builder.IfTrue(); |  | 
| 1171   Node* n41 = graph.NewNode(op, nil); |  | 
| 1172   USE(n41); |  | 
| 1173   op = common_builder.Branch(); |  | 
| 1174   Node* n40 = graph.NewNode(op, nil, nil); |  | 
| 1175   USE(n40); |  | 
| 1176   n40->ReplaceInput(0, n39); |  | 
| 1177   n40->ReplaceInput(1, n33); |  | 
| 1178   n41->ReplaceInput(0, n40); |  | 
| 1179   n33->ReplaceInput(1, n41); |  | 
| 1180   n36->ReplaceInput(2, n33); |  | 
| 1181   n39->ReplaceInput(1, n36); |  | 
| 1182   n39->ReplaceInput(2, n6); |  | 
| 1183   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1184   Node* n38 = graph.NewNode(op, nil, nil, nil); |  | 
| 1185   USE(n38); |  | 
| 1186   n38->ReplaceInput(0, n14); |  | 
| 1187   n38->ReplaceInput(1, n44); |  | 
| 1188   n38->ReplaceInput(2, n33); |  | 
| 1189   n39->ReplaceInput(3, n38); |  | 
| 1190   n39->ReplaceInput(4, n33); |  | 
| 1191   n44->ReplaceInput(3, n39); |  | 
| 1192   n44->ReplaceInput(4, n41); |  | 
| 1193   n35->ReplaceInput(1, n44); |  | 
| 1194   n35->ReplaceInput(2, n33); |  | 
| 1195   n45->ReplaceInput(0, n35); |  | 
| 1196   n45->ReplaceInput(1, n39); |  | 
| 1197   op = common_builder.IfFalse(); |  | 
| 1198   Node* n42 = graph.NewNode(op, nil); |  | 
| 1199   USE(n42); |  | 
| 1200   n42->ReplaceInput(0, n40); |  | 
| 1201   n45->ReplaceInput(2, n42); |  | 
| 1202   n46->ReplaceInput(0, n45); |  | 
| 1203 |  | 
| 1204   graph.SetStart(n0); |  | 
| 1205   graph.SetEnd(n46); |  | 
| 1206 |  | 
| 1207   ComputeAndVerifySchedule(46, &graph); |  | 
| 1208 } |  | 
| 1209 |  | 
| 1210 |  | 
| 1211 TEST(BuildScheduleBreakAndContinue) { |  | 
| 1212   HandleAndZoneScope scope; |  | 
| 1213   Isolate* isolate = scope.main_isolate(); |  | 
| 1214   Graph graph(scope.main_zone()); |  | 
| 1215   CommonOperatorBuilder common_builder(scope.main_zone()); |  | 
| 1216   JSOperatorBuilder js_builder(scope.main_zone()); |  | 
| 1217   const Operator* op; |  | 
| 1218 |  | 
| 1219   Handle<HeapObject> object = |  | 
| 1220       Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); |  | 
| 1221   Unique<HeapObject> unique_constant = |  | 
| 1222       Unique<HeapObject>::CreateUninitialized(object); |  | 
| 1223 |  | 
| 1224   // Manually transcripted code for: |  | 
| 1225   // function turbo_fan_test(a, b, c) { |  | 
| 1226   //   var d = 0; |  | 
| 1227   //   while (a < b) { |  | 
| 1228   //     a++; |  | 
| 1229   //     while (c < b) { |  | 
| 1230   //       c++; |  | 
| 1231   //       if (d == 0) break; |  | 
| 1232   //       a++; |  | 
| 1233   //     } |  | 
| 1234   //     if (a == 1) continue; |  | 
| 1235   //     d++; |  | 
| 1236   //   } |  | 
| 1237   //   return a + d; |  | 
| 1238   // } |  | 
| 1239   op = common_builder.Start(0); |  | 
| 1240   Node* n0 = graph.NewNode(op); |  | 
| 1241   USE(n0); |  | 
| 1242   Node* nil = graph.NewNode(common_builder.Dead()); |  | 
| 1243   op = common_builder.End(); |  | 
| 1244   Node* n58 = graph.NewNode(op, nil); |  | 
| 1245   USE(n58); |  | 
| 1246   op = common_builder.Return(); |  | 
| 1247   Node* n57 = graph.NewNode(op, nil, nil, nil); |  | 
| 1248   USE(n57); |  | 
| 1249   op = js_builder.Add(); |  | 
| 1250   Node* n56 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1251   USE(n56); |  | 
| 1252   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1253   Node* n10 = graph.NewNode(op, nil, nil, nil); |  | 
| 1254   USE(n10); |  | 
| 1255   op = common_builder.Parameter(0); |  | 
| 1256   Node* n2 = graph.NewNode(op, n0); |  | 
| 1257   USE(n2); |  | 
| 1258   n10->ReplaceInput(0, n2); |  | 
| 1259   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1260   Node* n25 = graph.NewNode(op, nil, nil, nil); |  | 
| 1261   USE(n25); |  | 
| 1262   op = js_builder.Add(); |  | 
| 1263   Node* n22 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1264   USE(n22); |  | 
| 1265   op = js_builder.ToNumber(); |  | 
| 1266   Node* n20 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 1267   USE(n20); |  | 
| 1268   n20->ReplaceInput(0, n10); |  | 
| 1269   op = common_builder.HeapConstant(unique_constant); |  | 
| 1270   Node* n6 = graph.NewNode(op); |  | 
| 1271   USE(n6); |  | 
| 1272   n20->ReplaceInput(1, n6); |  | 
| 1273   op = js_builder.LessThan(); |  | 
| 1274   Node* n16 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1275   USE(n16); |  | 
| 1276   n16->ReplaceInput(0, n10); |  | 
| 1277   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1278   Node* n11 = graph.NewNode(op, nil, nil, nil); |  | 
| 1279   USE(n11); |  | 
| 1280   op = common_builder.Parameter(0); |  | 
| 1281   Node* n3 = graph.NewNode(op, n0); |  | 
| 1282   USE(n3); |  | 
| 1283   n11->ReplaceInput(0, n3); |  | 
| 1284   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1285   Node* n26 = graph.NewNode(op, nil, nil, nil); |  | 
| 1286   USE(n26); |  | 
| 1287   n26->ReplaceInput(0, n11); |  | 
| 1288   n26->ReplaceInput(1, n26); |  | 
| 1289   op = common_builder.Loop(2); |  | 
| 1290   Node* n23 = graph.NewNode(op, nil, nil); |  | 
| 1291   USE(n23); |  | 
| 1292   op = common_builder.IfTrue(); |  | 
| 1293   Node* n18 = graph.NewNode(op, nil); |  | 
| 1294   USE(n18); |  | 
| 1295   op = common_builder.Branch(); |  | 
| 1296   Node* n17 = graph.NewNode(op, nil, nil); |  | 
| 1297   USE(n17); |  | 
| 1298   n17->ReplaceInput(0, n16); |  | 
| 1299   op = common_builder.Loop(2); |  | 
| 1300   Node* n8 = graph.NewNode(op, nil, nil); |  | 
| 1301   USE(n8); |  | 
| 1302   n8->ReplaceInput(0, n0); |  | 
| 1303   op = common_builder.Merge(2); |  | 
| 1304   Node* n53 = graph.NewNode(op, nil, nil); |  | 
| 1305   USE(n53); |  | 
| 1306   op = common_builder.IfTrue(); |  | 
| 1307   Node* n49 = graph.NewNode(op, nil); |  | 
| 1308   USE(n49); |  | 
| 1309   op = common_builder.Branch(); |  | 
| 1310   Node* n48 = graph.NewNode(op, nil, nil); |  | 
| 1311   USE(n48); |  | 
| 1312   op = js_builder.Equal(); |  | 
| 1313   Node* n47 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1314   USE(n47); |  | 
| 1315   n47->ReplaceInput(0, n25); |  | 
| 1316   op = common_builder.NumberConstant(0); |  | 
| 1317   Node* n46 = graph.NewNode(op); |  | 
| 1318   USE(n46); |  | 
| 1319   n47->ReplaceInput(1, n46); |  | 
| 1320   n47->ReplaceInput(2, n6); |  | 
| 1321   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1322   Node* n42 = graph.NewNode(op, nil, nil, nil); |  | 
| 1323   USE(n42); |  | 
| 1324   op = js_builder.LessThan(); |  | 
| 1325   Node* n30 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1326   USE(n30); |  | 
| 1327   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1328   Node* n27 = graph.NewNode(op, nil, nil, nil); |  | 
| 1329   USE(n27); |  | 
| 1330   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1331   Node* n12 = graph.NewNode(op, nil, nil, nil); |  | 
| 1332   USE(n12); |  | 
| 1333   op = common_builder.Parameter(0); |  | 
| 1334   Node* n4 = graph.NewNode(op, n0); |  | 
| 1335   USE(n4); |  | 
| 1336   n12->ReplaceInput(0, n4); |  | 
| 1337   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1338   Node* n41 = graph.NewNode(op, nil, nil, nil); |  | 
| 1339   USE(n41); |  | 
| 1340   n41->ReplaceInput(0, n27); |  | 
| 1341   op = js_builder.Add(); |  | 
| 1342   Node* n35 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1343   USE(n35); |  | 
| 1344   op = js_builder.ToNumber(); |  | 
| 1345   Node* n34 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 1346   USE(n34); |  | 
| 1347   n34->ReplaceInput(0, n27); |  | 
| 1348   n34->ReplaceInput(1, n6); |  | 
| 1349   n34->ReplaceInput(2, n30); |  | 
| 1350   op = common_builder.IfTrue(); |  | 
| 1351   Node* n32 = graph.NewNode(op, nil); |  | 
| 1352   USE(n32); |  | 
| 1353   op = common_builder.Branch(); |  | 
| 1354   Node* n31 = graph.NewNode(op, nil, nil); |  | 
| 1355   USE(n31); |  | 
| 1356   n31->ReplaceInput(0, n30); |  | 
| 1357   n31->ReplaceInput(1, n23); |  | 
| 1358   n32->ReplaceInput(0, n31); |  | 
| 1359   n34->ReplaceInput(3, n32); |  | 
| 1360   n35->ReplaceInput(0, n34); |  | 
| 1361   op = common_builder.NumberConstant(0); |  | 
| 1362   Node* n21 = graph.NewNode(op); |  | 
| 1363   USE(n21); |  | 
| 1364   n35->ReplaceInput(1, n21); |  | 
| 1365   n35->ReplaceInput(2, n6); |  | 
| 1366   n35->ReplaceInput(3, n34); |  | 
| 1367   n35->ReplaceInput(4, n32); |  | 
| 1368   n41->ReplaceInput(1, n35); |  | 
| 1369   op = common_builder.Merge(2); |  | 
| 1370   Node* n40 = graph.NewNode(op, nil, nil); |  | 
| 1371   USE(n40); |  | 
| 1372   op = common_builder.IfFalse(); |  | 
| 1373   Node* n33 = graph.NewNode(op, nil); |  | 
| 1374   USE(n33); |  | 
| 1375   n33->ReplaceInput(0, n31); |  | 
| 1376   n40->ReplaceInput(0, n33); |  | 
| 1377   op = common_builder.IfTrue(); |  | 
| 1378   Node* n39 = graph.NewNode(op, nil); |  | 
| 1379   USE(n39); |  | 
| 1380   op = common_builder.Branch(); |  | 
| 1381   Node* n38 = graph.NewNode(op, nil, nil); |  | 
| 1382   USE(n38); |  | 
| 1383   op = js_builder.Equal(); |  | 
| 1384   Node* n37 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1385   USE(n37); |  | 
| 1386   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1387   Node* n28 = graph.NewNode(op, nil, nil, nil); |  | 
| 1388   USE(n28); |  | 
| 1389   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1390   Node* n13 = graph.NewNode(op, nil, nil, nil); |  | 
| 1391   USE(n13); |  | 
| 1392   op = common_builder.NumberConstant(0); |  | 
| 1393   Node* n7 = graph.NewNode(op); |  | 
| 1394   USE(n7); |  | 
| 1395   n13->ReplaceInput(0, n7); |  | 
| 1396   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1397   Node* n54 = graph.NewNode(op, nil, nil, nil); |  | 
| 1398   USE(n54); |  | 
| 1399   n54->ReplaceInput(0, n28); |  | 
| 1400   op = js_builder.Add(); |  | 
| 1401   Node* n52 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1402   USE(n52); |  | 
| 1403   op = js_builder.ToNumber(); |  | 
| 1404   Node* n51 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 1405   USE(n51); |  | 
| 1406   n51->ReplaceInput(0, n28); |  | 
| 1407   n51->ReplaceInput(1, n6); |  | 
| 1408   n51->ReplaceInput(2, n47); |  | 
| 1409   op = common_builder.IfFalse(); |  | 
| 1410   Node* n50 = graph.NewNode(op, nil); |  | 
| 1411   USE(n50); |  | 
| 1412   n50->ReplaceInput(0, n48); |  | 
| 1413   n51->ReplaceInput(3, n50); |  | 
| 1414   n52->ReplaceInput(0, n51); |  | 
| 1415   n52->ReplaceInput(1, n21); |  | 
| 1416   n52->ReplaceInput(2, n6); |  | 
| 1417   n52->ReplaceInput(3, n51); |  | 
| 1418   n52->ReplaceInput(4, n50); |  | 
| 1419   n54->ReplaceInput(1, n52); |  | 
| 1420   n54->ReplaceInput(2, n53); |  | 
| 1421   n13->ReplaceInput(1, n54); |  | 
| 1422   n13->ReplaceInput(2, n8); |  | 
| 1423   n28->ReplaceInput(0, n13); |  | 
| 1424   n28->ReplaceInput(1, n28); |  | 
| 1425   n28->ReplaceInput(2, n23); |  | 
| 1426   n37->ReplaceInput(0, n28); |  | 
| 1427   op = common_builder.NumberConstant(0); |  | 
| 1428   Node* n36 = graph.NewNode(op); |  | 
| 1429   USE(n36); |  | 
| 1430   n37->ReplaceInput(1, n36); |  | 
| 1431   n37->ReplaceInput(2, n6); |  | 
| 1432   n37->ReplaceInput(3, n35); |  | 
| 1433   n37->ReplaceInput(4, n32); |  | 
| 1434   n38->ReplaceInput(0, n37); |  | 
| 1435   n38->ReplaceInput(1, n32); |  | 
| 1436   n39->ReplaceInput(0, n38); |  | 
| 1437   n40->ReplaceInput(1, n39); |  | 
| 1438   n41->ReplaceInput(2, n40); |  | 
| 1439   n12->ReplaceInput(1, n41); |  | 
| 1440   n12->ReplaceInput(2, n8); |  | 
| 1441   n27->ReplaceInput(0, n12); |  | 
| 1442   n27->ReplaceInput(1, n35); |  | 
| 1443   n27->ReplaceInput(2, n23); |  | 
| 1444   n30->ReplaceInput(0, n27); |  | 
| 1445   n30->ReplaceInput(1, n26); |  | 
| 1446   n30->ReplaceInput(2, n6); |  | 
| 1447   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1448   Node* n29 = graph.NewNode(op, nil, nil, nil); |  | 
| 1449   USE(n29); |  | 
| 1450   n29->ReplaceInput(0, n22); |  | 
| 1451   op = js_builder.Add(); |  | 
| 1452   Node* n45 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1453   USE(n45); |  | 
| 1454   op = js_builder.ToNumber(); |  | 
| 1455   Node* n44 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 1456   USE(n44); |  | 
| 1457   n44->ReplaceInput(0, n25); |  | 
| 1458   n44->ReplaceInput(1, n6); |  | 
| 1459   n44->ReplaceInput(2, n37); |  | 
| 1460   op = common_builder.IfFalse(); |  | 
| 1461   Node* n43 = graph.NewNode(op, nil); |  | 
| 1462   USE(n43); |  | 
| 1463   n43->ReplaceInput(0, n38); |  | 
| 1464   n44->ReplaceInput(3, n43); |  | 
| 1465   n45->ReplaceInput(0, n44); |  | 
| 1466   n45->ReplaceInput(1, n21); |  | 
| 1467   n45->ReplaceInput(2, n6); |  | 
| 1468   n45->ReplaceInput(3, n44); |  | 
| 1469   n45->ReplaceInput(4, n43); |  | 
| 1470   n29->ReplaceInput(1, n45); |  | 
| 1471   n29->ReplaceInput(2, n23); |  | 
| 1472   n30->ReplaceInput(3, n29); |  | 
| 1473   n30->ReplaceInput(4, n23); |  | 
| 1474   n42->ReplaceInput(0, n30); |  | 
| 1475   n42->ReplaceInput(1, n37); |  | 
| 1476   n42->ReplaceInput(2, n40); |  | 
| 1477   n47->ReplaceInput(3, n42); |  | 
| 1478   n47->ReplaceInput(4, n40); |  | 
| 1479   n48->ReplaceInput(0, n47); |  | 
| 1480   n48->ReplaceInput(1, n40); |  | 
| 1481   n49->ReplaceInput(0, n48); |  | 
| 1482   n53->ReplaceInput(0, n49); |  | 
| 1483   n53->ReplaceInput(1, n50); |  | 
| 1484   n8->ReplaceInput(1, n53); |  | 
| 1485   n17->ReplaceInput(1, n8); |  | 
| 1486   n18->ReplaceInput(0, n17); |  | 
| 1487   n23->ReplaceInput(0, n18); |  | 
| 1488   n23->ReplaceInput(1, n43); |  | 
| 1489   n26->ReplaceInput(2, n23); |  | 
| 1490   n11->ReplaceInput(1, n26); |  | 
| 1491   n11->ReplaceInput(2, n8); |  | 
| 1492   n16->ReplaceInput(1, n11); |  | 
| 1493   n16->ReplaceInput(2, n6); |  | 
| 1494   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1495   Node* n14 = graph.NewNode(op, nil, nil, nil); |  | 
| 1496   USE(n14); |  | 
| 1497   n14->ReplaceInput(0, n0); |  | 
| 1498   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1499   Node* n55 = graph.NewNode(op, nil, nil, nil); |  | 
| 1500   USE(n55); |  | 
| 1501   n55->ReplaceInput(0, n47); |  | 
| 1502   n55->ReplaceInput(1, n52); |  | 
| 1503   n55->ReplaceInput(2, n53); |  | 
| 1504   n14->ReplaceInput(1, n55); |  | 
| 1505   n14->ReplaceInput(2, n8); |  | 
| 1506   n16->ReplaceInput(3, n14); |  | 
| 1507   n16->ReplaceInput(4, n8); |  | 
| 1508   n20->ReplaceInput(2, n16); |  | 
| 1509   n20->ReplaceInput(3, n18); |  | 
| 1510   n22->ReplaceInput(0, n20); |  | 
| 1511   n22->ReplaceInput(1, n21); |  | 
| 1512   n22->ReplaceInput(2, n6); |  | 
| 1513   n22->ReplaceInput(3, n20); |  | 
| 1514   n22->ReplaceInput(4, n18); |  | 
| 1515   n25->ReplaceInput(0, n22); |  | 
| 1516   n25->ReplaceInput(1, n45); |  | 
| 1517   n25->ReplaceInput(2, n23); |  | 
| 1518   n10->ReplaceInput(1, n25); |  | 
| 1519   n10->ReplaceInput(2, n8); |  | 
| 1520   n56->ReplaceInput(0, n10); |  | 
| 1521   n56->ReplaceInput(1, n13); |  | 
| 1522   n56->ReplaceInput(2, n6); |  | 
| 1523   n56->ReplaceInput(3, n16); |  | 
| 1524   op = common_builder.IfFalse(); |  | 
| 1525   Node* n19 = graph.NewNode(op, nil); |  | 
| 1526   USE(n19); |  | 
| 1527   n19->ReplaceInput(0, n17); |  | 
| 1528   n56->ReplaceInput(4, n19); |  | 
| 1529   n57->ReplaceInput(0, n56); |  | 
| 1530   n57->ReplaceInput(1, n56); |  | 
| 1531   n57->ReplaceInput(2, n19); |  | 
| 1532   n58->ReplaceInput(0, n57); |  | 
| 1533 |  | 
| 1534   graph.SetStart(n0); |  | 
| 1535   graph.SetEnd(n58); |  | 
| 1536 |  | 
| 1537   ComputeAndVerifySchedule(62, &graph); |  | 
| 1538 } |  | 
| 1539 |  | 
| 1540 |  | 
| 1541 TEST(BuildScheduleSimpleLoopWithCodeMotion) { |  | 
| 1542   HandleAndZoneScope scope; |  | 
| 1543   Isolate* isolate = scope.main_isolate(); |  | 
| 1544   Graph graph(scope.main_zone()); |  | 
| 1545   CommonOperatorBuilder common_builder(scope.main_zone()); |  | 
| 1546   JSOperatorBuilder js_builder(scope.main_zone()); |  | 
| 1547   const Operator* op; |  | 
| 1548 |  | 
| 1549   Handle<HeapObject> object = |  | 
| 1550       Handle<HeapObject>(isolate->heap()->undefined_value(), isolate); |  | 
| 1551   Unique<HeapObject> unique_constant = |  | 
| 1552       Unique<HeapObject>::CreateUninitialized(object); |  | 
| 1553 |  | 
| 1554   // Manually transcripted code for: |  | 
| 1555   // function turbo_fan_test(a, b, c) { |  | 
| 1556   //   while (a < b) { |  | 
| 1557   //     a += b + c; |  | 
| 1558   //   } |  | 
| 1559   //   return a; |  | 
| 1560   // } |  | 
| 1561   op = common_builder.Start(0); |  | 
| 1562   Node* n0 = graph.NewNode(op); |  | 
| 1563   USE(n0); |  | 
| 1564   Node* nil = graph.NewNode(common_builder.Dead()); |  | 
| 1565   op = common_builder.End(); |  | 
| 1566   Node* n22 = graph.NewNode(op, nil); |  | 
| 1567   USE(n22); |  | 
| 1568   op = common_builder.Return(); |  | 
| 1569   Node* n21 = graph.NewNode(op, nil, nil, nil); |  | 
| 1570   USE(n21); |  | 
| 1571   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1572   Node* n9 = graph.NewNode(op, nil, nil, nil); |  | 
| 1573   USE(n9); |  | 
| 1574   op = common_builder.Parameter(0); |  | 
| 1575   Node* n2 = graph.NewNode(op, n0); |  | 
| 1576   USE(n2); |  | 
| 1577   n9->ReplaceInput(0, n2); |  | 
| 1578   op = js_builder.Add(); |  | 
| 1579   Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1580   USE(n20); |  | 
| 1581   n20->ReplaceInput(0, n9); |  | 
| 1582   op = &kIntAdd; |  | 
| 1583   Node* n19 = graph.NewNode(op, nil, nil); |  | 
| 1584   USE(n19); |  | 
| 1585   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1586   Node* n10 = graph.NewNode(op, nil, nil, nil); |  | 
| 1587   USE(n10); |  | 
| 1588   op = common_builder.Parameter(0); |  | 
| 1589   Node* n3 = graph.NewNode(op, n0); |  | 
| 1590   USE(n3); |  | 
| 1591   n10->ReplaceInput(0, n3); |  | 
| 1592   n10->ReplaceInput(1, n10); |  | 
| 1593   op = common_builder.Loop(2); |  | 
| 1594   Node* n7 = graph.NewNode(op, nil, nil); |  | 
| 1595   USE(n7); |  | 
| 1596   n7->ReplaceInput(0, n0); |  | 
| 1597   op = common_builder.IfTrue(); |  | 
| 1598   Node* n17 = graph.NewNode(op, nil); |  | 
| 1599   USE(n17); |  | 
| 1600   op = common_builder.Branch(); |  | 
| 1601   Node* n16 = graph.NewNode(op, nil, nil); |  | 
| 1602   USE(n16); |  | 
| 1603   op = js_builder.ToBoolean(); |  | 
| 1604   Node* n15 = graph.NewNode(op, nil, nil, nil, nil); |  | 
| 1605   USE(n15); |  | 
| 1606   op = js_builder.LessThan(); |  | 
| 1607   Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil); |  | 
| 1608   USE(n14); |  | 
| 1609   n14->ReplaceInput(0, n9); |  | 
| 1610   n14->ReplaceInput(1, n10); |  | 
| 1611   op = common_builder.HeapConstant(unique_constant); |  | 
| 1612   Node* n6 = graph.NewNode(op); |  | 
| 1613   USE(n6); |  | 
| 1614   n14->ReplaceInput(2, n6); |  | 
| 1615   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1616   Node* n12 = graph.NewNode(op, nil, nil, nil); |  | 
| 1617   USE(n12); |  | 
| 1618   n12->ReplaceInput(0, n0); |  | 
| 1619   n12->ReplaceInput(1, n20); |  | 
| 1620   n12->ReplaceInput(2, n7); |  | 
| 1621   n14->ReplaceInput(3, n12); |  | 
| 1622   n14->ReplaceInput(4, n7); |  | 
| 1623   n15->ReplaceInput(0, n14); |  | 
| 1624   n15->ReplaceInput(1, n6); |  | 
| 1625   n15->ReplaceInput(2, n14); |  | 
| 1626   n15->ReplaceInput(3, n7); |  | 
| 1627   n16->ReplaceInput(0, n15); |  | 
| 1628   n16->ReplaceInput(1, n7); |  | 
| 1629   n17->ReplaceInput(0, n16); |  | 
| 1630   n7->ReplaceInput(1, n17); |  | 
| 1631   n10->ReplaceInput(2, n7); |  | 
| 1632   n19->ReplaceInput(0, n2); |  | 
| 1633   op = common_builder.Phi(kMachAnyTagged, 2); |  | 
| 1634   Node* n11 = graph.NewNode(op, nil, nil, nil); |  | 
| 1635   USE(n11); |  | 
| 1636   op = common_builder.Parameter(0); |  | 
| 1637   Node* n4 = graph.NewNode(op, n0); |  | 
| 1638   USE(n4); |  | 
| 1639   n11->ReplaceInput(0, n4); |  | 
| 1640   n11->ReplaceInput(1, n11); |  | 
| 1641   n11->ReplaceInput(2, n7); |  | 
| 1642   n19->ReplaceInput(1, n3); |  | 
| 1643   n20->ReplaceInput(1, n19); |  | 
| 1644   n20->ReplaceInput(2, n6); |  | 
| 1645   n20->ReplaceInput(3, n19); |  | 
| 1646   n20->ReplaceInput(4, n17); |  | 
| 1647   n9->ReplaceInput(1, n20); |  | 
| 1648   n9->ReplaceInput(2, n7); |  | 
| 1649   n21->ReplaceInput(0, n9); |  | 
| 1650   n21->ReplaceInput(1, n15); |  | 
| 1651   op = common_builder.IfFalse(); |  | 
| 1652   Node* n18 = graph.NewNode(op, nil); |  | 
| 1653   USE(n18); |  | 
| 1654   n18->ReplaceInput(0, n16); |  | 
| 1655   n21->ReplaceInput(2, n18); |  | 
| 1656   n22->ReplaceInput(0, n21); |  | 
| 1657 |  | 
| 1658   graph.SetStart(n0); |  | 
| 1659   graph.SetEnd(n22); |  | 
| 1660 |  | 
| 1661   Schedule* schedule = ComputeAndVerifySchedule(19, &graph); |  | 
| 1662   // Make sure the integer-only add gets hoisted to a different block that the |  | 
| 1663   // JSAdd. |  | 
| 1664   CHECK(schedule->block(n19) != schedule->block(n20)); |  | 
| 1665 } |  | 
| 1666 |  | 
| 1667 |  | 
| 1668 #if V8_TURBOFAN_TARGET |  | 
| 1669 |  | 
| 1670 static Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, |  | 
| 1671                            Node* cond) { |  | 
| 1672   Node* tv = graph->NewNode(common->Int32Constant(6)); |  | 
| 1673   Node* fv = graph->NewNode(common->Int32Constant(7)); |  | 
| 1674   Node* br = graph->NewNode(common->Branch(), cond, graph->start()); |  | 
| 1675   Node* t = graph->NewNode(common->IfTrue(), br); |  | 
| 1676   Node* f = graph->NewNode(common->IfFalse(), br); |  | 
| 1677   Node* m = graph->NewNode(common->Merge(2), t, f); |  | 
| 1678   Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2), tv, fv, m); |  | 
| 1679   return phi; |  | 
| 1680 } |  | 
| 1681 |  | 
| 1682 |  | 
| 1683 TEST(FloatingDiamond1) { |  | 
| 1684   HandleAndZoneScope scope; |  | 
| 1685   Graph graph(scope.main_zone()); |  | 
| 1686   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1687 |  | 
| 1688   Node* start = graph.NewNode(common.Start(1)); |  | 
| 1689   graph.SetStart(start); |  | 
| 1690 |  | 
| 1691   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1692   Node* d1 = CreateDiamond(&graph, &common, p0); |  | 
| 1693   Node* ret = graph.NewNode(common.Return(), d1, start, start); |  | 
| 1694   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 1695 |  | 
| 1696   graph.SetEnd(end); |  | 
| 1697 |  | 
| 1698   ComputeAndVerifySchedule(13, &graph); |  | 
| 1699 } |  | 
| 1700 |  | 
| 1701 |  | 
| 1702 TEST(FloatingDiamond2) { |  | 
| 1703   HandleAndZoneScope scope; |  | 
| 1704   Graph graph(scope.main_zone()); |  | 
| 1705   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1706 |  | 
| 1707   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1708   graph.SetStart(start); |  | 
| 1709 |  | 
| 1710   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1711   Node* p1 = graph.NewNode(common.Parameter(1), start); |  | 
| 1712   Node* d1 = CreateDiamond(&graph, &common, p0); |  | 
| 1713   Node* d2 = CreateDiamond(&graph, &common, p1); |  | 
| 1714   Node* add = graph.NewNode(&kIntAdd, d1, d2); |  | 
| 1715   Node* ret = graph.NewNode(common.Return(), add, start, start); |  | 
| 1716   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 1717 |  | 
| 1718   graph.SetEnd(end); |  | 
| 1719 |  | 
| 1720   ComputeAndVerifySchedule(24, &graph); |  | 
| 1721 } |  | 
| 1722 |  | 
| 1723 |  | 
| 1724 TEST(FloatingDiamond3) { |  | 
| 1725   HandleAndZoneScope scope; |  | 
| 1726   Graph graph(scope.main_zone()); |  | 
| 1727   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1728 |  | 
| 1729   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1730   graph.SetStart(start); |  | 
| 1731 |  | 
| 1732   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1733   Node* p1 = graph.NewNode(common.Parameter(1), start); |  | 
| 1734   Node* d1 = CreateDiamond(&graph, &common, p0); |  | 
| 1735   Node* d2 = CreateDiamond(&graph, &common, p1); |  | 
| 1736   Node* add = graph.NewNode(&kIntAdd, d1, d2); |  | 
| 1737   Node* d3 = CreateDiamond(&graph, &common, add); |  | 
| 1738   Node* ret = graph.NewNode(common.Return(), d3, start, start); |  | 
| 1739   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 1740 |  | 
| 1741   graph.SetEnd(end); |  | 
| 1742 |  | 
| 1743   ComputeAndVerifySchedule(33, &graph); |  | 
| 1744 } |  | 
| 1745 |  | 
| 1746 |  | 
| 1747 TEST(NestedFloatingDiamonds) { |  | 
| 1748   HandleAndZoneScope scope; |  | 
| 1749   Graph graph(scope.main_zone()); |  | 
| 1750   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1751   SimplifiedOperatorBuilder simplified(scope.main_zone()); |  | 
| 1752 |  | 
| 1753   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1754   graph.SetStart(start); |  | 
| 1755 |  | 
| 1756   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1757 |  | 
| 1758   Node* fv = graph.NewNode(common.Int32Constant(7)); |  | 
| 1759   Node* br = graph.NewNode(common.Branch(), p0, graph.start()); |  | 
| 1760   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 1761   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 1762 |  | 
| 1763   Node* map = graph.NewNode( |  | 
| 1764       simplified.LoadElement(AccessBuilder::ForFixedArrayElement()), p0, p0, p0, |  | 
| 1765       start, f); |  | 
| 1766   Node* br1 = graph.NewNode(common.Branch(), map, graph.start()); |  | 
| 1767   Node* t1 = graph.NewNode(common.IfTrue(), br1); |  | 
| 1768   Node* f1 = graph.NewNode(common.IfFalse(), br1); |  | 
| 1769   Node* m1 = graph.NewNode(common.Merge(2), t1, f1); |  | 
| 1770   Node* ttrue = graph.NewNode(common.Int32Constant(1)); |  | 
| 1771   Node* ffalse = graph.NewNode(common.Int32Constant(0)); |  | 
| 1772   Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), ttrue, ffalse, m1); |  | 
| 1773 |  | 
| 1774 |  | 
| 1775   Node* m = graph.NewNode(common.Merge(2), t, f); |  | 
| 1776   Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), fv, phi1, m); |  | 
| 1777   Node* ephi1 = graph.NewNode(common.EffectPhi(2), start, map, m); |  | 
| 1778 |  | 
| 1779   Node* ret = graph.NewNode(common.Return(), phi, ephi1, start); |  | 
| 1780   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 1781 |  | 
| 1782   graph.SetEnd(end); |  | 
| 1783 |  | 
| 1784   ComputeAndVerifySchedule(23, &graph); |  | 
| 1785 } |  | 
| 1786 |  | 
| 1787 |  | 
| 1788 TEST(NestedFloatingDiamondWithChain) { |  | 
| 1789   HandleAndZoneScope scope; |  | 
| 1790   Graph graph(scope.main_zone()); |  | 
| 1791   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1792 |  | 
| 1793   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1794   graph.SetStart(start); |  | 
| 1795 |  | 
| 1796   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1797   Node* p1 = graph.NewNode(common.Parameter(1), start); |  | 
| 1798   Node* c = graph.NewNode(common.Int32Constant(7)); |  | 
| 1799 |  | 
| 1800   Node* brA1 = graph.NewNode(common.Branch(), p0, graph.start()); |  | 
| 1801   Node* tA1 = graph.NewNode(common.IfTrue(), brA1); |  | 
| 1802   Node* fA1 = graph.NewNode(common.IfFalse(), brA1); |  | 
| 1803   Node* mA1 = graph.NewNode(common.Merge(2), tA1, fA1); |  | 
| 1804   Node* phiA1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p1, mA1); |  | 
| 1805 |  | 
| 1806   Node* brB1 = graph.NewNode(common.Branch(), p1, graph.start()); |  | 
| 1807   Node* tB1 = graph.NewNode(common.IfTrue(), brB1); |  | 
| 1808   Node* fB1 = graph.NewNode(common.IfFalse(), brB1); |  | 
| 1809   Node* mB1 = graph.NewNode(common.Merge(2), tB1, fB1); |  | 
| 1810   Node* phiB1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p1, mB1); |  | 
| 1811 |  | 
| 1812   Node* brA2 = graph.NewNode(common.Branch(), phiB1, mA1); |  | 
| 1813   Node* tA2 = graph.NewNode(common.IfTrue(), brA2); |  | 
| 1814   Node* fA2 = graph.NewNode(common.IfFalse(), brA2); |  | 
| 1815   Node* mA2 = graph.NewNode(common.Merge(2), tA2, fA2); |  | 
| 1816   Node* phiA2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phiB1, c, mA2); |  | 
| 1817 |  | 
| 1818   Node* brB2 = graph.NewNode(common.Branch(), phiA1, mB1); |  | 
| 1819   Node* tB2 = graph.NewNode(common.IfTrue(), brB2); |  | 
| 1820   Node* fB2 = graph.NewNode(common.IfFalse(), brB2); |  | 
| 1821   Node* mB2 = graph.NewNode(common.Merge(2), tB2, fB2); |  | 
| 1822   Node* phiB2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phiA1, c, mB2); |  | 
| 1823 |  | 
| 1824   Node* add = graph.NewNode(&kIntAdd, phiA2, phiB2); |  | 
| 1825   Node* ret = graph.NewNode(common.Return(), add, start, start); |  | 
| 1826   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 1827 |  | 
| 1828   graph.SetEnd(end); |  | 
| 1829 |  | 
| 1830   ComputeAndVerifySchedule(35, &graph); |  | 
| 1831 } |  | 
| 1832 |  | 
| 1833 |  | 
| 1834 TEST(NestedFloatingDiamondWithLoop) { |  | 
| 1835   HandleAndZoneScope scope; |  | 
| 1836   Graph graph(scope.main_zone()); |  | 
| 1837   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1838 |  | 
| 1839   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1840   graph.SetStart(start); |  | 
| 1841 |  | 
| 1842   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1843 |  | 
| 1844   Node* fv = graph.NewNode(common.Int32Constant(7)); |  | 
| 1845   Node* br = graph.NewNode(common.Branch(), p0, graph.start()); |  | 
| 1846   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 1847   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 1848 |  | 
| 1849   Node* loop = graph.NewNode(common.Loop(2), f, start); |  | 
| 1850   Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); |  | 
| 1851 |  | 
| 1852   Node* add = graph.NewNode(&kIntAdd, ind, fv); |  | 
| 1853   Node* br1 = graph.NewNode(common.Branch(), add, loop); |  | 
| 1854   Node* t1 = graph.NewNode(common.IfTrue(), br1); |  | 
| 1855   Node* f1 = graph.NewNode(common.IfFalse(), br1); |  | 
| 1856 |  | 
| 1857   loop->ReplaceInput(1, t1);  // close loop. |  | 
| 1858   ind->ReplaceInput(1, ind);  // close induction variable. |  | 
| 1859 |  | 
| 1860   Node* m = graph.NewNode(common.Merge(2), t, f1); |  | 
| 1861   Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), fv, ind, m); |  | 
| 1862 |  | 
| 1863   Node* ret = graph.NewNode(common.Return(), phi, start, start); |  | 
| 1864   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 1865 |  | 
| 1866   graph.SetEnd(end); |  | 
| 1867 |  | 
| 1868   ComputeAndVerifySchedule(20, &graph); |  | 
| 1869 } |  | 
| 1870 |  | 
| 1871 |  | 
| 1872 TEST(LoopedFloatingDiamond1) { |  | 
| 1873   HandleAndZoneScope scope; |  | 
| 1874   Graph graph(scope.main_zone()); |  | 
| 1875   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1876 |  | 
| 1877   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1878   graph.SetStart(start); |  | 
| 1879 |  | 
| 1880   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1881 |  | 
| 1882   Node* c = graph.NewNode(common.Int32Constant(7)); |  | 
| 1883   Node* loop = graph.NewNode(common.Loop(2), start, start); |  | 
| 1884   Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); |  | 
| 1885   Node* add = graph.NewNode(&kIntAdd, ind, c); |  | 
| 1886 |  | 
| 1887   Node* br = graph.NewNode(common.Branch(), add, loop); |  | 
| 1888   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 1889   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 1890 |  | 
| 1891   Node* br1 = graph.NewNode(common.Branch(), p0, graph.start()); |  | 
| 1892   Node* t1 = graph.NewNode(common.IfTrue(), br1); |  | 
| 1893   Node* f1 = graph.NewNode(common.IfFalse(), br1); |  | 
| 1894   Node* m1 = graph.NewNode(common.Merge(2), t1, f1); |  | 
| 1895   Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), add, p0, m1); |  | 
| 1896 |  | 
| 1897   loop->ReplaceInput(1, t);    // close loop. |  | 
| 1898   ind->ReplaceInput(1, phi1);  // close induction variable. |  | 
| 1899 |  | 
| 1900   Node* ret = graph.NewNode(common.Return(), ind, start, f); |  | 
| 1901   Node* end = graph.NewNode(common.End(), ret, f); |  | 
| 1902 |  | 
| 1903   graph.SetEnd(end); |  | 
| 1904 |  | 
| 1905   ComputeAndVerifySchedule(20, &graph); |  | 
| 1906 } |  | 
| 1907 |  | 
| 1908 |  | 
| 1909 TEST(LoopedFloatingDiamond2) { |  | 
| 1910   HandleAndZoneScope scope; |  | 
| 1911   Graph graph(scope.main_zone()); |  | 
| 1912   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1913 |  | 
| 1914   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1915   graph.SetStart(start); |  | 
| 1916 |  | 
| 1917   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1918 |  | 
| 1919   Node* c = graph.NewNode(common.Int32Constant(7)); |  | 
| 1920   Node* loop = graph.NewNode(common.Loop(2), start, start); |  | 
| 1921   Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); |  | 
| 1922 |  | 
| 1923   Node* br1 = graph.NewNode(common.Branch(), p0, graph.start()); |  | 
| 1924   Node* t1 = graph.NewNode(common.IfTrue(), br1); |  | 
| 1925   Node* f1 = graph.NewNode(common.IfFalse(), br1); |  | 
| 1926   Node* m1 = graph.NewNode(common.Merge(2), t1, f1); |  | 
| 1927   Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind, m1); |  | 
| 1928 |  | 
| 1929   Node* add = graph.NewNode(&kIntAdd, ind, phi1); |  | 
| 1930 |  | 
| 1931   Node* br = graph.NewNode(common.Branch(), add, loop); |  | 
| 1932   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 1933   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 1934 |  | 
| 1935   loop->ReplaceInput(1, t);   // close loop. |  | 
| 1936   ind->ReplaceInput(1, add);  // close induction variable. |  | 
| 1937 |  | 
| 1938   Node* ret = graph.NewNode(common.Return(), ind, start, f); |  | 
| 1939   Node* end = graph.NewNode(common.End(), ret, f); |  | 
| 1940 |  | 
| 1941   graph.SetEnd(end); |  | 
| 1942 |  | 
| 1943   ComputeAndVerifySchedule(20, &graph); |  | 
| 1944 } |  | 
| 1945 |  | 
| 1946 |  | 
| 1947 TEST(LoopedFloatingDiamond3) { |  | 
| 1948   HandleAndZoneScope scope; |  | 
| 1949   Graph graph(scope.main_zone()); |  | 
| 1950   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 1951 |  | 
| 1952   Node* start = graph.NewNode(common.Start(2)); |  | 
| 1953   graph.SetStart(start); |  | 
| 1954 |  | 
| 1955   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 1956 |  | 
| 1957   Node* c = graph.NewNode(common.Int32Constant(7)); |  | 
| 1958   Node* loop = graph.NewNode(common.Loop(2), start, start); |  | 
| 1959   Node* ind = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); |  | 
| 1960 |  | 
| 1961   Node* br1 = graph.NewNode(common.Branch(), p0, graph.start()); |  | 
| 1962   Node* t1 = graph.NewNode(common.IfTrue(), br1); |  | 
| 1963   Node* f1 = graph.NewNode(common.IfFalse(), br1); |  | 
| 1964 |  | 
| 1965   Node* loop1 = graph.NewNode(common.Loop(2), t1, start); |  | 
| 1966   Node* ind1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), p0, p0, loop); |  | 
| 1967 |  | 
| 1968   Node* add1 = graph.NewNode(&kIntAdd, ind1, c); |  | 
| 1969   Node* br2 = graph.NewNode(common.Branch(), add1, loop1); |  | 
| 1970   Node* t2 = graph.NewNode(common.IfTrue(), br2); |  | 
| 1971   Node* f2 = graph.NewNode(common.IfFalse(), br2); |  | 
| 1972 |  | 
| 1973   loop1->ReplaceInput(1, t2);   // close inner loop. |  | 
| 1974   ind1->ReplaceInput(1, ind1);  // close inner induction variable. |  | 
| 1975 |  | 
| 1976   Node* m1 = graph.NewNode(common.Merge(2), f1, f2); |  | 
| 1977   Node* phi1 = graph.NewNode(common.Phi(kMachAnyTagged, 2), c, ind1, m1); |  | 
| 1978 |  | 
| 1979   Node* add = graph.NewNode(&kIntAdd, ind, phi1); |  | 
| 1980 |  | 
| 1981   Node* br = graph.NewNode(common.Branch(), add, loop); |  | 
| 1982   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 1983   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 1984 |  | 
| 1985   loop->ReplaceInput(1, t);   // close loop. |  | 
| 1986   ind->ReplaceInput(1, add);  // close induction variable. |  | 
| 1987 |  | 
| 1988   Node* ret = graph.NewNode(common.Return(), ind, start, f); |  | 
| 1989   Node* end = graph.NewNode(common.End(), ret, f); |  | 
| 1990 |  | 
| 1991   graph.SetEnd(end); |  | 
| 1992 |  | 
| 1993   ComputeAndVerifySchedule(28, &graph); |  | 
| 1994 } |  | 
| 1995 |  | 
| 1996 |  | 
| 1997 TEST(PhisPushedDownToDifferentBranches) { |  | 
| 1998   HandleAndZoneScope scope; |  | 
| 1999   Graph graph(scope.main_zone()); |  | 
| 2000   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 2001 |  | 
| 2002   Node* start = graph.NewNode(common.Start(2)); |  | 
| 2003   graph.SetStart(start); |  | 
| 2004 |  | 
| 2005   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 2006   Node* p1 = graph.NewNode(common.Parameter(1), start); |  | 
| 2007 |  | 
| 2008   Node* v1 = graph.NewNode(common.Int32Constant(1)); |  | 
| 2009   Node* v2 = graph.NewNode(common.Int32Constant(2)); |  | 
| 2010   Node* v3 = graph.NewNode(common.Int32Constant(3)); |  | 
| 2011   Node* v4 = graph.NewNode(common.Int32Constant(4)); |  | 
| 2012   Node* br = graph.NewNode(common.Branch(), p0, graph.start()); |  | 
| 2013   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 2014   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 2015   Node* m = graph.NewNode(common.Merge(2), t, f); |  | 
| 2016   Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), v1, v2, m); |  | 
| 2017   Node* phi2 = graph.NewNode(common.Phi(kMachAnyTagged, 2), v3, v4, m); |  | 
| 2018 |  | 
| 2019   Node* br2 = graph.NewNode(common.Branch(), p1, graph.start()); |  | 
| 2020   Node* t2 = graph.NewNode(common.IfTrue(), br2); |  | 
| 2021   Node* f2 = graph.NewNode(common.IfFalse(), br2); |  | 
| 2022   Node* m2 = graph.NewNode(common.Merge(2), t2, f2); |  | 
| 2023   Node* phi3 = graph.NewNode(common.Phi(kMachAnyTagged, 2), phi, phi2, m2); |  | 
| 2024 |  | 
| 2025   Node* ret = graph.NewNode(common.Return(), phi3, start, start); |  | 
| 2026   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 2027 |  | 
| 2028   graph.SetEnd(end); |  | 
| 2029 |  | 
| 2030   ComputeAndVerifySchedule(24, &graph); |  | 
| 2031 } |  | 
| 2032 |  | 
| 2033 |  | 
| 2034 TEST(BranchHintTrue) { |  | 
| 2035   HandleAndZoneScope scope; |  | 
| 2036   Graph graph(scope.main_zone()); |  | 
| 2037   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 2038 |  | 
| 2039   Node* start = graph.NewNode(common.Start(1)); |  | 
| 2040   graph.SetStart(start); |  | 
| 2041 |  | 
| 2042   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 2043   Node* tv = graph.NewNode(common.Int32Constant(6)); |  | 
| 2044   Node* fv = graph.NewNode(common.Int32Constant(7)); |  | 
| 2045   Node* br = graph.NewNode(common.Branch(BranchHint::kTrue), p0, start); |  | 
| 2046   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 2047   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 2048   Node* m = graph.NewNode(common.Merge(2), t, f); |  | 
| 2049   Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), tv, fv, m); |  | 
| 2050   Node* ret = graph.NewNode(common.Return(), phi, start, start); |  | 
| 2051   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 2052 |  | 
| 2053   graph.SetEnd(end); |  | 
| 2054 |  | 
| 2055   Schedule* schedule = ComputeAndVerifySchedule(13, &graph); |  | 
| 2056   // Make sure the false block is marked as deferred. |  | 
| 2057   CHECK(!schedule->block(t)->deferred()); |  | 
| 2058   CHECK(schedule->block(f)->deferred()); |  | 
| 2059 } |  | 
| 2060 |  | 
| 2061 |  | 
| 2062 TEST(BranchHintFalse) { |  | 
| 2063   HandleAndZoneScope scope; |  | 
| 2064   Graph graph(scope.main_zone()); |  | 
| 2065   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 2066 |  | 
| 2067   Node* start = graph.NewNode(common.Start(1)); |  | 
| 2068   graph.SetStart(start); |  | 
| 2069 |  | 
| 2070   Node* p0 = graph.NewNode(common.Parameter(0), start); |  | 
| 2071   Node* tv = graph.NewNode(common.Int32Constant(6)); |  | 
| 2072   Node* fv = graph.NewNode(common.Int32Constant(7)); |  | 
| 2073   Node* br = graph.NewNode(common.Branch(BranchHint::kFalse), p0, start); |  | 
| 2074   Node* t = graph.NewNode(common.IfTrue(), br); |  | 
| 2075   Node* f = graph.NewNode(common.IfFalse(), br); |  | 
| 2076   Node* m = graph.NewNode(common.Merge(2), t, f); |  | 
| 2077   Node* phi = graph.NewNode(common.Phi(kMachAnyTagged, 2), tv, fv, m); |  | 
| 2078   Node* ret = graph.NewNode(common.Return(), phi, start, start); |  | 
| 2079   Node* end = graph.NewNode(common.End(), ret, start); |  | 
| 2080 |  | 
| 2081   graph.SetEnd(end); |  | 
| 2082 |  | 
| 2083   Schedule* schedule = ComputeAndVerifySchedule(13, &graph); |  | 
| 2084   // Make sure the true block is marked as deferred. |  | 
| 2085   CHECK(schedule->block(t)->deferred()); |  | 
| 2086   CHECK(!schedule->block(f)->deferred()); |  | 
| 2087 } |  | 
| 2088 |  | 
| 2089 |  | 
| 2090 TEST(ScheduleTerminate) { |  | 
| 2091   HandleAndZoneScope scope; |  | 
| 2092   Graph graph(scope.main_zone()); |  | 
| 2093   CommonOperatorBuilder common(scope.main_zone()); |  | 
| 2094 |  | 
| 2095   Node* start = graph.NewNode(common.Start(1)); |  | 
| 2096   graph.SetStart(start); |  | 
| 2097 |  | 
| 2098   Node* loop = graph.NewNode(common.Loop(2), start, start); |  | 
| 2099   loop->ReplaceInput(1, loop);  // self loop, NTL. |  | 
| 2100 |  | 
| 2101   Node* effect = graph.NewNode(common.EffectPhi(1), start, loop); |  | 
| 2102   effect->ReplaceInput(0, effect); |  | 
| 2103 |  | 
| 2104   Node* terminate = graph.NewNode(common.Terminate(1), effect, loop); |  | 
| 2105   Node* end = graph.NewNode(common.End(), terminate); |  | 
| 2106 |  | 
| 2107   graph.SetEnd(end); |  | 
| 2108 |  | 
| 2109   Schedule* schedule = ComputeAndVerifySchedule(6, &graph); |  | 
| 2110   BasicBlock* block = schedule->block(loop); |  | 
| 2111   CHECK_NE(NULL, loop); |  | 
| 2112   CHECK_EQ(block, schedule->block(effect)); |  | 
| 2113   CHECK_GE(block->rpo_number(), 0); |  | 
| 2114 } |  | 
| 2115 |  | 
| 2116 #endif |  | 
| OLD | NEW | 
|---|