OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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/scheduler.h" | 5 #include "src/compiler/scheduler.h" |
6 | 6 |
7 #include "src/bit-vector.h" | 7 #include "src/bit-vector.h" |
8 #include "src/compiler/common-operator.h" | 8 #include "src/compiler/common-operator.h" |
9 #include "src/compiler/control-equivalence.h" | 9 #include "src/compiler/control-equivalence.h" |
10 #include "src/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
(...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 class SpecialRPONumberer : public ZoneObject { | 580 class SpecialRPONumberer : public ZoneObject { |
581 public: | 581 public: |
582 SpecialRPONumberer(Zone* zone, Schedule* schedule) | 582 SpecialRPONumberer(Zone* zone, Schedule* schedule) |
583 : zone_(zone), | 583 : zone_(zone), |
584 schedule_(schedule), | 584 schedule_(schedule), |
585 order_(NULL), | 585 order_(NULL), |
586 beyond_end_(NULL), | 586 beyond_end_(NULL), |
587 loops_(zone), | 587 loops_(zone), |
588 backedges_(zone), | 588 backedges_(zone), |
589 stack_(zone), | 589 stack_(zone), |
590 previous_block_count_(0) {} | 590 previous_block_count_(0), |
| 591 empty_(0, zone) {} |
591 | 592 |
592 // Computes the special reverse-post-order for the main control flow graph, | 593 // Computes the special reverse-post-order for the main control flow graph, |
593 // that is for the graph spanned between the schedule's start and end blocks. | 594 // that is for the graph spanned between the schedule's start and end blocks. |
594 void ComputeSpecialRPO() { | 595 void ComputeSpecialRPO() { |
595 DCHECK(schedule_->end()->SuccessorCount() == 0); | 596 DCHECK(schedule_->end()->SuccessorCount() == 0); |
596 DCHECK(!order_); // Main order does not exist yet. | 597 DCHECK(!order_); // Main order does not exist yet. |
597 ComputeAndInsertSpecialRPO(schedule_->start(), schedule_->end()); | 598 ComputeAndInsertSpecialRPO(schedule_->start(), schedule_->end()); |
598 } | 599 } |
599 | 600 |
600 // Computes the special reverse-post-order for a partial control flow graph, | 601 // Computes the special reverse-post-order for a partial control flow graph, |
(...skipping 16 matching lines...) Expand all Loading... |
617 } | 618 } |
618 | 619 |
619 // Print and verify the special reverse-post-order. | 620 // Print and verify the special reverse-post-order. |
620 void PrintAndVerifySpecialRPO() { | 621 void PrintAndVerifySpecialRPO() { |
621 #if DEBUG | 622 #if DEBUG |
622 if (FLAG_trace_turbo_scheduler) PrintRPO(); | 623 if (FLAG_trace_turbo_scheduler) PrintRPO(); |
623 VerifySpecialRPO(); | 624 VerifySpecialRPO(); |
624 #endif | 625 #endif |
625 } | 626 } |
626 | 627 |
| 628 const ZoneList<BasicBlock*>& GetOutgoingBlocks(BasicBlock* block) { |
| 629 if (HasLoopNumber(block)) { |
| 630 LoopInfo const& loop = loops_[GetLoopNumber(block)]; |
| 631 if (loop.outgoing) return *loop.outgoing; |
| 632 } |
| 633 return empty_; |
| 634 } |
| 635 |
627 private: | 636 private: |
628 typedef std::pair<BasicBlock*, size_t> Backedge; | 637 typedef std::pair<BasicBlock*, size_t> Backedge; |
629 | 638 |
630 // Numbering for BasicBlock::rpo_number for this block traversal: | 639 // Numbering for BasicBlock::rpo_number for this block traversal: |
631 static const int kBlockOnStack = -2; | 640 static const int kBlockOnStack = -2; |
632 static const int kBlockVisited1 = -3; | 641 static const int kBlockVisited1 = -3; |
633 static const int kBlockVisited2 = -4; | 642 static const int kBlockVisited2 = -4; |
634 static const int kBlockUnvisited1 = -1; | 643 static const int kBlockUnvisited1 = -1; |
635 static const int kBlockUnvisited2 = kBlockVisited1; | 644 static const int kBlockUnvisited2 = kBlockVisited1; |
636 | 645 |
(...skipping 402 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1039 #endif // DEBUG | 1048 #endif // DEBUG |
1040 | 1049 |
1041 Zone* zone_; | 1050 Zone* zone_; |
1042 Schedule* schedule_; | 1051 Schedule* schedule_; |
1043 BasicBlock* order_; | 1052 BasicBlock* order_; |
1044 BasicBlock* beyond_end_; | 1053 BasicBlock* beyond_end_; |
1045 ZoneVector<LoopInfo> loops_; | 1054 ZoneVector<LoopInfo> loops_; |
1046 ZoneVector<Backedge> backedges_; | 1055 ZoneVector<Backedge> backedges_; |
1047 ZoneVector<SpecialRPOStackFrame> stack_; | 1056 ZoneVector<SpecialRPOStackFrame> stack_; |
1048 size_t previous_block_count_; | 1057 size_t previous_block_count_; |
| 1058 ZoneList<BasicBlock*> const empty_; |
1049 }; | 1059 }; |
1050 | 1060 |
1051 | 1061 |
1052 BasicBlockVector* Scheduler::ComputeSpecialRPO(Zone* zone, Schedule* schedule) { | 1062 BasicBlockVector* Scheduler::ComputeSpecialRPO(Zone* zone, Schedule* schedule) { |
1053 SpecialRPONumberer numberer(zone, schedule); | 1063 SpecialRPONumberer numberer(zone, schedule); |
1054 numberer.ComputeSpecialRPO(); | 1064 numberer.ComputeSpecialRPO(); |
1055 numberer.SerializeRPOIntoSchedule(); | 1065 numberer.SerializeRPOIntoSchedule(); |
1056 numberer.PrintAndVerifySpecialRPO(); | 1066 numberer.PrintAndVerifySpecialRPO(); |
1057 return schedule->rpo_order(); | 1067 return schedule->rpo_order(); |
1058 } | 1068 } |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1339 // The schedule early block dominates the schedule late block. | 1349 // The schedule early block dominates the schedule late block. |
1340 BasicBlock* min_block = scheduler_->GetData(node)->minimum_block_; | 1350 BasicBlock* min_block = scheduler_->GetData(node)->minimum_block_; |
1341 DCHECK_EQ(min_block, BasicBlock::GetCommonDominator(block, min_block)); | 1351 DCHECK_EQ(min_block, BasicBlock::GetCommonDominator(block, min_block)); |
1342 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum = B%d\n", | 1352 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum = B%d\n", |
1343 node->id(), node->op()->mnemonic(), block->id().ToInt(), | 1353 node->id(), node->op()->mnemonic(), block->id().ToInt(), |
1344 block->loop_depth(), min_block->id().ToInt()); | 1354 block->loop_depth(), min_block->id().ToInt()); |
1345 | 1355 |
1346 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively | 1356 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively |
1347 // into enclosing loop pre-headers until they would preceed their schedule | 1357 // into enclosing loop pre-headers until they would preceed their schedule |
1348 // early position. | 1358 // early position. |
1349 BasicBlock* hoist_block = GetPreHeader(block); | 1359 BasicBlock* hoist_block = GetHoistBlock(block); |
1350 if (hoist_block && | 1360 if (hoist_block && |
1351 hoist_block->dominator_depth() >= min_block->dominator_depth()) { | 1361 hoist_block->dominator_depth() >= min_block->dominator_depth()) { |
1352 do { | 1362 do { |
1353 Trace(" hoisting #%d:%s to block B%d\n", node->id(), | 1363 Trace(" hoisting #%d:%s to block B%d\n", node->id(), |
1354 node->op()->mnemonic(), hoist_block->id().ToInt()); | 1364 node->op()->mnemonic(), hoist_block->id().ToInt()); |
1355 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); | 1365 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); |
1356 block = hoist_block; | 1366 block = hoist_block; |
1357 hoist_block = GetPreHeader(hoist_block); | 1367 hoist_block = GetHoistBlock(hoist_block); |
1358 } while (hoist_block && | 1368 } while (hoist_block && |
1359 hoist_block->dominator_depth() >= min_block->dominator_depth()); | 1369 hoist_block->dominator_depth() >= min_block->dominator_depth()); |
1360 } else if (scheduler_->flags_ & Scheduler::kSplitNodes) { | 1370 } else if (scheduler_->flags_ & Scheduler::kSplitNodes) { |
1361 // Split the {node} if beneficial and return the new {block} for it. | 1371 // Split the {node} if beneficial and return the new {block} for it. |
1362 block = SplitNode(block, node); | 1372 block = SplitNode(block, node); |
1363 } | 1373 } |
1364 | 1374 |
1365 // Schedule the node or a floating control structure. | 1375 // Schedule the node or a floating control structure. |
1366 if (IrOpcode::IsMergeOpcode(node->opcode())) { | 1376 if (IrOpcode::IsMergeOpcode(node->opcode())) { |
1367 ScheduleFloatingControl(block, node); | 1377 ScheduleFloatingControl(block, node); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 Trace(" cloning #%d:%s for B%d\n", use_node->id(), | 1468 Trace(" cloning #%d:%s for B%d\n", use_node->id(), |
1459 use_node->op()->mnemonic(), use_block->id().ToInt()); | 1469 use_node->op()->mnemonic(), use_block->id().ToInt()); |
1460 scheduler_->schedule_queue_.push(use_node); | 1470 scheduler_->schedule_queue_.push(use_node); |
1461 } | 1471 } |
1462 } | 1472 } |
1463 edge.UpdateTo(use_node); | 1473 edge.UpdateTo(use_node); |
1464 } | 1474 } |
1465 return block; | 1475 return block; |
1466 } | 1476 } |
1467 | 1477 |
1468 BasicBlock* GetPreHeader(BasicBlock* block) { | 1478 BasicBlock* GetHoistBlock(BasicBlock* block) { |
1469 if (block->IsLoopHeader()) { | 1479 if (block->IsLoopHeader()) return block->dominator(); |
1470 return block->dominator(); | 1480 // We have to check to make sure that the {block} dominates all |
1471 } else if (block->loop_header() != NULL) { | 1481 // of the outgoing blocks. If it doesn't, then there is a path |
1472 return block->loop_header()->dominator(); | 1482 // out of the loop which does not execute this {block}, so we |
1473 } else { | 1483 // can't hoist operations from this {block} out of the loop, as |
1474 return NULL; | 1484 // that would introduce additional computations. |
| 1485 if (BasicBlock* header_block = block->loop_header()) { |
| 1486 for (BasicBlock* outgoing_block : |
| 1487 scheduler_->special_rpo_->GetOutgoingBlocks(header_block)) { |
| 1488 if (BasicBlock::GetCommonDominator(block, outgoing_block) != block) { |
| 1489 return nullptr; |
| 1490 } |
| 1491 } |
| 1492 return header_block->dominator(); |
1475 } | 1493 } |
| 1494 return nullptr; |
1476 } | 1495 } |
1477 | 1496 |
1478 BasicBlock* GetCommonDominatorOfUses(Node* node) { | 1497 BasicBlock* GetCommonDominatorOfUses(Node* node) { |
1479 BasicBlock* block = nullptr; | 1498 BasicBlock* block = nullptr; |
1480 for (Edge edge : node->use_edges()) { | 1499 for (Edge edge : node->use_edges()) { |
1481 BasicBlock* use_block = GetBlockForUse(edge); | 1500 BasicBlock* use_block = GetBlockForUse(edge); |
1482 block = block == NULL ? use_block : use_block == NULL | 1501 block = block == NULL ? use_block : use_block == NULL |
1483 ? block | 1502 ? block |
1484 : BasicBlock::GetCommonDominator( | 1503 : BasicBlock::GetCommonDominator( |
1485 block, use_block); | 1504 block, use_block); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1660 for (Node* const node : *nodes) { | 1679 for (Node* const node : *nodes) { |
1661 schedule_->SetBlockForNode(to, node); | 1680 schedule_->SetBlockForNode(to, node); |
1662 scheduled_nodes_[to->id().ToSize()].push_back(node); | 1681 scheduled_nodes_[to->id().ToSize()].push_back(node); |
1663 } | 1682 } |
1664 nodes->clear(); | 1683 nodes->clear(); |
1665 } | 1684 } |
1666 | 1685 |
1667 } // namespace compiler | 1686 } // namespace compiler |
1668 } // namespace internal | 1687 } // namespace internal |
1669 } // namespace v8 | 1688 } // namespace v8 |
OLD | NEW |