Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(20)

Side by Side Diff: src/compiler/scheduler.cc

Issue 958533002: [turbofan] Don't introduce additional computation when hoisting out of loops. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/unittests/compiler/scheduler-unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | test/unittests/compiler/scheduler-unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698