Home | History | Annotate | Download | only in compiler
      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 #include "test/cctest/cctest.h"
      7 
      8 #include "src/compiler/common-operator.h"
      9 #include "src/compiler/generic-node-inl.h"
     10 #include "src/compiler/generic-node.h"
     11 #include "src/compiler/graph.h"
     12 #include "src/compiler/graph-visualizer.h"
     13 #include "src/compiler/js-operator.h"
     14 #include "src/compiler/machine-operator.h"
     15 #include "src/compiler/node.h"
     16 #include "src/compiler/operator.h"
     17 #include "src/compiler/schedule.h"
     18 #include "src/compiler/scheduler.h"
     19 #include "src/compiler/verifier.h"
     20 
     21 using namespace v8::internal;
     22 using namespace v8::internal::compiler;
     23 
     24 // TODO(titzer): pull RPO tests out to their own file.
     25 struct TestLoop {
     26   int count;
     27   BasicBlock** nodes;
     28   BasicBlock* header() { return nodes[0]; }
     29   BasicBlock* last() { return nodes[count - 1]; }
     30   ~TestLoop() { delete[] nodes; }
     31 };
     32 
     33 
     34 static TestLoop* CreateLoop(Schedule* schedule, int count) {
     35   TestLoop* loop = new TestLoop();
     36   loop->count = count;
     37   loop->nodes = new BasicBlock* [count];
     38   for (int i = 0; i < count; i++) {
     39     loop->nodes[i] = schedule->NewBasicBlock();
     40     if (i > 0) schedule->AddSuccessor(loop->nodes[i - 1], loop->nodes[i]);
     41   }
     42   schedule->AddSuccessor(loop->nodes[count - 1], loop->nodes[0]);
     43   return loop;
     44 }
     45 
     46 
     47 static void CheckRPONumbers(BasicBlockVector* order, int expected,
     48                             bool loops_allowed) {
     49   CHECK_EQ(expected, static_cast<int>(order->size()));
     50   for (int i = 0; i < static_cast<int>(order->size()); i++) {
     51     CHECK(order->at(i)->rpo_number_ == i);
     52     if (!loops_allowed) CHECK_LT(order->at(i)->loop_end_, 0);
     53   }
     54 }
     55 
     56 
     57 static void CheckLoopContains(BasicBlock** blocks, int body_size) {
     58   BasicBlock* header = blocks[0];
     59   CHECK_GT(header->loop_end_, 0);
     60   CHECK_EQ(body_size, (header->loop_end_ - header->rpo_number_));
     61   for (int i = 0; i < body_size; i++) {
     62     int num = blocks[i]->rpo_number_;
     63     CHECK(num >= header->rpo_number_ && num < header->loop_end_);
     64     CHECK(header->LoopContains(blocks[i]));
     65     CHECK(header->IsLoopHeader() || blocks[i]->loop_header_ == header);
     66   }
     67 }
     68 
     69 
     70 static int GetScheduledNodeCount(Schedule* schedule) {
     71   int node_count = 0;
     72   for (BasicBlockVectorIter i = schedule->rpo_order()->begin();
     73        i != schedule->rpo_order()->end(); ++i) {
     74     BasicBlock* block = *i;
     75     for (BasicBlock::const_iterator j = block->begin(); j != block->end();
     76          ++j) {
     77       ++node_count;
     78     }
     79     BasicBlock::Control control = block->control_;
     80     if (control != BasicBlock::kNone) {
     81       ++node_count;
     82     }
     83   }
     84   return node_count;
     85 }
     86 
     87 
     88 static Schedule* ComputeAndVerifySchedule(int expected, Graph* graph) {
     89   if (FLAG_trace_turbo) {
     90     OFStream os(stdout);
     91     os << AsDOT(*graph);
     92   }
     93 
     94   Schedule* schedule = Scheduler::ComputeSchedule(graph);
     95 
     96   if (FLAG_trace_turbo_scheduler) {
     97     OFStream os(stdout);
     98     os << *schedule << endl;
     99   }
    100   ScheduleVerifier::Run(schedule);
    101   CHECK_EQ(expected, GetScheduledNodeCount(schedule));
    102   return schedule;
    103 }
    104 
    105 
    106 TEST(RPODegenerate1) {
    107   HandleAndZoneScope scope;
    108   Schedule schedule(scope.main_zone());
    109 
    110   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    111   CheckRPONumbers(order, 1, false);
    112   CHECK_EQ(schedule.start(), order->at(0));
    113 }
    114 
    115 
    116 TEST(RPODegenerate2) {
    117   HandleAndZoneScope scope;
    118   Schedule schedule(scope.main_zone());
    119 
    120   schedule.AddGoto(schedule.start(), schedule.end());
    121   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    122   CheckRPONumbers(order, 2, false);
    123   CHECK_EQ(schedule.start(), order->at(0));
    124   CHECK_EQ(schedule.end(), order->at(1));
    125 }
    126 
    127 
    128 TEST(RPOLine) {
    129   HandleAndZoneScope scope;
    130 
    131   for (int i = 0; i < 10; i++) {
    132     Schedule schedule(scope.main_zone());
    133 
    134     BasicBlock* last = schedule.start();
    135     for (int j = 0; j < i; j++) {
    136       BasicBlock* block = schedule.NewBasicBlock();
    137       schedule.AddGoto(last, block);
    138       last = block;
    139     }
    140     BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    141     CheckRPONumbers(order, 1 + i, false);
    142 
    143     Schedule::BasicBlocks blocks(schedule.all_blocks());
    144     for (Schedule::BasicBlocks::iterator iter = blocks.begin();
    145          iter != blocks.end(); ++iter) {
    146       BasicBlock* block = *iter;
    147       if (block->rpo_number_ >= 0 && block->SuccessorCount() == 1) {
    148         CHECK(block->rpo_number_ + 1 == block->SuccessorAt(0)->rpo_number_);
    149       }
    150     }
    151   }
    152 }
    153 
    154 
    155 TEST(RPOSelfLoop) {
    156   HandleAndZoneScope scope;
    157   Schedule schedule(scope.main_zone());
    158   schedule.AddSuccessor(schedule.start(), schedule.start());
    159   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    160   CheckRPONumbers(order, 1, true);
    161   BasicBlock* loop[] = {schedule.start()};
    162   CheckLoopContains(loop, 1);
    163 }
    164 
    165 
    166 TEST(RPOEntryLoop) {
    167   HandleAndZoneScope scope;
    168   Schedule schedule(scope.main_zone());
    169   schedule.AddSuccessor(schedule.start(), schedule.end());
    170   schedule.AddSuccessor(schedule.end(), schedule.start());
    171   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    172   CheckRPONumbers(order, 2, true);
    173   BasicBlock* loop[] = {schedule.start(), schedule.end()};
    174   CheckLoopContains(loop, 2);
    175 }
    176 
    177 
    178 TEST(RPOEndLoop) {
    179   HandleAndZoneScope scope;
    180   Schedule schedule(scope.main_zone());
    181   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
    182   schedule.AddSuccessor(schedule.start(), loop1->header());
    183   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    184   CheckRPONumbers(order, 3, true);
    185   CheckLoopContains(loop1->nodes, loop1->count);
    186 }
    187 
    188 
    189 TEST(RPOEndLoopNested) {
    190   HandleAndZoneScope scope;
    191   Schedule schedule(scope.main_zone());
    192   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2));
    193   schedule.AddSuccessor(schedule.start(), loop1->header());
    194   schedule.AddSuccessor(loop1->last(), schedule.start());
    195   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    196   CheckRPONumbers(order, 3, true);
    197   CheckLoopContains(loop1->nodes, loop1->count);
    198 }
    199 
    200 
    201 TEST(RPODiamond) {
    202   HandleAndZoneScope scope;
    203   Schedule schedule(scope.main_zone());
    204 
    205   BasicBlock* A = schedule.start();
    206   BasicBlock* B = schedule.NewBasicBlock();
    207   BasicBlock* C = schedule.NewBasicBlock();
    208   BasicBlock* D = schedule.end();
    209 
    210   schedule.AddSuccessor(A, B);
    211   schedule.AddSuccessor(A, C);
    212   schedule.AddSuccessor(B, D);
    213   schedule.AddSuccessor(C, D);
    214 
    215   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    216   CheckRPONumbers(order, 4, false);
    217 
    218   CHECK_EQ(0, A->rpo_number_);
    219   CHECK((B->rpo_number_ == 1 && C->rpo_number_ == 2) ||
    220         (B->rpo_number_ == 2 && C->rpo_number_ == 1));
    221   CHECK_EQ(3, D->rpo_number_);
    222 }
    223 
    224 
    225 TEST(RPOLoop1) {
    226   HandleAndZoneScope scope;
    227   Schedule schedule(scope.main_zone());
    228 
    229   BasicBlock* A = schedule.start();
    230   BasicBlock* B = schedule.NewBasicBlock();
    231   BasicBlock* C = schedule.NewBasicBlock();
    232   BasicBlock* D = schedule.end();
    233 
    234   schedule.AddSuccessor(A, B);
    235   schedule.AddSuccessor(B, C);
    236   schedule.AddSuccessor(C, B);
    237   schedule.AddSuccessor(C, D);
    238 
    239   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    240   CheckRPONumbers(order, 4, true);
    241   BasicBlock* loop[] = {B, C};
    242   CheckLoopContains(loop, 2);
    243 }
    244 
    245 
    246 TEST(RPOLoop2) {
    247   HandleAndZoneScope scope;
    248   Schedule schedule(scope.main_zone());
    249 
    250   BasicBlock* A = schedule.start();
    251   BasicBlock* B = schedule.NewBasicBlock();
    252   BasicBlock* C = schedule.NewBasicBlock();
    253   BasicBlock* D = schedule.end();
    254 
    255   schedule.AddSuccessor(A, B);
    256   schedule.AddSuccessor(B, C);
    257   schedule.AddSuccessor(C, B);
    258   schedule.AddSuccessor(B, D);
    259 
    260   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    261   CheckRPONumbers(order, 4, true);
    262   BasicBlock* loop[] = {B, C};
    263   CheckLoopContains(loop, 2);
    264 }
    265 
    266 
    267 TEST(RPOLoopN) {
    268   HandleAndZoneScope scope;
    269 
    270   for (int i = 0; i < 11; i++) {
    271     Schedule schedule(scope.main_zone());
    272     BasicBlock* A = schedule.start();
    273     BasicBlock* B = schedule.NewBasicBlock();
    274     BasicBlock* C = schedule.NewBasicBlock();
    275     BasicBlock* D = schedule.NewBasicBlock();
    276     BasicBlock* E = schedule.NewBasicBlock();
    277     BasicBlock* F = schedule.NewBasicBlock();
    278     BasicBlock* G = schedule.end();
    279 
    280     schedule.AddSuccessor(A, B);
    281     schedule.AddSuccessor(B, C);
    282     schedule.AddSuccessor(C, D);
    283     schedule.AddSuccessor(D, E);
    284     schedule.AddSuccessor(E, F);
    285     schedule.AddSuccessor(F, B);
    286     schedule.AddSuccessor(B, G);
    287 
    288     // Throw in extra backedges from time to time.
    289     if (i == 1) schedule.AddSuccessor(B, B);
    290     if (i == 2) schedule.AddSuccessor(C, B);
    291     if (i == 3) schedule.AddSuccessor(D, B);
    292     if (i == 4) schedule.AddSuccessor(E, B);
    293     if (i == 5) schedule.AddSuccessor(F, B);
    294 
    295     // Throw in extra loop exits from time to time.
    296     if (i == 6) schedule.AddSuccessor(B, G);
    297     if (i == 7) schedule.AddSuccessor(C, G);
    298     if (i == 8) schedule.AddSuccessor(D, G);
    299     if (i == 9) schedule.AddSuccessor(E, G);
    300     if (i == 10) schedule.AddSuccessor(F, G);
    301 
    302     BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    303     CheckRPONumbers(order, 7, true);
    304     BasicBlock* loop[] = {B, C, D, E, F};
    305     CheckLoopContains(loop, 5);
    306   }
    307 }
    308 
    309 
    310 TEST(RPOLoopNest1) {
    311   HandleAndZoneScope scope;
    312   Schedule schedule(scope.main_zone());
    313 
    314   BasicBlock* A = schedule.start();
    315   BasicBlock* B = schedule.NewBasicBlock();
    316   BasicBlock* C = schedule.NewBasicBlock();
    317   BasicBlock* D = schedule.NewBasicBlock();
    318   BasicBlock* E = schedule.NewBasicBlock();
    319   BasicBlock* F = schedule.end();
    320 
    321   schedule.AddSuccessor(A, B);
    322   schedule.AddSuccessor(B, C);
    323   schedule.AddSuccessor(C, D);
    324   schedule.AddSuccessor(D, C);
    325   schedule.AddSuccessor(D, E);
    326   schedule.AddSuccessor(E, B);
    327   schedule.AddSuccessor(E, F);
    328 
    329   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    330   CheckRPONumbers(order, 6, true);
    331   BasicBlock* loop1[] = {B, C, D, E};
    332   CheckLoopContains(loop1, 4);
    333 
    334   BasicBlock* loop2[] = {C, D};
    335   CheckLoopContains(loop2, 2);
    336 }
    337 
    338 
    339 TEST(RPOLoopNest2) {
    340   HandleAndZoneScope scope;
    341   Schedule schedule(scope.main_zone());
    342 
    343   BasicBlock* A = schedule.start();
    344   BasicBlock* B = schedule.NewBasicBlock();
    345   BasicBlock* C = schedule.NewBasicBlock();
    346   BasicBlock* D = schedule.NewBasicBlock();
    347   BasicBlock* E = schedule.NewBasicBlock();
    348   BasicBlock* F = schedule.NewBasicBlock();
    349   BasicBlock* G = schedule.NewBasicBlock();
    350   BasicBlock* H = schedule.end();
    351 
    352   schedule.AddSuccessor(A, B);
    353   schedule.AddSuccessor(B, C);
    354   schedule.AddSuccessor(C, D);
    355   schedule.AddSuccessor(D, E);
    356   schedule.AddSuccessor(E, F);
    357   schedule.AddSuccessor(F, G);
    358   schedule.AddSuccessor(G, H);
    359 
    360   schedule.AddSuccessor(E, D);
    361   schedule.AddSuccessor(F, C);
    362   schedule.AddSuccessor(G, B);
    363 
    364   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    365   CheckRPONumbers(order, 8, true);
    366   BasicBlock* loop1[] = {B, C, D, E, F, G};
    367   CheckLoopContains(loop1, 6);
    368 
    369   BasicBlock* loop2[] = {C, D, E, F};
    370   CheckLoopContains(loop2, 4);
    371 
    372   BasicBlock* loop3[] = {D, E};
    373   CheckLoopContains(loop3, 2);
    374 }
    375 
    376 
    377 TEST(RPOLoopFollow1) {
    378   HandleAndZoneScope scope;
    379   Schedule schedule(scope.main_zone());
    380 
    381   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
    382   SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
    383 
    384   BasicBlock* A = schedule.start();
    385   BasicBlock* E = schedule.end();
    386 
    387   schedule.AddSuccessor(A, loop1->header());
    388   schedule.AddSuccessor(loop1->header(), loop2->header());
    389   schedule.AddSuccessor(loop2->last(), E);
    390 
    391   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    392 
    393   CheckLoopContains(loop1->nodes, loop1->count);
    394 
    395   CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
    396   CheckLoopContains(loop1->nodes, loop1->count);
    397   CheckLoopContains(loop2->nodes, loop2->count);
    398 }
    399 
    400 
    401 TEST(RPOLoopFollow2) {
    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* S = schedule.NewBasicBlock();
    410   BasicBlock* E = schedule.end();
    411 
    412   schedule.AddSuccessor(A, loop1->header());
    413   schedule.AddSuccessor(loop1->header(), S);
    414   schedule.AddSuccessor(S, loop2->header());
    415   schedule.AddSuccessor(loop2->last(), E);
    416 
    417   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    418 
    419   CheckLoopContains(loop1->nodes, loop1->count);
    420 
    421   CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
    422   CheckLoopContains(loop1->nodes, loop1->count);
    423   CheckLoopContains(loop2->nodes, loop2->count);
    424 }
    425 
    426 
    427 TEST(RPOLoopFollowN) {
    428   HandleAndZoneScope scope;
    429 
    430   for (int size = 1; size < 5; size++) {
    431     for (int exit = 0; exit < size; exit++) {
    432       Schedule schedule(scope.main_zone());
    433       SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
    434       SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size));
    435       BasicBlock* A = schedule.start();
    436       BasicBlock* E = schedule.end();
    437 
    438       schedule.AddSuccessor(A, loop1->header());
    439       schedule.AddSuccessor(loop1->nodes[exit], loop2->header());
    440       schedule.AddSuccessor(loop2->nodes[exit], E);
    441       BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    442       CheckLoopContains(loop1->nodes, loop1->count);
    443 
    444       CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
    445       CheckLoopContains(loop1->nodes, loop1->count);
    446       CheckLoopContains(loop2->nodes, loop2->count);
    447     }
    448   }
    449 }
    450 
    451 
    452 TEST(RPONestedLoopFollow1) {
    453   HandleAndZoneScope scope;
    454   Schedule schedule(scope.main_zone());
    455 
    456   SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1));
    457   SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1));
    458 
    459   BasicBlock* A = schedule.start();
    460   BasicBlock* B = schedule.NewBasicBlock();
    461   BasicBlock* C = schedule.NewBasicBlock();
    462   BasicBlock* E = schedule.end();
    463 
    464   schedule.AddSuccessor(A, B);
    465   schedule.AddSuccessor(B, loop1->header());
    466   schedule.AddSuccessor(loop1->header(), loop2->header());
    467   schedule.AddSuccessor(loop2->last(), C);
    468   schedule.AddSuccessor(C, E);
    469   schedule.AddSuccessor(C, B);
    470 
    471   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    472 
    473   CheckLoopContains(loop1->nodes, loop1->count);
    474 
    475   CHECK_EQ(schedule.BasicBlockCount(), static_cast<int>(order->size()));
    476   CheckLoopContains(loop1->nodes, loop1->count);
    477   CheckLoopContains(loop2->nodes, loop2->count);
    478 
    479   BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C};
    480   CheckLoopContains(loop3, 4);
    481 }
    482 
    483 
    484 TEST(RPOLoopBackedges1) {
    485   HandleAndZoneScope scope;
    486 
    487   int size = 8;
    488   for (int i = 0; i < size; i++) {
    489     for (int j = 0; j < size; j++) {
    490       Schedule schedule(scope.main_zone());
    491       BasicBlock* A = schedule.start();
    492       BasicBlock* E = schedule.end();
    493 
    494       SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
    495       schedule.AddSuccessor(A, loop1->header());
    496       schedule.AddSuccessor(loop1->last(), E);
    497 
    498       schedule.AddSuccessor(loop1->nodes[i], loop1->header());
    499       schedule.AddSuccessor(loop1->nodes[j], E);
    500 
    501       BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    502       CheckRPONumbers(order, schedule.BasicBlockCount(), true);
    503       CheckLoopContains(loop1->nodes, loop1->count);
    504     }
    505   }
    506 }
    507 
    508 
    509 TEST(RPOLoopOutedges1) {
    510   HandleAndZoneScope scope;
    511 
    512   int size = 8;
    513   for (int i = 0; i < size; i++) {
    514     for (int j = 0; j < size; j++) {
    515       Schedule schedule(scope.main_zone());
    516       BasicBlock* A = schedule.start();
    517       BasicBlock* D = schedule.NewBasicBlock();
    518       BasicBlock* E = schedule.end();
    519 
    520       SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
    521       schedule.AddSuccessor(A, loop1->header());
    522       schedule.AddSuccessor(loop1->last(), E);
    523 
    524       schedule.AddSuccessor(loop1->nodes[i], loop1->header());
    525       schedule.AddSuccessor(loop1->nodes[j], D);
    526       schedule.AddSuccessor(D, E);
    527 
    528       BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    529       CheckRPONumbers(order, schedule.BasicBlockCount(), true);
    530       CheckLoopContains(loop1->nodes, loop1->count);
    531     }
    532   }
    533 }
    534 
    535 
    536 TEST(RPOLoopOutedges2) {
    537   HandleAndZoneScope scope;
    538 
    539   int size = 8;
    540   for (int i = 0; i < size; i++) {
    541     Schedule schedule(scope.main_zone());
    542     BasicBlock* A = schedule.start();
    543     BasicBlock* E = schedule.end();
    544 
    545     SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
    546     schedule.AddSuccessor(A, loop1->header());
    547     schedule.AddSuccessor(loop1->last(), E);
    548 
    549     for (int j = 0; j < size; j++) {
    550       BasicBlock* O = schedule.NewBasicBlock();
    551       schedule.AddSuccessor(loop1->nodes[j], O);
    552       schedule.AddSuccessor(O, E);
    553     }
    554 
    555     BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    556     CheckRPONumbers(order, schedule.BasicBlockCount(), true);
    557     CheckLoopContains(loop1->nodes, loop1->count);
    558   }
    559 }
    560 
    561 
    562 TEST(RPOLoopOutloops1) {
    563   HandleAndZoneScope scope;
    564 
    565   int size = 8;
    566   for (int i = 0; i < size; i++) {
    567     Schedule schedule(scope.main_zone());
    568     BasicBlock* A = schedule.start();
    569     BasicBlock* E = schedule.end();
    570     SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size));
    571     schedule.AddSuccessor(A, loop1->header());
    572     schedule.AddSuccessor(loop1->last(), E);
    573 
    574     TestLoop** loopN = new TestLoop* [size];
    575     for (int j = 0; j < size; j++) {
    576       loopN[j] = CreateLoop(&schedule, 2);
    577       schedule.AddSuccessor(loop1->nodes[j], loopN[j]->header());
    578       schedule.AddSuccessor(loopN[j]->last(), E);
    579     }
    580 
    581     BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    582     CheckRPONumbers(order, schedule.BasicBlockCount(), true);
    583     CheckLoopContains(loop1->nodes, loop1->count);
    584 
    585     for (int j = 0; j < size; j++) {
    586       CheckLoopContains(loopN[j]->nodes, loopN[j]->count);
    587       delete loopN[j];
    588     }
    589     delete[] loopN;
    590   }
    591 }
    592 
    593 
    594 TEST(RPOLoopMultibackedge) {
    595   HandleAndZoneScope scope;
    596   Schedule schedule(scope.main_zone());
    597 
    598   BasicBlock* A = schedule.start();
    599   BasicBlock* B = schedule.NewBasicBlock();
    600   BasicBlock* C = schedule.NewBasicBlock();
    601   BasicBlock* D = schedule.end();
    602   BasicBlock* E = schedule.NewBasicBlock();
    603 
    604   schedule.AddSuccessor(A, B);
    605   schedule.AddSuccessor(B, C);
    606   schedule.AddSuccessor(B, D);
    607   schedule.AddSuccessor(B, E);
    608   schedule.AddSuccessor(C, B);
    609   schedule.AddSuccessor(D, B);
    610   schedule.AddSuccessor(E, B);
    611 
    612   BasicBlockVector* order = Scheduler::ComputeSpecialRPO(&schedule);
    613   CheckRPONumbers(order, 5, true);
    614 
    615   BasicBlock* loop1[] = {B, C, D, E};
    616   CheckLoopContains(loop1, 4);
    617 }
    618 
    619 
    620 TEST(BuildScheduleEmpty) {
    621   HandleAndZoneScope scope;
    622   Graph graph(scope.main_zone());
    623   CommonOperatorBuilder builder(scope.main_zone());
    624   graph.SetStart(graph.NewNode(builder.Start(0)));
    625   graph.SetEnd(graph.NewNode(builder.End(), graph.start()));
    626 
    627   USE(Scheduler::ComputeSchedule(&graph));
    628 }
    629 
    630 
    631 TEST(BuildScheduleOneParameter) {
    632   HandleAndZoneScope scope;
    633   Graph graph(scope.main_zone());
    634   CommonOperatorBuilder builder(scope.main_zone());
    635   graph.SetStart(graph.NewNode(builder.Start(0)));
    636 
    637   Node* p1 = graph.NewNode(builder.Parameter(0), graph.start());
    638   Node* ret = graph.NewNode(builder.Return(), p1, graph.start(), graph.start());
    639 
    640   graph.SetEnd(graph.NewNode(builder.End(), ret));
    641 
    642   USE(Scheduler::ComputeSchedule(&graph));
    643 }
    644 
    645 
    646 TEST(BuildScheduleIfSplit) {
    647   HandleAndZoneScope scope;
    648   Graph graph(scope.main_zone());
    649   CommonOperatorBuilder builder(scope.main_zone());
    650   JSOperatorBuilder js_builder(scope.main_zone());
    651   graph.SetStart(graph.NewNode(builder.Start(3)));
    652 
    653   Node* p1 = graph.NewNode(builder.Parameter(0), graph.start());
    654   Node* p2 = graph.NewNode(builder.Parameter(1), graph.start());
    655   Node* p3 = graph.NewNode(builder.Parameter(2), graph.start());
    656   Node* p4 = graph.NewNode(builder.Parameter(3), graph.start());
    657   Node* p5 = graph.NewNode(builder.Parameter(4), graph.start());
    658   Node* cmp = graph.NewNode(js_builder.LessThanOrEqual(), p1, p2, p3,
    659                             graph.start(), graph.start());
    660   Node* branch = graph.NewNode(builder.Branch(), cmp, graph.start());
    661   Node* true_branch = graph.NewNode(builder.IfTrue(), branch);
    662   Node* false_branch = graph.NewNode(builder.IfFalse(), branch);
    663 
    664   Node* ret1 = graph.NewNode(builder.Return(), p4, graph.start(), true_branch);
    665   Node* ret2 = graph.NewNode(builder.Return(), p5, graph.start(), false_branch);
    666   Node* merge = graph.NewNode(builder.Merge(2), ret1, ret2);
    667   graph.SetEnd(graph.NewNode(builder.End(), merge));
    668 
    669   ComputeAndVerifySchedule(13, &graph);
    670 }
    671 
    672 
    673 TEST(BuildScheduleIfSplitWithEffects) {
    674   HandleAndZoneScope scope;
    675   Isolate* isolate = scope.main_isolate();
    676   Graph graph(scope.main_zone());
    677   CommonOperatorBuilder common_builder(scope.main_zone());
    678   JSOperatorBuilder js_builder(scope.main_zone());
    679   const Operator* op;
    680 
    681   Handle<Object> object =
    682       Handle<Object>(isolate->heap()->undefined_value(), isolate);
    683   Unique<Object> unique_constant = Unique<Object>::CreateUninitialized(object);
    684 
    685   // Manually transcripted code for:
    686   // function turbo_fan_test(a, b, c, y) {
    687   //   if (a < b) {
    688   //     return a + b - c * c - a + y;
    689   //   } else {
    690   //     return c * c - a;
    691   //   }
    692   // }
    693   op = common_builder.Start(0);
    694   Node* n0 = graph.NewNode(op);
    695   USE(n0);
    696   Node* nil = graph.NewNode(common_builder.Dead());
    697   op = common_builder.End();
    698   Node* n23 = graph.NewNode(op, nil);
    699   USE(n23);
    700   op = common_builder.Merge(2);
    701   Node* n22 = graph.NewNode(op, nil, nil);
    702   USE(n22);
    703   op = common_builder.Return();
    704   Node* n16 = graph.NewNode(op, nil, nil, nil);
    705   USE(n16);
    706   op = js_builder.Add();
    707   Node* n15 = graph.NewNode(op, nil, nil, nil, nil, nil);
    708   USE(n15);
    709   op = js_builder.Subtract();
    710   Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
    711   USE(n14);
    712   op = js_builder.Subtract();
    713   Node* n13 = graph.NewNode(op, nil, nil, nil, nil, nil);
    714   USE(n13);
    715   op = js_builder.Add();
    716   Node* n11 = graph.NewNode(op, nil, nil, nil, nil, nil);
    717   USE(n11);
    718   op = common_builder.Parameter(0);
    719   Node* n2 = graph.NewNode(op, n0);
    720   USE(n2);
    721   n11->ReplaceInput(0, n2);
    722   op = common_builder.Parameter(0);
    723   Node* n3 = graph.NewNode(op, n0);
    724   USE(n3);
    725   n11->ReplaceInput(1, n3);
    726   op = common_builder.HeapConstant(unique_constant);
    727   Node* n7 = graph.NewNode(op);
    728   USE(n7);
    729   n11->ReplaceInput(2, n7);
    730   op = js_builder.LessThan();
    731   Node* n8 = graph.NewNode(op, nil, nil, nil, nil, nil);
    732   USE(n8);
    733   n8->ReplaceInput(0, n2);
    734   n8->ReplaceInput(1, n3);
    735   n8->ReplaceInput(2, n7);
    736   n8->ReplaceInput(3, n0);
    737   n8->ReplaceInput(4, n0);
    738   n11->ReplaceInput(3, n8);
    739   op = common_builder.IfTrue();
    740   Node* n10 = graph.NewNode(op, nil);
    741   USE(n10);
    742   op = common_builder.Branch();
    743   Node* n9 = graph.NewNode(op, nil, nil);
    744   USE(n9);
    745   n9->ReplaceInput(0, n8);
    746   n9->ReplaceInput(1, n0);
    747   n10->ReplaceInput(0, n9);
    748   n11->ReplaceInput(4, n10);
    749   n13->ReplaceInput(0, n11);
    750   op = js_builder.Multiply();
    751   Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil);
    752   USE(n12);
    753   op = common_builder.Parameter(0);
    754   Node* n4 = graph.NewNode(op, n0);
    755   USE(n4);
    756   n12->ReplaceInput(0, n4);
    757   n12->ReplaceInput(1, n4);
    758   n12->ReplaceInput(2, n7);
    759   n12->ReplaceInput(3, n11);
    760   n12->ReplaceInput(4, n10);
    761   n13->ReplaceInput(1, n12);
    762   n13->ReplaceInput(2, n7);
    763   n13->ReplaceInput(3, n12);
    764   n13->ReplaceInput(4, n10);
    765   n14->ReplaceInput(0, n13);
    766   n14->ReplaceInput(1, n2);
    767   n14->ReplaceInput(2, n7);
    768   n14->ReplaceInput(3, n13);
    769   n14->ReplaceInput(4, n10);
    770   n15->ReplaceInput(0, n14);
    771   op = common_builder.Parameter(0);
    772   Node* n5 = graph.NewNode(op, n0);
    773   USE(n5);
    774   n15->ReplaceInput(1, n5);
    775   n15->ReplaceInput(2, n7);
    776   n15->ReplaceInput(3, n14);
    777   n15->ReplaceInput(4, n10);
    778   n16->ReplaceInput(0, n15);
    779   n16->ReplaceInput(1, n15);
    780   n16->ReplaceInput(2, n10);
    781   n22->ReplaceInput(0, n16);
    782   op = common_builder.Return();
    783   Node* n21 = graph.NewNode(op, nil, nil, nil);
    784   USE(n21);
    785   op = js_builder.Subtract();
    786   Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
    787   USE(n20);
    788   op = js_builder.Multiply();
    789   Node* n19 = graph.NewNode(op, nil, nil, nil, nil, nil);
    790   USE(n19);
    791   n19->ReplaceInput(0, n4);
    792   n19->ReplaceInput(1, n4);
    793   n19->ReplaceInput(2, n7);
    794   n19->ReplaceInput(3, n8);
    795   op = common_builder.IfFalse();
    796   Node* n18 = graph.NewNode(op, nil);
    797   USE(n18);
    798   n18->ReplaceInput(0, n9);
    799   n19->ReplaceInput(4, n18);
    800   n20->ReplaceInput(0, n19);
    801   n20->ReplaceInput(1, n2);
    802   n20->ReplaceInput(2, n7);
    803   n20->ReplaceInput(3, n19);
    804   n20->ReplaceInput(4, n18);
    805   n21->ReplaceInput(0, n20);
    806   n21->ReplaceInput(1, n20);
    807   n21->ReplaceInput(2, n18);
    808   n22->ReplaceInput(1, n21);
    809   n23->ReplaceInput(0, n22);
    810 
    811   graph.SetStart(n0);
    812   graph.SetEnd(n23);
    813 
    814   ComputeAndVerifySchedule(20, &graph);
    815 }
    816 
    817 
    818 TEST(BuildScheduleSimpleLoop) {
    819   HandleAndZoneScope scope;
    820   Isolate* isolate = scope.main_isolate();
    821   Graph graph(scope.main_zone());
    822   CommonOperatorBuilder common_builder(scope.main_zone());
    823   JSOperatorBuilder js_builder(scope.main_zone());
    824   const Operator* op;
    825 
    826   Handle<Object> object =
    827       Handle<Object>(isolate->heap()->undefined_value(), isolate);
    828   Unique<Object> unique_constant = Unique<Object>::CreateUninitialized(object);
    829 
    830   // Manually transcripted code for:
    831   // function turbo_fan_test(a, b) {
    832   //   while (a < b) {
    833   //     a++;
    834   //   }
    835   //   return a;
    836   // }
    837   op = common_builder.Start(0);
    838   Node* n0 = graph.NewNode(op);
    839   USE(n0);
    840   Node* nil = graph.NewNode(common_builder.Dead());
    841   op = common_builder.End();
    842   Node* n20 = graph.NewNode(op, nil);
    843   USE(n20);
    844   op = common_builder.Return();
    845   Node* n19 = graph.NewNode(op, nil, nil, nil);
    846   USE(n19);
    847   op = common_builder.Phi(kMachAnyTagged, 2);
    848   Node* n8 = graph.NewNode(op, nil, nil, nil);
    849   USE(n8);
    850   op = common_builder.Parameter(0);
    851   Node* n2 = graph.NewNode(op, n0);
    852   USE(n2);
    853   n8->ReplaceInput(0, n2);
    854   op = js_builder.Add();
    855   Node* n18 = graph.NewNode(op, nil, nil, nil, nil, nil);
    856   USE(n18);
    857   op = js_builder.ToNumber();
    858   Node* n16 = graph.NewNode(op, nil, nil, nil, nil);
    859   USE(n16);
    860   n16->ReplaceInput(0, n8);
    861   op = common_builder.HeapConstant(unique_constant);
    862   Node* n5 = graph.NewNode(op);
    863   USE(n5);
    864   n16->ReplaceInput(1, n5);
    865   op = js_builder.LessThan();
    866   Node* n12 = graph.NewNode(op, nil, nil, nil, nil, nil);
    867   USE(n12);
    868   n12->ReplaceInput(0, n8);
    869   op = common_builder.Phi(kMachAnyTagged, 2);
    870   Node* n9 = graph.NewNode(op, nil, nil, nil);
    871   USE(n9);
    872   op = common_builder.Parameter(0);
    873   Node* n3 = graph.NewNode(op, n0);
    874   USE(n3);
    875   n9->ReplaceInput(0, n3);
    876   n9->ReplaceInput(1, n9);
    877   op = common_builder.Loop(2);
    878   Node* n6 = graph.NewNode(op, nil, nil);
    879   USE(n6);
    880   n6->ReplaceInput(0, n0);
    881   op = common_builder.IfTrue();
    882   Node* n14 = graph.NewNode(op, nil);
    883   USE(n14);
    884   op = common_builder.Branch();
    885   Node* n13 = graph.NewNode(op, nil, nil);
    886   USE(n13);
    887   n13->ReplaceInput(0, n12);
    888   n13->ReplaceInput(1, n6);
    889   n14->ReplaceInput(0, n13);
    890   n6->ReplaceInput(1, n14);
    891   n9->ReplaceInput(2, n6);
    892   n12->ReplaceInput(1, n9);
    893   n12->ReplaceInput(2, n5);
    894   op = common_builder.Phi(kMachAnyTagged, 2);
    895   Node* n10 = graph.NewNode(op, nil, nil, nil);
    896   USE(n10);
    897   n10->ReplaceInput(0, n0);
    898   n10->ReplaceInput(1, n18);
    899   n10->ReplaceInput(2, n6);
    900   n12->ReplaceInput(3, n10);
    901   n12->ReplaceInput(4, n6);
    902   n16->ReplaceInput(2, n12);
    903   n16->ReplaceInput(3, n14);
    904   n18->ReplaceInput(0, n16);
    905   op = common_builder.NumberConstant(0);
    906   Node* n17 = graph.NewNode(op);
    907   USE(n17);
    908   n18->ReplaceInput(1, n17);
    909   n18->ReplaceInput(2, n5);
    910   n18->ReplaceInput(3, n16);
    911   n18->ReplaceInput(4, n14);
    912   n8->ReplaceInput(1, n18);
    913   n8->ReplaceInput(2, n6);
    914   n19->ReplaceInput(0, n8);
    915   n19->ReplaceInput(1, n12);
    916   op = common_builder.IfFalse();
    917   Node* n15 = graph.NewNode(op, nil);
    918   USE(n15);
    919   n15->ReplaceInput(0, n13);
    920   n19->ReplaceInput(2, n15);
    921   n20->ReplaceInput(0, n19);
    922 
    923   graph.SetStart(n0);
    924   graph.SetEnd(n20);
    925 
    926   ComputeAndVerifySchedule(19, &graph);
    927 }
    928 
    929 
    930 TEST(BuildScheduleComplexLoops) {
    931   HandleAndZoneScope scope;
    932   Isolate* isolate = scope.main_isolate();
    933   Graph graph(scope.main_zone());
    934   CommonOperatorBuilder common_builder(scope.main_zone());
    935   JSOperatorBuilder js_builder(scope.main_zone());
    936   const Operator* op;
    937 
    938   Handle<Object> object =
    939       Handle<Object>(isolate->heap()->undefined_value(), isolate);
    940   Unique<Object> unique_constant = Unique<Object>::CreateUninitialized(object);
    941 
    942   // Manually transcripted code for:
    943   // function turbo_fan_test(a, b, c) {
    944   //   while (a < b) {
    945   //     a++;
    946   //     while (c < b) {
    947   //       c++;
    948   //     }
    949   //   }
    950   //   while (a < b) {
    951   //     a += 2;
    952   //   }
    953   //   return a;
    954   // }
    955   op = common_builder.Start(0);
    956   Node* n0 = graph.NewNode(op);
    957   USE(n0);
    958   Node* nil = graph.NewNode(common_builder.Dead());
    959   op = common_builder.End();
    960   Node* n46 = graph.NewNode(op, nil);
    961   USE(n46);
    962   op = common_builder.Return();
    963   Node* n45 = graph.NewNode(op, nil, nil, nil);
    964   USE(n45);
    965   op = common_builder.Phi(kMachAnyTagged, 2);
    966   Node* n35 = graph.NewNode(op, nil, nil, nil);
    967   USE(n35);
    968   op = common_builder.Phi(kMachAnyTagged, 2);
    969   Node* n9 = graph.NewNode(op, nil, nil, nil);
    970   USE(n9);
    971   op = common_builder.Parameter(0);
    972   Node* n2 = graph.NewNode(op, n0);
    973   USE(n2);
    974   n9->ReplaceInput(0, n2);
    975   op = common_builder.Phi(kMachAnyTagged, 2);
    976   Node* n23 = graph.NewNode(op, nil, nil, nil);
    977   USE(n23);
    978   op = js_builder.Add();
    979   Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
    980   USE(n20);
    981   op = js_builder.ToNumber();
    982   Node* n18 = graph.NewNode(op, nil, nil, nil, nil);
    983   USE(n18);
    984   n18->ReplaceInput(0, n9);
    985   op = common_builder.HeapConstant(unique_constant);
    986   Node* n6 = graph.NewNode(op);
    987   USE(n6);
    988   n18->ReplaceInput(1, n6);
    989   op = js_builder.LessThan();
    990   Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
    991   USE(n14);
    992   n14->ReplaceInput(0, n9);
    993   op = common_builder.Phi(kMachAnyTagged, 2);
    994   Node* n10 = graph.NewNode(op, nil, nil, nil);
    995   USE(n10);
    996   op = common_builder.Parameter(0);
    997   Node* n3 = graph.NewNode(op, n0);
    998   USE(n3);
    999   n10->ReplaceInput(0, n3);
   1000   op = common_builder.Phi(kMachAnyTagged, 2);
   1001   Node* n24 = graph.NewNode(op, nil, nil, nil);
   1002   USE(n24);
   1003   n24->ReplaceInput(0, n10);
   1004   n24->ReplaceInput(1, n24);
   1005   op = common_builder.Loop(2);
   1006   Node* n21 = graph.NewNode(op, nil, nil);
   1007   USE(n21);
   1008   op = common_builder.IfTrue();
   1009   Node* n16 = graph.NewNode(op, nil);
   1010   USE(n16);
   1011   op = common_builder.Branch();
   1012   Node* n15 = graph.NewNode(op, nil, nil);
   1013   USE(n15);
   1014   n15->ReplaceInput(0, n14);
   1015   op = common_builder.Loop(2);
   1016   Node* n7 = graph.NewNode(op, nil, nil);
   1017   USE(n7);
   1018   n7->ReplaceInput(0, n0);
   1019   op = common_builder.IfFalse();
   1020   Node* n30 = graph.NewNode(op, nil);
   1021   USE(n30);
   1022   op = common_builder.Branch();
   1023   Node* n28 = graph.NewNode(op, nil, nil);
   1024   USE(n28);
   1025   op = js_builder.LessThan();
   1026   Node* n27 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1027   USE(n27);
   1028   op = common_builder.Phi(kMachAnyTagged, 2);
   1029   Node* n25 = graph.NewNode(op, nil, nil, nil);
   1030   USE(n25);
   1031   op = common_builder.Phi(kMachAnyTagged, 2);
   1032   Node* n11 = graph.NewNode(op, nil, nil, nil);
   1033   USE(n11);
   1034   op = common_builder.Parameter(0);
   1035   Node* n4 = graph.NewNode(op, n0);
   1036   USE(n4);
   1037   n11->ReplaceInput(0, n4);
   1038   n11->ReplaceInput(1, n25);
   1039   n11->ReplaceInput(2, n7);
   1040   n25->ReplaceInput(0, n11);
   1041   op = js_builder.Add();
   1042   Node* n32 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1043   USE(n32);
   1044   op = js_builder.ToNumber();
   1045   Node* n31 = graph.NewNode(op, nil, nil, nil, nil);
   1046   USE(n31);
   1047   n31->ReplaceInput(0, n25);
   1048   n31->ReplaceInput(1, n6);
   1049   n31->ReplaceInput(2, n27);
   1050   op = common_builder.IfTrue();
   1051   Node* n29 = graph.NewNode(op, nil);
   1052   USE(n29);
   1053   n29->ReplaceInput(0, n28);
   1054   n31->ReplaceInput(3, n29);
   1055   n32->ReplaceInput(0, n31);
   1056   op = common_builder.NumberConstant(0);
   1057   Node* n19 = graph.NewNode(op);
   1058   USE(n19);
   1059   n32->ReplaceInput(1, n19);
   1060   n32->ReplaceInput(2, n6);
   1061   n32->ReplaceInput(3, n31);
   1062   n32->ReplaceInput(4, n29);
   1063   n25->ReplaceInput(1, n32);
   1064   n25->ReplaceInput(2, n21);
   1065   n27->ReplaceInput(0, n25);
   1066   n27->ReplaceInput(1, n24);
   1067   n27->ReplaceInput(2, n6);
   1068   op = common_builder.Phi(kMachAnyTagged, 2);
   1069   Node* n26 = graph.NewNode(op, nil, nil, nil);
   1070   USE(n26);
   1071   n26->ReplaceInput(0, n20);
   1072   n26->ReplaceInput(1, n32);
   1073   n26->ReplaceInput(2, n21);
   1074   n27->ReplaceInput(3, n26);
   1075   n27->ReplaceInput(4, n21);
   1076   n28->ReplaceInput(0, n27);
   1077   n28->ReplaceInput(1, n21);
   1078   n30->ReplaceInput(0, n28);
   1079   n7->ReplaceInput(1, n30);
   1080   n15->ReplaceInput(1, n7);
   1081   n16->ReplaceInput(0, n15);
   1082   n21->ReplaceInput(0, n16);
   1083   n21->ReplaceInput(1, n29);
   1084   n24->ReplaceInput(2, n21);
   1085   n10->ReplaceInput(1, n24);
   1086   n10->ReplaceInput(2, n7);
   1087   n14->ReplaceInput(1, n10);
   1088   n14->ReplaceInput(2, n6);
   1089   op = common_builder.Phi(kMachAnyTagged, 2);
   1090   Node* n12 = graph.NewNode(op, nil, nil, nil);
   1091   USE(n12);
   1092   n12->ReplaceInput(0, n0);
   1093   n12->ReplaceInput(1, n27);
   1094   n12->ReplaceInput(2, n7);
   1095   n14->ReplaceInput(3, n12);
   1096   n14->ReplaceInput(4, n7);
   1097   n18->ReplaceInput(2, n14);
   1098   n18->ReplaceInput(3, n16);
   1099   n20->ReplaceInput(0, n18);
   1100   n20->ReplaceInput(1, n19);
   1101   n20->ReplaceInput(2, n6);
   1102   n20->ReplaceInput(3, n18);
   1103   n20->ReplaceInput(4, n16);
   1104   n23->ReplaceInput(0, n20);
   1105   n23->ReplaceInput(1, n23);
   1106   n23->ReplaceInput(2, n21);
   1107   n9->ReplaceInput(1, n23);
   1108   n9->ReplaceInput(2, n7);
   1109   n35->ReplaceInput(0, n9);
   1110   op = js_builder.Add();
   1111   Node* n44 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1112   USE(n44);
   1113   n44->ReplaceInput(0, n35);
   1114   op = common_builder.NumberConstant(0);
   1115   Node* n43 = graph.NewNode(op);
   1116   USE(n43);
   1117   n44->ReplaceInput(1, n43);
   1118   n44->ReplaceInput(2, n6);
   1119   op = js_builder.LessThan();
   1120   Node* n39 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1121   USE(n39);
   1122   n39->ReplaceInput(0, n35);
   1123   op = common_builder.Phi(kMachAnyTagged, 2);
   1124   Node* n36 = graph.NewNode(op, nil, nil, nil);
   1125   USE(n36);
   1126   n36->ReplaceInput(0, n10);
   1127   n36->ReplaceInput(1, n36);
   1128   op = common_builder.Loop(2);
   1129   Node* n33 = graph.NewNode(op, nil, nil);
   1130   USE(n33);
   1131   op = common_builder.IfFalse();
   1132   Node* n17 = graph.NewNode(op, nil);
   1133   USE(n17);
   1134   n17->ReplaceInput(0, n15);
   1135   n33->ReplaceInput(0, n17);
   1136   op = common_builder.IfTrue();
   1137   Node* n41 = graph.NewNode(op, nil);
   1138   USE(n41);
   1139   op = common_builder.Branch();
   1140   Node* n40 = graph.NewNode(op, nil, nil);
   1141   USE(n40);
   1142   n40->ReplaceInput(0, n39);
   1143   n40->ReplaceInput(1, n33);
   1144   n41->ReplaceInput(0, n40);
   1145   n33->ReplaceInput(1, n41);
   1146   n36->ReplaceInput(2, n33);
   1147   n39->ReplaceInput(1, n36);
   1148   n39->ReplaceInput(2, n6);
   1149   op = common_builder.Phi(kMachAnyTagged, 2);
   1150   Node* n38 = graph.NewNode(op, nil, nil, nil);
   1151   USE(n38);
   1152   n38->ReplaceInput(0, n14);
   1153   n38->ReplaceInput(1, n44);
   1154   n38->ReplaceInput(2, n33);
   1155   n39->ReplaceInput(3, n38);
   1156   n39->ReplaceInput(4, n33);
   1157   n44->ReplaceInput(3, n39);
   1158   n44->ReplaceInput(4, n41);
   1159   n35->ReplaceInput(1, n44);
   1160   n35->ReplaceInput(2, n33);
   1161   n45->ReplaceInput(0, n35);
   1162   n45->ReplaceInput(1, n39);
   1163   op = common_builder.IfFalse();
   1164   Node* n42 = graph.NewNode(op, nil);
   1165   USE(n42);
   1166   n42->ReplaceInput(0, n40);
   1167   n45->ReplaceInput(2, n42);
   1168   n46->ReplaceInput(0, n45);
   1169 
   1170   graph.SetStart(n0);
   1171   graph.SetEnd(n46);
   1172 
   1173   ComputeAndVerifySchedule(46, &graph);
   1174 }
   1175 
   1176 
   1177 TEST(BuildScheduleBreakAndContinue) {
   1178   HandleAndZoneScope scope;
   1179   Isolate* isolate = scope.main_isolate();
   1180   Graph graph(scope.main_zone());
   1181   CommonOperatorBuilder common_builder(scope.main_zone());
   1182   JSOperatorBuilder js_builder(scope.main_zone());
   1183   const Operator* op;
   1184 
   1185   Handle<Object> object =
   1186       Handle<Object>(isolate->heap()->undefined_value(), isolate);
   1187   Unique<Object> unique_constant = Unique<Object>::CreateUninitialized(object);
   1188 
   1189   // Manually transcripted code for:
   1190   // function turbo_fan_test(a, b, c) {
   1191   //   var d = 0;
   1192   //   while (a < b) {
   1193   //     a++;
   1194   //     while (c < b) {
   1195   //       c++;
   1196   //       if (d == 0) break;
   1197   //       a++;
   1198   //     }
   1199   //     if (a == 1) continue;
   1200   //     d++;
   1201   //   }
   1202   //   return a + d;
   1203   // }
   1204   op = common_builder.Start(0);
   1205   Node* n0 = graph.NewNode(op);
   1206   USE(n0);
   1207   Node* nil = graph.NewNode(common_builder.Dead());
   1208   op = common_builder.End();
   1209   Node* n58 = graph.NewNode(op, nil);
   1210   USE(n58);
   1211   op = common_builder.Return();
   1212   Node* n57 = graph.NewNode(op, nil, nil, nil);
   1213   USE(n57);
   1214   op = js_builder.Add();
   1215   Node* n56 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1216   USE(n56);
   1217   op = common_builder.Phi(kMachAnyTagged, 2);
   1218   Node* n10 = graph.NewNode(op, nil, nil, nil);
   1219   USE(n10);
   1220   op = common_builder.Parameter(0);
   1221   Node* n2 = graph.NewNode(op, n0);
   1222   USE(n2);
   1223   n10->ReplaceInput(0, n2);
   1224   op = common_builder.Phi(kMachAnyTagged, 2);
   1225   Node* n25 = graph.NewNode(op, nil, nil, nil);
   1226   USE(n25);
   1227   op = js_builder.Add();
   1228   Node* n22 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1229   USE(n22);
   1230   op = js_builder.ToNumber();
   1231   Node* n20 = graph.NewNode(op, nil, nil, nil, nil);
   1232   USE(n20);
   1233   n20->ReplaceInput(0, n10);
   1234   op = common_builder.HeapConstant(unique_constant);
   1235   Node* n6 = graph.NewNode(op);
   1236   USE(n6);
   1237   n20->ReplaceInput(1, n6);
   1238   op = js_builder.LessThan();
   1239   Node* n16 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1240   USE(n16);
   1241   n16->ReplaceInput(0, n10);
   1242   op = common_builder.Phi(kMachAnyTagged, 2);
   1243   Node* n11 = graph.NewNode(op, nil, nil, nil);
   1244   USE(n11);
   1245   op = common_builder.Parameter(0);
   1246   Node* n3 = graph.NewNode(op, n0);
   1247   USE(n3);
   1248   n11->ReplaceInput(0, n3);
   1249   op = common_builder.Phi(kMachAnyTagged, 2);
   1250   Node* n26 = graph.NewNode(op, nil, nil, nil);
   1251   USE(n26);
   1252   n26->ReplaceInput(0, n11);
   1253   n26->ReplaceInput(1, n26);
   1254   op = common_builder.Loop(2);
   1255   Node* n23 = graph.NewNode(op, nil, nil);
   1256   USE(n23);
   1257   op = common_builder.IfTrue();
   1258   Node* n18 = graph.NewNode(op, nil);
   1259   USE(n18);
   1260   op = common_builder.Branch();
   1261   Node* n17 = graph.NewNode(op, nil, nil);
   1262   USE(n17);
   1263   n17->ReplaceInput(0, n16);
   1264   op = common_builder.Loop(2);
   1265   Node* n8 = graph.NewNode(op, nil, nil);
   1266   USE(n8);
   1267   n8->ReplaceInput(0, n0);
   1268   op = common_builder.Merge(2);
   1269   Node* n53 = graph.NewNode(op, nil, nil);
   1270   USE(n53);
   1271   op = common_builder.IfTrue();
   1272   Node* n49 = graph.NewNode(op, nil);
   1273   USE(n49);
   1274   op = common_builder.Branch();
   1275   Node* n48 = graph.NewNode(op, nil, nil);
   1276   USE(n48);
   1277   op = js_builder.Equal();
   1278   Node* n47 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1279   USE(n47);
   1280   n47->ReplaceInput(0, n25);
   1281   op = common_builder.NumberConstant(0);
   1282   Node* n46 = graph.NewNode(op);
   1283   USE(n46);
   1284   n47->ReplaceInput(1, n46);
   1285   n47->ReplaceInput(2, n6);
   1286   op = common_builder.Phi(kMachAnyTagged, 2);
   1287   Node* n42 = graph.NewNode(op, nil, nil, nil);
   1288   USE(n42);
   1289   op = js_builder.LessThan();
   1290   Node* n30 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1291   USE(n30);
   1292   op = common_builder.Phi(kMachAnyTagged, 2);
   1293   Node* n27 = graph.NewNode(op, nil, nil, nil);
   1294   USE(n27);
   1295   op = common_builder.Phi(kMachAnyTagged, 2);
   1296   Node* n12 = graph.NewNode(op, nil, nil, nil);
   1297   USE(n12);
   1298   op = common_builder.Parameter(0);
   1299   Node* n4 = graph.NewNode(op, n0);
   1300   USE(n4);
   1301   n12->ReplaceInput(0, n4);
   1302   op = common_builder.Phi(kMachAnyTagged, 2);
   1303   Node* n41 = graph.NewNode(op, nil, nil, nil);
   1304   USE(n41);
   1305   n41->ReplaceInput(0, n27);
   1306   op = js_builder.Add();
   1307   Node* n35 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1308   USE(n35);
   1309   op = js_builder.ToNumber();
   1310   Node* n34 = graph.NewNode(op, nil, nil, nil, nil);
   1311   USE(n34);
   1312   n34->ReplaceInput(0, n27);
   1313   n34->ReplaceInput(1, n6);
   1314   n34->ReplaceInput(2, n30);
   1315   op = common_builder.IfTrue();
   1316   Node* n32 = graph.NewNode(op, nil);
   1317   USE(n32);
   1318   op = common_builder.Branch();
   1319   Node* n31 = graph.NewNode(op, nil, nil);
   1320   USE(n31);
   1321   n31->ReplaceInput(0, n30);
   1322   n31->ReplaceInput(1, n23);
   1323   n32->ReplaceInput(0, n31);
   1324   n34->ReplaceInput(3, n32);
   1325   n35->ReplaceInput(0, n34);
   1326   op = common_builder.NumberConstant(0);
   1327   Node* n21 = graph.NewNode(op);
   1328   USE(n21);
   1329   n35->ReplaceInput(1, n21);
   1330   n35->ReplaceInput(2, n6);
   1331   n35->ReplaceInput(3, n34);
   1332   n35->ReplaceInput(4, n32);
   1333   n41->ReplaceInput(1, n35);
   1334   op = common_builder.Merge(2);
   1335   Node* n40 = graph.NewNode(op, nil, nil);
   1336   USE(n40);
   1337   op = common_builder.IfFalse();
   1338   Node* n33 = graph.NewNode(op, nil);
   1339   USE(n33);
   1340   n33->ReplaceInput(0, n31);
   1341   n40->ReplaceInput(0, n33);
   1342   op = common_builder.IfTrue();
   1343   Node* n39 = graph.NewNode(op, nil);
   1344   USE(n39);
   1345   op = common_builder.Branch();
   1346   Node* n38 = graph.NewNode(op, nil, nil);
   1347   USE(n38);
   1348   op = js_builder.Equal();
   1349   Node* n37 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1350   USE(n37);
   1351   op = common_builder.Phi(kMachAnyTagged, 2);
   1352   Node* n28 = graph.NewNode(op, nil, nil, nil);
   1353   USE(n28);
   1354   op = common_builder.Phi(kMachAnyTagged, 2);
   1355   Node* n13 = graph.NewNode(op, nil, nil, nil);
   1356   USE(n13);
   1357   op = common_builder.NumberConstant(0);
   1358   Node* n7 = graph.NewNode(op);
   1359   USE(n7);
   1360   n13->ReplaceInput(0, n7);
   1361   op = common_builder.Phi(kMachAnyTagged, 2);
   1362   Node* n54 = graph.NewNode(op, nil, nil, nil);
   1363   USE(n54);
   1364   n54->ReplaceInput(0, n28);
   1365   op = js_builder.Add();
   1366   Node* n52 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1367   USE(n52);
   1368   op = js_builder.ToNumber();
   1369   Node* n51 = graph.NewNode(op, nil, nil, nil, nil);
   1370   USE(n51);
   1371   n51->ReplaceInput(0, n28);
   1372   n51->ReplaceInput(1, n6);
   1373   n51->ReplaceInput(2, n47);
   1374   op = common_builder.IfFalse();
   1375   Node* n50 = graph.NewNode(op, nil);
   1376   USE(n50);
   1377   n50->ReplaceInput(0, n48);
   1378   n51->ReplaceInput(3, n50);
   1379   n52->ReplaceInput(0, n51);
   1380   n52->ReplaceInput(1, n21);
   1381   n52->ReplaceInput(2, n6);
   1382   n52->ReplaceInput(3, n51);
   1383   n52->ReplaceInput(4, n50);
   1384   n54->ReplaceInput(1, n52);
   1385   n54->ReplaceInput(2, n53);
   1386   n13->ReplaceInput(1, n54);
   1387   n13->ReplaceInput(2, n8);
   1388   n28->ReplaceInput(0, n13);
   1389   n28->ReplaceInput(1, n28);
   1390   n28->ReplaceInput(2, n23);
   1391   n37->ReplaceInput(0, n28);
   1392   op = common_builder.NumberConstant(0);
   1393   Node* n36 = graph.NewNode(op);
   1394   USE(n36);
   1395   n37->ReplaceInput(1, n36);
   1396   n37->ReplaceInput(2, n6);
   1397   n37->ReplaceInput(3, n35);
   1398   n37->ReplaceInput(4, n32);
   1399   n38->ReplaceInput(0, n37);
   1400   n38->ReplaceInput(1, n32);
   1401   n39->ReplaceInput(0, n38);
   1402   n40->ReplaceInput(1, n39);
   1403   n41->ReplaceInput(2, n40);
   1404   n12->ReplaceInput(1, n41);
   1405   n12->ReplaceInput(2, n8);
   1406   n27->ReplaceInput(0, n12);
   1407   n27->ReplaceInput(1, n35);
   1408   n27->ReplaceInput(2, n23);
   1409   n30->ReplaceInput(0, n27);
   1410   n30->ReplaceInput(1, n26);
   1411   n30->ReplaceInput(2, n6);
   1412   op = common_builder.Phi(kMachAnyTagged, 2);
   1413   Node* n29 = graph.NewNode(op, nil, nil, nil);
   1414   USE(n29);
   1415   n29->ReplaceInput(0, n22);
   1416   op = js_builder.Add();
   1417   Node* n45 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1418   USE(n45);
   1419   op = js_builder.ToNumber();
   1420   Node* n44 = graph.NewNode(op, nil, nil, nil, nil);
   1421   USE(n44);
   1422   n44->ReplaceInput(0, n25);
   1423   n44->ReplaceInput(1, n6);
   1424   n44->ReplaceInput(2, n37);
   1425   op = common_builder.IfFalse();
   1426   Node* n43 = graph.NewNode(op, nil);
   1427   USE(n43);
   1428   n43->ReplaceInput(0, n38);
   1429   n44->ReplaceInput(3, n43);
   1430   n45->ReplaceInput(0, n44);
   1431   n45->ReplaceInput(1, n21);
   1432   n45->ReplaceInput(2, n6);
   1433   n45->ReplaceInput(3, n44);
   1434   n45->ReplaceInput(4, n43);
   1435   n29->ReplaceInput(1, n45);
   1436   n29->ReplaceInput(2, n23);
   1437   n30->ReplaceInput(3, n29);
   1438   n30->ReplaceInput(4, n23);
   1439   n42->ReplaceInput(0, n30);
   1440   n42->ReplaceInput(1, n37);
   1441   n42->ReplaceInput(2, n40);
   1442   n47->ReplaceInput(3, n42);
   1443   n47->ReplaceInput(4, n40);
   1444   n48->ReplaceInput(0, n47);
   1445   n48->ReplaceInput(1, n40);
   1446   n49->ReplaceInput(0, n48);
   1447   n53->ReplaceInput(0, n49);
   1448   n53->ReplaceInput(1, n50);
   1449   n8->ReplaceInput(1, n53);
   1450   n17->ReplaceInput(1, n8);
   1451   n18->ReplaceInput(0, n17);
   1452   n23->ReplaceInput(0, n18);
   1453   n23->ReplaceInput(1, n43);
   1454   n26->ReplaceInput(2, n23);
   1455   n11->ReplaceInput(1, n26);
   1456   n11->ReplaceInput(2, n8);
   1457   n16->ReplaceInput(1, n11);
   1458   n16->ReplaceInput(2, n6);
   1459   op = common_builder.Phi(kMachAnyTagged, 2);
   1460   Node* n14 = graph.NewNode(op, nil, nil, nil);
   1461   USE(n14);
   1462   n14->ReplaceInput(0, n0);
   1463   op = common_builder.Phi(kMachAnyTagged, 2);
   1464   Node* n55 = graph.NewNode(op, nil, nil, nil);
   1465   USE(n55);
   1466   n55->ReplaceInput(0, n47);
   1467   n55->ReplaceInput(1, n52);
   1468   n55->ReplaceInput(2, n53);
   1469   n14->ReplaceInput(1, n55);
   1470   n14->ReplaceInput(2, n8);
   1471   n16->ReplaceInput(3, n14);
   1472   n16->ReplaceInput(4, n8);
   1473   n20->ReplaceInput(2, n16);
   1474   n20->ReplaceInput(3, n18);
   1475   n22->ReplaceInput(0, n20);
   1476   n22->ReplaceInput(1, n21);
   1477   n22->ReplaceInput(2, n6);
   1478   n22->ReplaceInput(3, n20);
   1479   n22->ReplaceInput(4, n18);
   1480   n25->ReplaceInput(0, n22);
   1481   n25->ReplaceInput(1, n45);
   1482   n25->ReplaceInput(2, n23);
   1483   n10->ReplaceInput(1, n25);
   1484   n10->ReplaceInput(2, n8);
   1485   n56->ReplaceInput(0, n10);
   1486   n56->ReplaceInput(1, n13);
   1487   n56->ReplaceInput(2, n6);
   1488   n56->ReplaceInput(3, n16);
   1489   op = common_builder.IfFalse();
   1490   Node* n19 = graph.NewNode(op, nil);
   1491   USE(n19);
   1492   n19->ReplaceInput(0, n17);
   1493   n56->ReplaceInput(4, n19);
   1494   n57->ReplaceInput(0, n56);
   1495   n57->ReplaceInput(1, n56);
   1496   n57->ReplaceInput(2, n19);
   1497   n58->ReplaceInput(0, n57);
   1498 
   1499   graph.SetStart(n0);
   1500   graph.SetEnd(n58);
   1501 
   1502   ComputeAndVerifySchedule(62, &graph);
   1503 }
   1504 
   1505 
   1506 TEST(BuildScheduleSimpleLoopWithCodeMotion) {
   1507   HandleAndZoneScope scope;
   1508   Isolate* isolate = scope.main_isolate();
   1509   Graph graph(scope.main_zone());
   1510   CommonOperatorBuilder common_builder(scope.main_zone());
   1511   JSOperatorBuilder js_builder(scope.main_zone());
   1512   MachineOperatorBuilder machine_builder;
   1513   const Operator* op;
   1514 
   1515   Handle<Object> object =
   1516       Handle<Object>(isolate->heap()->undefined_value(), isolate);
   1517   Unique<Object> unique_constant = Unique<Object>::CreateUninitialized(object);
   1518 
   1519   // Manually transcripted code for:
   1520   // function turbo_fan_test(a, b, c) {
   1521   //   while (a < b) {
   1522   //     a += b + c;
   1523   //   }
   1524   //   return a;
   1525   // }
   1526   op = common_builder.Start(0);
   1527   Node* n0 = graph.NewNode(op);
   1528   USE(n0);
   1529   Node* nil = graph.NewNode(common_builder.Dead());
   1530   op = common_builder.End();
   1531   Node* n22 = graph.NewNode(op, nil);
   1532   USE(n22);
   1533   op = common_builder.Return();
   1534   Node* n21 = graph.NewNode(op, nil, nil, nil);
   1535   USE(n21);
   1536   op = common_builder.Phi(kMachAnyTagged, 2);
   1537   Node* n9 = graph.NewNode(op, nil, nil, nil);
   1538   USE(n9);
   1539   op = common_builder.Parameter(0);
   1540   Node* n2 = graph.NewNode(op, n0);
   1541   USE(n2);
   1542   n9->ReplaceInput(0, n2);
   1543   op = js_builder.Add();
   1544   Node* n20 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1545   USE(n20);
   1546   n20->ReplaceInput(0, n9);
   1547   op = machine_builder.Int32Add();
   1548   Node* n19 = graph.NewNode(op, nil, nil);
   1549   USE(n19);
   1550   op = common_builder.Phi(kMachAnyTagged, 2);
   1551   Node* n10 = graph.NewNode(op, nil, nil, nil);
   1552   USE(n10);
   1553   op = common_builder.Parameter(0);
   1554   Node* n3 = graph.NewNode(op, n0);
   1555   USE(n3);
   1556   n10->ReplaceInput(0, n3);
   1557   n10->ReplaceInput(1, n10);
   1558   op = common_builder.Loop(2);
   1559   Node* n7 = graph.NewNode(op, nil, nil);
   1560   USE(n7);
   1561   n7->ReplaceInput(0, n0);
   1562   op = common_builder.IfTrue();
   1563   Node* n17 = graph.NewNode(op, nil);
   1564   USE(n17);
   1565   op = common_builder.Branch();
   1566   Node* n16 = graph.NewNode(op, nil, nil);
   1567   USE(n16);
   1568   op = js_builder.ToBoolean();
   1569   Node* n15 = graph.NewNode(op, nil, nil, nil, nil);
   1570   USE(n15);
   1571   op = js_builder.LessThan();
   1572   Node* n14 = graph.NewNode(op, nil, nil, nil, nil, nil);
   1573   USE(n14);
   1574   n14->ReplaceInput(0, n9);
   1575   n14->ReplaceInput(1, n10);
   1576   op = common_builder.HeapConstant(unique_constant);
   1577   Node* n6 = graph.NewNode(op);
   1578   USE(n6);
   1579   n14->ReplaceInput(2, n6);
   1580   op = common_builder.Phi(kMachAnyTagged, 2);
   1581   Node* n12 = graph.NewNode(op, nil, nil, nil);
   1582   USE(n12);
   1583   n12->ReplaceInput(0, n0);
   1584   n12->ReplaceInput(1, n20);
   1585   n12->ReplaceInput(2, n7);
   1586   n14->ReplaceInput(3, n12);
   1587   n14->ReplaceInput(4, n7);
   1588   n15->ReplaceInput(0, n14);
   1589   n15->ReplaceInput(1, n6);
   1590   n15->ReplaceInput(2, n14);
   1591   n15->ReplaceInput(3, n7);
   1592   n16->ReplaceInput(0, n15);
   1593   n16->ReplaceInput(1, n7);
   1594   n17->ReplaceInput(0, n16);
   1595   n7->ReplaceInput(1, n17);
   1596   n10->ReplaceInput(2, n7);
   1597   n19->ReplaceInput(0, n2);
   1598   op = common_builder.Phi(kMachAnyTagged, 2);
   1599   Node* n11 = graph.NewNode(op, nil, nil, nil);
   1600   USE(n11);
   1601   op = common_builder.Parameter(0);
   1602   Node* n4 = graph.NewNode(op, n0);
   1603   USE(n4);
   1604   n11->ReplaceInput(0, n4);
   1605   n11->ReplaceInput(1, n11);
   1606   n11->ReplaceInput(2, n7);
   1607   n19->ReplaceInput(1, n3);
   1608   n20->ReplaceInput(1, n19);
   1609   n20->ReplaceInput(2, n6);
   1610   n20->ReplaceInput(3, n19);
   1611   n20->ReplaceInput(4, n17);
   1612   n9->ReplaceInput(1, n20);
   1613   n9->ReplaceInput(2, n7);
   1614   n21->ReplaceInput(0, n9);
   1615   n21->ReplaceInput(1, n15);
   1616   op = common_builder.IfFalse();
   1617   Node* n18 = graph.NewNode(op, nil);
   1618   USE(n18);
   1619   n18->ReplaceInput(0, n16);
   1620   n21->ReplaceInput(2, n18);
   1621   n22->ReplaceInput(0, n21);
   1622 
   1623   graph.SetStart(n0);
   1624   graph.SetEnd(n22);
   1625 
   1626   Schedule* schedule = ComputeAndVerifySchedule(19, &graph);
   1627   // Make sure the integer-only add gets hoisted to a different block that the
   1628   // JSAdd.
   1629   CHECK(schedule->block(n19) != schedule->block(n20));
   1630 }
   1631 
   1632 
   1633 #if V8_TURBOFAN_TARGET
   1634 
   1635 static Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common,
   1636                            Node* cond) {
   1637   Node* tv = graph->NewNode(common->Int32Constant(6));
   1638   Node* fv = graph->NewNode(common->Int32Constant(7));
   1639   Node* br = graph->NewNode(common->Branch(), cond, graph->start());
   1640   Node* t = graph->NewNode(common->IfTrue(), br);
   1641   Node* f = graph->NewNode(common->IfFalse(), br);
   1642   Node* m = graph->NewNode(common->Merge(2), t, f);
   1643   Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2), tv, fv, m);
   1644   return phi;
   1645 }
   1646 
   1647 
   1648 TEST(FloatingDiamond1) {
   1649   HandleAndZoneScope scope;
   1650   Graph graph(scope.main_zone());
   1651   CommonOperatorBuilder common(scope.main_zone());
   1652 
   1653   Node* start = graph.NewNode(common.Start(1));
   1654   graph.SetStart(start);
   1655 
   1656   Node* p0 = graph.NewNode(common.Parameter(0), start);
   1657   Node* d1 = CreateDiamond(&graph, &common, p0);
   1658   Node* ret = graph.NewNode(common.Return(), d1, start, start);
   1659   Node* end = graph.NewNode(common.End(), ret, start);
   1660 
   1661   graph.SetEnd(end);
   1662 
   1663   ComputeAndVerifySchedule(13, &graph);
   1664 }
   1665 
   1666 
   1667 TEST(FloatingDiamond2) {
   1668   HandleAndZoneScope scope;
   1669   Graph graph(scope.main_zone());
   1670   CommonOperatorBuilder common(scope.main_zone());
   1671   MachineOperatorBuilder machine;
   1672 
   1673   Node* start = graph.NewNode(common.Start(2));
   1674   graph.SetStart(start);
   1675 
   1676   Node* p0 = graph.NewNode(common.Parameter(0), start);
   1677   Node* p1 = graph.NewNode(common.Parameter(1), start);
   1678   Node* d1 = CreateDiamond(&graph, &common, p0);
   1679   Node* d2 = CreateDiamond(&graph, &common, p1);
   1680   Node* add = graph.NewNode(machine.Int32Add(), d1, d2);
   1681   Node* ret = graph.NewNode(common.Return(), add, start, start);
   1682   Node* end = graph.NewNode(common.End(), ret, start);
   1683 
   1684   graph.SetEnd(end);
   1685 
   1686   ComputeAndVerifySchedule(24, &graph);
   1687 }
   1688 
   1689 
   1690 TEST(FloatingDiamond3) {
   1691   HandleAndZoneScope scope;
   1692   Graph graph(scope.main_zone());
   1693   CommonOperatorBuilder common(scope.main_zone());
   1694   MachineOperatorBuilder machine;
   1695 
   1696   Node* start = graph.NewNode(common.Start(2));
   1697   graph.SetStart(start);
   1698 
   1699   Node* p0 = graph.NewNode(common.Parameter(0), start);
   1700   Node* p1 = graph.NewNode(common.Parameter(1), start);
   1701   Node* d1 = CreateDiamond(&graph, &common, p0);
   1702   Node* d2 = CreateDiamond(&graph, &common, p1);
   1703   Node* add = graph.NewNode(machine.Int32Add(), d1, d2);
   1704   Node* d3 = CreateDiamond(&graph, &common, add);
   1705   Node* ret = graph.NewNode(common.Return(), d3, start, start);
   1706   Node* end = graph.NewNode(common.End(), ret, start);
   1707 
   1708   graph.SetEnd(end);
   1709 
   1710   ComputeAndVerifySchedule(33, &graph);
   1711 }
   1712 
   1713 #endif
   1714