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