| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/access-builder.h" | 5 #include "src/compiler/access-builder.h" |
| 6 #include "src/compiler/common-operator.h" | 6 #include "src/compiler/common-operator.h" |
| 7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
| 8 #include "src/compiler/graph-visualizer.h" | 8 #include "src/compiler/graph-visualizer.h" |
| 9 #include "src/compiler/js-operator.h" | 9 #include "src/compiler/js-operator.h" |
| 10 #include "src/compiler/node.h" | 10 #include "src/compiler/node.h" |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 JSOperatorBuilder* js() { return &js_; } | 64 JSOperatorBuilder* js() { return &js_; } |
| 65 | 65 |
| 66 private: | 66 private: |
| 67 Graph graph_; | 67 Graph graph_; |
| 68 CommonOperatorBuilder common_; | 68 CommonOperatorBuilder common_; |
| 69 SimplifiedOperatorBuilder simplified_; | 69 SimplifiedOperatorBuilder simplified_; |
| 70 JSOperatorBuilder js_; | 70 JSOperatorBuilder js_; |
| 71 }; | 71 }; |
| 72 | 72 |
| 73 | 73 |
| 74 class SchedulerRPOTest : public SchedulerTest { | |
| 75 public: | |
| 76 SchedulerRPOTest() {} | |
| 77 | |
| 78 // TODO(titzer): pull RPO tests out to their own file. | |
| 79 void CheckRPONumbers(BasicBlockVector* order, size_t expected, | |
| 80 bool loops_allowed) { | |
| 81 CHECK(expected == order->size()); | |
| 82 for (int i = 0; i < static_cast<int>(order->size()); i++) { | |
| 83 CHECK(order->at(i)->rpo_number() == i); | |
| 84 if (!loops_allowed) { | |
| 85 CHECK(!order->at(i)->loop_end()); | |
| 86 CHECK(!order->at(i)->loop_header()); | |
| 87 } | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 void CheckLoop(BasicBlockVector* order, BasicBlock** blocks, int body_size) { | |
| 92 BasicBlock* header = blocks[0]; | |
| 93 BasicBlock* end = header->loop_end(); | |
| 94 CHECK(end); | |
| 95 CHECK_GT(end->rpo_number(), 0); | |
| 96 CHECK_EQ(body_size, end->rpo_number() - header->rpo_number()); | |
| 97 for (int i = 0; i < body_size; i++) { | |
| 98 CHECK_GE(blocks[i]->rpo_number(), header->rpo_number()); | |
| 99 CHECK_LT(blocks[i]->rpo_number(), end->rpo_number()); | |
| 100 CHECK(header->LoopContains(blocks[i])); | |
| 101 CHECK(header->IsLoopHeader() || blocks[i]->loop_header() == header); | |
| 102 } | |
| 103 if (header->rpo_number() > 0) { | |
| 104 CHECK_NE(order->at(header->rpo_number() - 1)->loop_header(), header); | |
| 105 } | |
| 106 if (end->rpo_number() < static_cast<int>(order->size())) { | |
| 107 CHECK_NE(order->at(end->rpo_number())->loop_header(), header); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 struct TestLoop { | |
| 112 int count; | |
| 113 BasicBlock** nodes; | |
| 114 BasicBlock* header() { return nodes[0]; } | |
| 115 BasicBlock* last() { return nodes[count - 1]; } | |
| 116 ~TestLoop() { delete[] nodes; } | |
| 117 }; | |
| 118 | |
| 119 TestLoop* CreateLoop(Schedule* schedule, int count) { | |
| 120 TestLoop* loop = new TestLoop(); | |
| 121 loop->count = count; | |
| 122 loop->nodes = new BasicBlock* [count]; | |
| 123 for (int i = 0; i < count; i++) { | |
| 124 loop->nodes[i] = schedule->NewBasicBlock(); | |
| 125 if (i > 0) { | |
| 126 schedule->AddSuccessorForTesting(loop->nodes[i - 1], loop->nodes[i]); | |
| 127 } | |
| 128 } | |
| 129 schedule->AddSuccessorForTesting(loop->nodes[count - 1], loop->nodes[0]); | |
| 130 return loop; | |
| 131 } | |
| 132 }; | |
| 133 | |
| 134 | |
| 135 namespace { | 74 namespace { |
| 136 | 75 |
| 137 const Operator kHeapConstant(IrOpcode::kHeapConstant, Operator::kPure, | 76 const Operator kHeapConstant(IrOpcode::kHeapConstant, Operator::kPure, |
| 138 "HeapConstant", 0, 0, 0, 1, 0, 0); | 77 "HeapConstant", 0, 0, 0, 1, 0, 0); |
| 139 const Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, | 78 const Operator kIntAdd(IrOpcode::kInt32Add, Operator::kPure, "Int32Add", 2, 0, |
| 140 0, 1, 0, 0); | 79 0, 1, 0, 0); |
| 141 const Operator kMockCall(IrOpcode::kCall, Operator::kNoProperties, "MockCall", | 80 const Operator kMockCall(IrOpcode::kCall, Operator::kNoProperties, "MockCall", |
| 142 0, 0, 1, 1, 1, 2); | 81 0, 0, 1, 1, 1, 2); |
| 143 const Operator kMockTailCall(IrOpcode::kTailCall, Operator::kNoProperties, | 82 const Operator kMockTailCall(IrOpcode::kTailCall, Operator::kNoProperties, |
| 144 "MockTailCall", 1, 1, 1, 0, 0, 1); | 83 "MockTailCall", 1, 1, 1, 0, 0, 1); |
| 145 | 84 |
| 146 } // namespace | 85 } // namespace |
| 147 | 86 |
| 148 | 87 |
| 149 // ----------------------------------------------------------------------------- | |
| 150 // Special reverse-post-order block ordering. | |
| 151 | |
| 152 | |
| 153 TEST_F(SchedulerRPOTest, Degenerate1) { | |
| 154 Schedule schedule(zone()); | |
| 155 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 156 CheckRPONumbers(order, 1, false); | |
| 157 EXPECT_EQ(schedule.start(), order->at(0)); | |
| 158 } | |
| 159 | |
| 160 | |
| 161 TEST_F(SchedulerRPOTest, Degenerate2) { | |
| 162 Schedule schedule(zone()); | |
| 163 | |
| 164 schedule.AddGoto(schedule.start(), schedule.end()); | |
| 165 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 166 CheckRPONumbers(order, 2, false); | |
| 167 EXPECT_EQ(schedule.start(), order->at(0)); | |
| 168 EXPECT_EQ(schedule.end(), order->at(1)); | |
| 169 } | |
| 170 | |
| 171 | |
| 172 TEST_F(SchedulerRPOTest, Line) { | |
| 173 for (int i = 0; i < 10; i++) { | |
| 174 Schedule schedule(zone()); | |
| 175 | |
| 176 BasicBlock* last = schedule.start(); | |
| 177 for (int j = 0; j < i; j++) { | |
| 178 BasicBlock* block = schedule.NewBasicBlock(); | |
| 179 block->set_deferred(i & 1); | |
| 180 schedule.AddGoto(last, block); | |
| 181 last = block; | |
| 182 } | |
| 183 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 184 CheckRPONumbers(order, 1 + i, false); | |
| 185 | |
| 186 for (size_t i = 0; i < schedule.BasicBlockCount(); i++) { | |
| 187 BasicBlock* block = schedule.GetBlockById(BasicBlock::Id::FromSize(i)); | |
| 188 if (block->rpo_number() >= 0 && block->SuccessorCount() == 1) { | |
| 189 EXPECT_EQ(block->rpo_number() + 1, block->SuccessorAt(0)->rpo_number()); | |
| 190 } | |
| 191 } | |
| 192 } | |
| 193 } | |
| 194 | |
| 195 | |
| 196 TEST_F(SchedulerRPOTest, SelfLoop) { | |
| 197 Schedule schedule(zone()); | |
| 198 schedule.AddSuccessorForTesting(schedule.start(), schedule.start()); | |
| 199 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 200 CheckRPONumbers(order, 1, true); | |
| 201 BasicBlock* loop[] = {schedule.start()}; | |
| 202 CheckLoop(order, loop, 1); | |
| 203 } | |
| 204 | |
| 205 | |
| 206 TEST_F(SchedulerRPOTest, EntryLoop) { | |
| 207 Schedule schedule(zone()); | |
| 208 BasicBlock* body = schedule.NewBasicBlock(); | |
| 209 schedule.AddSuccessorForTesting(schedule.start(), body); | |
| 210 schedule.AddSuccessorForTesting(body, schedule.start()); | |
| 211 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 212 CheckRPONumbers(order, 2, true); | |
| 213 BasicBlock* loop[] = {schedule.start(), body}; | |
| 214 CheckLoop(order, loop, 2); | |
| 215 } | |
| 216 | |
| 217 | |
| 218 TEST_F(SchedulerRPOTest, EndLoop) { | |
| 219 Schedule schedule(zone()); | |
| 220 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2)); | |
| 221 schedule.AddSuccessorForTesting(schedule.start(), loop1->header()); | |
| 222 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 223 CheckRPONumbers(order, 3, true); | |
| 224 CheckLoop(order, loop1->nodes, loop1->count); | |
| 225 } | |
| 226 | |
| 227 | |
| 228 TEST_F(SchedulerRPOTest, EndLoopNested) { | |
| 229 Schedule schedule(zone()); | |
| 230 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 2)); | |
| 231 schedule.AddSuccessorForTesting(schedule.start(), loop1->header()); | |
| 232 schedule.AddSuccessorForTesting(loop1->last(), schedule.start()); | |
| 233 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 234 CheckRPONumbers(order, 3, true); | |
| 235 CheckLoop(order, loop1->nodes, loop1->count); | |
| 236 } | |
| 237 | |
| 238 | |
| 239 TEST_F(SchedulerRPOTest, Diamond) { | |
| 240 Schedule schedule(zone()); | |
| 241 | |
| 242 BasicBlock* A = schedule.start(); | |
| 243 BasicBlock* B = schedule.NewBasicBlock(); | |
| 244 BasicBlock* C = schedule.NewBasicBlock(); | |
| 245 BasicBlock* D = schedule.end(); | |
| 246 | |
| 247 schedule.AddSuccessorForTesting(A, B); | |
| 248 schedule.AddSuccessorForTesting(A, C); | |
| 249 schedule.AddSuccessorForTesting(B, D); | |
| 250 schedule.AddSuccessorForTesting(C, D); | |
| 251 | |
| 252 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 253 CheckRPONumbers(order, 4, false); | |
| 254 | |
| 255 EXPECT_EQ(0, A->rpo_number()); | |
| 256 EXPECT_THAT(B->rpo_number(), AnyOf(1, 2)); | |
| 257 EXPECT_THAT(C->rpo_number(), AnyOf(1, 2)); | |
| 258 EXPECT_EQ(3, D->rpo_number()); | |
| 259 } | |
| 260 | |
| 261 | |
| 262 TEST_F(SchedulerRPOTest, Loop1) { | |
| 263 Schedule schedule(zone()); | |
| 264 | |
| 265 BasicBlock* A = schedule.start(); | |
| 266 BasicBlock* B = schedule.NewBasicBlock(); | |
| 267 BasicBlock* C = schedule.NewBasicBlock(); | |
| 268 BasicBlock* D = schedule.end(); | |
| 269 | |
| 270 schedule.AddSuccessorForTesting(A, B); | |
| 271 schedule.AddSuccessorForTesting(B, C); | |
| 272 schedule.AddSuccessorForTesting(C, B); | |
| 273 schedule.AddSuccessorForTesting(C, D); | |
| 274 | |
| 275 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 276 CheckRPONumbers(order, 4, true); | |
| 277 BasicBlock* loop[] = {B, C}; | |
| 278 CheckLoop(order, loop, 2); | |
| 279 } | |
| 280 | |
| 281 | |
| 282 TEST_F(SchedulerRPOTest, Loop2) { | |
| 283 Schedule schedule(zone()); | |
| 284 | |
| 285 BasicBlock* A = schedule.start(); | |
| 286 BasicBlock* B = schedule.NewBasicBlock(); | |
| 287 BasicBlock* C = schedule.NewBasicBlock(); | |
| 288 BasicBlock* D = schedule.end(); | |
| 289 | |
| 290 schedule.AddSuccessorForTesting(A, B); | |
| 291 schedule.AddSuccessorForTesting(B, C); | |
| 292 schedule.AddSuccessorForTesting(C, B); | |
| 293 schedule.AddSuccessorForTesting(B, D); | |
| 294 | |
| 295 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 296 CheckRPONumbers(order, 4, true); | |
| 297 BasicBlock* loop[] = {B, C}; | |
| 298 CheckLoop(order, loop, 2); | |
| 299 } | |
| 300 | |
| 301 | |
| 302 TEST_F(SchedulerRPOTest, LoopN) { | |
| 303 for (int i = 0; i < 11; i++) { | |
| 304 Schedule schedule(zone()); | |
| 305 BasicBlock* A = schedule.start(); | |
| 306 BasicBlock* B = schedule.NewBasicBlock(); | |
| 307 BasicBlock* C = schedule.NewBasicBlock(); | |
| 308 BasicBlock* D = schedule.NewBasicBlock(); | |
| 309 BasicBlock* E = schedule.NewBasicBlock(); | |
| 310 BasicBlock* F = schedule.NewBasicBlock(); | |
| 311 BasicBlock* G = schedule.end(); | |
| 312 | |
| 313 schedule.AddSuccessorForTesting(A, B); | |
| 314 schedule.AddSuccessorForTesting(B, C); | |
| 315 schedule.AddSuccessorForTesting(C, D); | |
| 316 schedule.AddSuccessorForTesting(D, E); | |
| 317 schedule.AddSuccessorForTesting(E, F); | |
| 318 schedule.AddSuccessorForTesting(F, B); | |
| 319 schedule.AddSuccessorForTesting(B, G); | |
| 320 | |
| 321 // Throw in extra backedges from time to time. | |
| 322 if (i == 1) schedule.AddSuccessorForTesting(B, B); | |
| 323 if (i == 2) schedule.AddSuccessorForTesting(C, B); | |
| 324 if (i == 3) schedule.AddSuccessorForTesting(D, B); | |
| 325 if (i == 4) schedule.AddSuccessorForTesting(E, B); | |
| 326 if (i == 5) schedule.AddSuccessorForTesting(F, B); | |
| 327 | |
| 328 // Throw in extra loop exits from time to time. | |
| 329 if (i == 6) schedule.AddSuccessorForTesting(B, G); | |
| 330 if (i == 7) schedule.AddSuccessorForTesting(C, G); | |
| 331 if (i == 8) schedule.AddSuccessorForTesting(D, G); | |
| 332 if (i == 9) schedule.AddSuccessorForTesting(E, G); | |
| 333 if (i == 10) schedule.AddSuccessorForTesting(F, G); | |
| 334 | |
| 335 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 336 CheckRPONumbers(order, 7, true); | |
| 337 BasicBlock* loop[] = {B, C, D, E, F}; | |
| 338 CheckLoop(order, loop, 5); | |
| 339 } | |
| 340 } | |
| 341 | |
| 342 | |
| 343 TEST_F(SchedulerRPOTest, LoopNest1) { | |
| 344 Schedule schedule(zone()); | |
| 345 | |
| 346 BasicBlock* A = schedule.start(); | |
| 347 BasicBlock* B = schedule.NewBasicBlock(); | |
| 348 BasicBlock* C = schedule.NewBasicBlock(); | |
| 349 BasicBlock* D = schedule.NewBasicBlock(); | |
| 350 BasicBlock* E = schedule.NewBasicBlock(); | |
| 351 BasicBlock* F = schedule.end(); | |
| 352 | |
| 353 schedule.AddSuccessorForTesting(A, B); | |
| 354 schedule.AddSuccessorForTesting(B, C); | |
| 355 schedule.AddSuccessorForTesting(C, D); | |
| 356 schedule.AddSuccessorForTesting(D, C); | |
| 357 schedule.AddSuccessorForTesting(D, E); | |
| 358 schedule.AddSuccessorForTesting(E, B); | |
| 359 schedule.AddSuccessorForTesting(E, F); | |
| 360 | |
| 361 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 362 CheckRPONumbers(order, 6, true); | |
| 363 BasicBlock* loop1[] = {B, C, D, E}; | |
| 364 CheckLoop(order, loop1, 4); | |
| 365 | |
| 366 BasicBlock* loop2[] = {C, D}; | |
| 367 CheckLoop(order, loop2, 2); | |
| 368 } | |
| 369 | |
| 370 | |
| 371 TEST_F(SchedulerRPOTest, LoopNest2) { | |
| 372 Schedule schedule(zone()); | |
| 373 | |
| 374 BasicBlock* A = schedule.start(); | |
| 375 BasicBlock* B = schedule.NewBasicBlock(); | |
| 376 BasicBlock* C = schedule.NewBasicBlock(); | |
| 377 BasicBlock* D = schedule.NewBasicBlock(); | |
| 378 BasicBlock* E = schedule.NewBasicBlock(); | |
| 379 BasicBlock* F = schedule.NewBasicBlock(); | |
| 380 BasicBlock* G = schedule.NewBasicBlock(); | |
| 381 BasicBlock* H = schedule.end(); | |
| 382 | |
| 383 schedule.AddSuccessorForTesting(A, B); | |
| 384 schedule.AddSuccessorForTesting(B, C); | |
| 385 schedule.AddSuccessorForTesting(C, D); | |
| 386 schedule.AddSuccessorForTesting(D, E); | |
| 387 schedule.AddSuccessorForTesting(E, F); | |
| 388 schedule.AddSuccessorForTesting(F, G); | |
| 389 schedule.AddSuccessorForTesting(G, H); | |
| 390 | |
| 391 schedule.AddSuccessorForTesting(E, D); | |
| 392 schedule.AddSuccessorForTesting(F, C); | |
| 393 schedule.AddSuccessorForTesting(G, B); | |
| 394 | |
| 395 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 396 CheckRPONumbers(order, 8, true); | |
| 397 BasicBlock* loop1[] = {B, C, D, E, F, G}; | |
| 398 CheckLoop(order, loop1, 6); | |
| 399 | |
| 400 BasicBlock* loop2[] = {C, D, E, F}; | |
| 401 CheckLoop(order, loop2, 4); | |
| 402 | |
| 403 BasicBlock* loop3[] = {D, E}; | |
| 404 CheckLoop(order, loop3, 2); | |
| 405 } | |
| 406 | |
| 407 | |
| 408 TEST_F(SchedulerRPOTest, LoopFollow1) { | |
| 409 Schedule schedule(zone()); | |
| 410 | |
| 411 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); | |
| 412 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); | |
| 413 | |
| 414 BasicBlock* A = schedule.start(); | |
| 415 BasicBlock* E = schedule.end(); | |
| 416 | |
| 417 schedule.AddSuccessorForTesting(A, loop1->header()); | |
| 418 schedule.AddSuccessorForTesting(loop1->header(), loop2->header()); | |
| 419 schedule.AddSuccessorForTesting(loop2->last(), E); | |
| 420 | |
| 421 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 422 | |
| 423 EXPECT_EQ(schedule.BasicBlockCount(), order->size()); | |
| 424 CheckLoop(order, loop1->nodes, loop1->count); | |
| 425 CheckLoop(order, loop2->nodes, loop2->count); | |
| 426 } | |
| 427 | |
| 428 | |
| 429 TEST_F(SchedulerRPOTest, LoopFollow2) { | |
| 430 Schedule schedule(zone()); | |
| 431 | |
| 432 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); | |
| 433 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); | |
| 434 | |
| 435 BasicBlock* A = schedule.start(); | |
| 436 BasicBlock* S = schedule.NewBasicBlock(); | |
| 437 BasicBlock* E = schedule.end(); | |
| 438 | |
| 439 schedule.AddSuccessorForTesting(A, loop1->header()); | |
| 440 schedule.AddSuccessorForTesting(loop1->header(), S); | |
| 441 schedule.AddSuccessorForTesting(S, loop2->header()); | |
| 442 schedule.AddSuccessorForTesting(loop2->last(), E); | |
| 443 | |
| 444 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 445 | |
| 446 EXPECT_EQ(schedule.BasicBlockCount(), order->size()); | |
| 447 CheckLoop(order, loop1->nodes, loop1->count); | |
| 448 CheckLoop(order, loop2->nodes, loop2->count); | |
| 449 } | |
| 450 | |
| 451 | |
| 452 TEST_F(SchedulerRPOTest, LoopFollowN) { | |
| 453 for (int size = 1; size < 5; size++) { | |
| 454 for (int exit = 0; exit < size; exit++) { | |
| 455 Schedule schedule(zone()); | |
| 456 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
| 457 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, size)); | |
| 458 BasicBlock* A = schedule.start(); | |
| 459 BasicBlock* E = schedule.end(); | |
| 460 | |
| 461 schedule.AddSuccessorForTesting(A, loop1->header()); | |
| 462 schedule.AddSuccessorForTesting(loop1->nodes[exit], loop2->header()); | |
| 463 schedule.AddSuccessorForTesting(loop2->nodes[exit], E); | |
| 464 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 465 | |
| 466 EXPECT_EQ(schedule.BasicBlockCount(), order->size()); | |
| 467 CheckLoop(order, loop1->nodes, loop1->count); | |
| 468 CheckLoop(order, loop2->nodes, loop2->count); | |
| 469 } | |
| 470 } | |
| 471 } | |
| 472 | |
| 473 | |
| 474 TEST_F(SchedulerRPOTest, NestedLoopFollow1) { | |
| 475 Schedule schedule(zone()); | |
| 476 | |
| 477 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, 1)); | |
| 478 base::SmartPointer<TestLoop> loop2(CreateLoop(&schedule, 1)); | |
| 479 | |
| 480 BasicBlock* A = schedule.start(); | |
| 481 BasicBlock* B = schedule.NewBasicBlock(); | |
| 482 BasicBlock* C = schedule.NewBasicBlock(); | |
| 483 BasicBlock* E = schedule.end(); | |
| 484 | |
| 485 schedule.AddSuccessorForTesting(A, B); | |
| 486 schedule.AddSuccessorForTesting(B, loop1->header()); | |
| 487 schedule.AddSuccessorForTesting(loop1->header(), loop2->header()); | |
| 488 schedule.AddSuccessorForTesting(loop2->last(), C); | |
| 489 schedule.AddSuccessorForTesting(C, E); | |
| 490 schedule.AddSuccessorForTesting(C, B); | |
| 491 | |
| 492 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 493 | |
| 494 EXPECT_EQ(schedule.BasicBlockCount(), order->size()); | |
| 495 CheckLoop(order, loop1->nodes, loop1->count); | |
| 496 CheckLoop(order, loop2->nodes, loop2->count); | |
| 497 | |
| 498 BasicBlock* loop3[] = {B, loop1->nodes[0], loop2->nodes[0], C}; | |
| 499 CheckLoop(order, loop3, 4); | |
| 500 } | |
| 501 | |
| 502 | |
| 503 TEST_F(SchedulerRPOTest, LoopBackedges1) { | |
| 504 int size = 8; | |
| 505 for (int i = 0; i < size; i++) { | |
| 506 for (int j = 0; j < size; j++) { | |
| 507 Schedule schedule(zone()); | |
| 508 BasicBlock* A = schedule.start(); | |
| 509 BasicBlock* E = schedule.end(); | |
| 510 | |
| 511 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
| 512 schedule.AddSuccessorForTesting(A, loop1->header()); | |
| 513 schedule.AddSuccessorForTesting(loop1->last(), E); | |
| 514 | |
| 515 schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header()); | |
| 516 schedule.AddSuccessorForTesting(loop1->nodes[j], E); | |
| 517 | |
| 518 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 519 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
| 520 CheckLoop(order, loop1->nodes, loop1->count); | |
| 521 } | |
| 522 } | |
| 523 } | |
| 524 | |
| 525 | |
| 526 TEST_F(SchedulerRPOTest, LoopOutedges1) { | |
| 527 int size = 8; | |
| 528 for (int i = 0; i < size; i++) { | |
| 529 for (int j = 0; j < size; j++) { | |
| 530 Schedule schedule(zone()); | |
| 531 BasicBlock* A = schedule.start(); | |
| 532 BasicBlock* D = schedule.NewBasicBlock(); | |
| 533 BasicBlock* E = schedule.end(); | |
| 534 | |
| 535 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
| 536 schedule.AddSuccessorForTesting(A, loop1->header()); | |
| 537 schedule.AddSuccessorForTesting(loop1->last(), E); | |
| 538 | |
| 539 schedule.AddSuccessorForTesting(loop1->nodes[i], loop1->header()); | |
| 540 schedule.AddSuccessorForTesting(loop1->nodes[j], D); | |
| 541 schedule.AddSuccessorForTesting(D, E); | |
| 542 | |
| 543 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 544 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
| 545 CheckLoop(order, loop1->nodes, loop1->count); | |
| 546 } | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 | |
| 551 TEST_F(SchedulerRPOTest, LoopOutedges2) { | |
| 552 int size = 8; | |
| 553 for (int i = 0; i < size; i++) { | |
| 554 Schedule schedule(zone()); | |
| 555 BasicBlock* A = schedule.start(); | |
| 556 BasicBlock* E = schedule.end(); | |
| 557 | |
| 558 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
| 559 schedule.AddSuccessorForTesting(A, loop1->header()); | |
| 560 schedule.AddSuccessorForTesting(loop1->last(), E); | |
| 561 | |
| 562 for (int j = 0; j < size; j++) { | |
| 563 BasicBlock* O = schedule.NewBasicBlock(); | |
| 564 schedule.AddSuccessorForTesting(loop1->nodes[j], O); | |
| 565 schedule.AddSuccessorForTesting(O, E); | |
| 566 } | |
| 567 | |
| 568 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 569 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
| 570 CheckLoop(order, loop1->nodes, loop1->count); | |
| 571 } | |
| 572 } | |
| 573 | |
| 574 | |
| 575 TEST_F(SchedulerRPOTest, LoopOutloops1) { | |
| 576 int size = 8; | |
| 577 for (int i = 0; i < size; i++) { | |
| 578 Schedule schedule(zone()); | |
| 579 BasicBlock* A = schedule.start(); | |
| 580 BasicBlock* E = schedule.end(); | |
| 581 base::SmartPointer<TestLoop> loop1(CreateLoop(&schedule, size)); | |
| 582 schedule.AddSuccessorForTesting(A, loop1->header()); | |
| 583 schedule.AddSuccessorForTesting(loop1->last(), E); | |
| 584 | |
| 585 TestLoop** loopN = new TestLoop* [size]; | |
| 586 for (int j = 0; j < size; j++) { | |
| 587 loopN[j] = CreateLoop(&schedule, 2); | |
| 588 schedule.AddSuccessorForTesting(loop1->nodes[j], loopN[j]->header()); | |
| 589 schedule.AddSuccessorForTesting(loopN[j]->last(), E); | |
| 590 } | |
| 591 | |
| 592 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 593 CheckRPONumbers(order, schedule.BasicBlockCount(), true); | |
| 594 CheckLoop(order, loop1->nodes, loop1->count); | |
| 595 | |
| 596 for (int j = 0; j < size; j++) { | |
| 597 CheckLoop(order, loopN[j]->nodes, loopN[j]->count); | |
| 598 delete loopN[j]; | |
| 599 } | |
| 600 delete[] loopN; | |
| 601 } | |
| 602 } | |
| 603 | |
| 604 | |
| 605 TEST_F(SchedulerRPOTest, LoopMultibackedge) { | |
| 606 Schedule schedule(zone()); | |
| 607 | |
| 608 BasicBlock* A = schedule.start(); | |
| 609 BasicBlock* B = schedule.NewBasicBlock(); | |
| 610 BasicBlock* C = schedule.NewBasicBlock(); | |
| 611 BasicBlock* D = schedule.NewBasicBlock(); | |
| 612 BasicBlock* E = schedule.NewBasicBlock(); | |
| 613 | |
| 614 schedule.AddSuccessorForTesting(A, B); | |
| 615 schedule.AddSuccessorForTesting(B, C); | |
| 616 schedule.AddSuccessorForTesting(B, D); | |
| 617 schedule.AddSuccessorForTesting(B, E); | |
| 618 schedule.AddSuccessorForTesting(C, B); | |
| 619 schedule.AddSuccessorForTesting(D, B); | |
| 620 schedule.AddSuccessorForTesting(E, B); | |
| 621 | |
| 622 BasicBlockVector* order = Scheduler::ComputeSpecialRPO(zone(), &schedule); | |
| 623 CheckRPONumbers(order, 5, true); | |
| 624 | |
| 625 BasicBlock* loop1[] = {B, C, D, E}; | |
| 626 CheckLoop(order, loop1, 4); | |
| 627 } | |
| 628 | |
| 629 | |
| 630 // ----------------------------------------------------------------------------- | |
| 631 // Graph end-to-end scheduling. | |
| 632 | |
| 633 | |
| 634 TEST_F(SchedulerTest, BuildScheduleEmpty) { | 88 TEST_F(SchedulerTest, BuildScheduleEmpty) { |
| 635 graph()->SetStart(graph()->NewNode(common()->Start(0))); | 89 graph()->SetStart(graph()->NewNode(common()->Start(0))); |
| 636 graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start())); | 90 graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start())); |
| 637 USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags)); | 91 USE(Scheduler::ComputeSchedule(zone(), graph(), Scheduler::kNoFlags)); |
| 638 } | 92 } |
| 639 | 93 |
| 640 | 94 |
| 641 TEST_F(SchedulerTest, BuildScheduleOneParameter) { | 95 TEST_F(SchedulerTest, BuildScheduleOneParameter) { |
| 642 graph()->SetStart(graph()->NewNode(common()->Start(0))); | 96 graph()->SetStart(graph()->NewNode(common()->Start(0))); |
| 643 | 97 |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1155 | 609 |
| 1156 Schedule* schedule = ComputeAndVerifySchedule(6); | 610 Schedule* schedule = ComputeAndVerifySchedule(6); |
| 1157 BasicBlock* block = schedule->block(loop); | 611 BasicBlock* block = schedule->block(loop); |
| 1158 EXPECT_EQ(block, schedule->block(effect)); | 612 EXPECT_EQ(block, schedule->block(effect)); |
| 1159 EXPECT_GE(block->rpo_number(), 0); | 613 EXPECT_GE(block->rpo_number(), 0); |
| 1160 } | 614 } |
| 1161 | 615 |
| 1162 } // namespace compiler | 616 } // namespace compiler |
| 1163 } // namespace internal | 617 } // namespace internal |
| 1164 } // namespace v8 | 618 } // namespace v8 |
| OLD | NEW |