| 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 |