Chromium Code Reviews| 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 <deque> | 5 #include <deque> |
| 6 #include <queue> | 6 #include <queue> |
| 7 | 7 |
| 8 #include "src/compiler/scheduler.h" | 8 #include "src/compiler/scheduler.h" |
| 9 | 9 |
| 10 #include "src/bit-vector.h" | 10 #include "src/bit-vector.h" |
| (...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 577 #if DEBUG | 577 #if DEBUG |
| 578 if (FLAG_trace_turbo_scheduler) PrintRPO(); | 578 if (FLAG_trace_turbo_scheduler) PrintRPO(); |
| 579 VerifySpecialRPO(); | 579 VerifySpecialRPO(); |
| 580 #endif | 580 #endif |
| 581 } | 581 } |
| 582 | 582 |
| 583 private: | 583 private: |
| 584 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree. | 584 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree. |
| 585 friend class Scheduler; | 585 friend class Scheduler; |
| 586 | 586 |
| 587 // Numbering for BasicBlockData.rpo_number_ for this block traversal: | 587 // Numbering for BasicBlock::rpo_number for this block traversal: |
| 588 static const int kBlockOnStack = -2; | 588 static const int kBlockOnStack = -2; |
| 589 static const int kBlockVisited1 = -3; | 589 static const int kBlockVisited1 = -3; |
| 590 static const int kBlockVisited2 = -4; | 590 static const int kBlockVisited2 = -4; |
| 591 static const int kBlockUnvisited1 = -1; | 591 static const int kBlockUnvisited1 = -1; |
| 592 static const int kBlockUnvisited2 = kBlockVisited1; | 592 static const int kBlockUnvisited2 = kBlockVisited1; |
| 593 | 593 |
| 594 struct SpecialRPOStackFrame { | 594 struct SpecialRPOStackFrame { |
| 595 BasicBlock* block; | 595 BasicBlock* block; |
| 596 size_t index; | 596 size_t index; |
| 597 }; | 597 }; |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 // mutating any existing order so that the result is still valid. | 667 // mutating any existing order so that the result is still valid. |
| 668 void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) { | 668 void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) { |
| 669 // RPO should not have been serialized for this schedule yet. | 669 // RPO should not have been serialized for this schedule yet. |
| 670 CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number()); | 670 CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number()); |
| 671 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); | 671 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); |
| 672 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); | 672 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); |
| 673 | 673 |
| 674 // Find correct insertion point within existing order. | 674 // Find correct insertion point within existing order. |
| 675 BlockList* insert_head = order_->FindForBlock(entry); | 675 BlockList* insert_head = order_->FindForBlock(entry); |
| 676 BlockList* insert_tail = insert_head == NULL ? NULL : insert_head->next; | 676 BlockList* insert_tail = insert_head == NULL ? NULL : insert_head->next; |
| 677 BlockList* order = insert_tail; | |
| 677 | 678 |
| 678 // Perform an iterative RPO traversal using an explicit stack, | 679 // Perform an iterative RPO traversal using an explicit stack, |
| 679 // recording backedges that form cycles. O(|B|). | 680 // recording backedges that form cycles. O(|B|). |
| 680 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone_); | 681 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone_); |
| 681 SpecialRPOStackFrame* stack = zone_->NewArray<SpecialRPOStackFrame>( | 682 SpecialRPOStackFrame* stack = zone_->NewArray<SpecialRPOStackFrame>( |
| 682 static_cast<int>(schedule_->BasicBlockCount())); | 683 static_cast<int>(schedule_->BasicBlockCount())); |
| 683 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); | 684 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); |
| 684 int num_loops = 0; | 685 int num_loops = 0; |
| 685 | 686 |
| 686 while (stack_depth > 0) { | 687 while (stack_depth > 0) { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 701 // Assign a new loop number to the header if it doesn't have one. | 702 // Assign a new loop number to the header if it doesn't have one. |
| 702 SetLoopNumber(succ, num_loops++); | 703 SetLoopNumber(succ, num_loops++); |
| 703 } | 704 } |
| 704 } else { | 705 } else { |
| 705 // Push the successor onto the stack. | 706 // Push the successor onto the stack. |
| 706 DCHECK(succ->rpo_number() == kBlockUnvisited1); | 707 DCHECK(succ->rpo_number() == kBlockUnvisited1); |
| 707 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); | 708 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); |
| 708 } | 709 } |
| 709 } else { | 710 } else { |
| 710 // Finished with all successors; pop the stack and add the block. | 711 // Finished with all successors; pop the stack and add the block. |
| 711 insert_tail = insert_tail->Add(zone_, frame->block); | 712 order = order->Add(zone_, frame->block); |
| 712 frame->block->set_rpo_number(kBlockVisited1); | 713 frame->block->set_rpo_number(kBlockVisited1); |
| 713 stack_depth--; | 714 stack_depth--; |
| 714 } | 715 } |
| 715 } | 716 } |
| 716 | 717 |
| 717 // Insert the result into any existing order. | |
| 718 if (insert_head == NULL) { | |
| 719 order_ = insert_tail; | |
| 720 } else { | |
| 721 insert_head->next = insert_tail->next; | |
| 722 } | |
| 723 | |
| 724 // If no loops were encountered, then the order we computed was correct. | 718 // If no loops were encountered, then the order we computed was correct. |
| 725 if (num_loops != 0) { | 719 if (num_loops != 0) { |
| 726 // Otherwise, compute the loop information from the backedges in order | 720 // Otherwise, compute the loop information from the backedges in order |
| 727 // to perform a traversal that groups loop bodies together. | 721 // to perform a traversal that groups loop bodies together. |
| 728 ComputeLoopInfo(stack, num_loops, &backedges); | 722 ComputeLoopInfo(stack, num_loops, &backedges); |
| 729 | 723 |
| 730 // Initialize the "loop stack". Note the entry could be a loop header. | 724 // Initialize the "loop stack". Note the entry could be a loop header. |
| 731 LoopInfo* loop = | 725 LoopInfo* loop = |
| 732 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL; | 726 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL; |
| 733 order_ = NULL; | 727 order = NULL; |
| 734 | 728 |
| 735 // Perform an iterative post-order traversal, visiting loop bodies before | 729 // Perform an iterative post-order traversal, visiting loop bodies before |
| 736 // edges that lead out of loops. Visits each block once, but linking loop | 730 // edges that lead out of loops. Visits each block once, but linking loop |
| 737 // sections together is linear in the loop size, so overall is | 731 // sections together is linear in the loop size, so overall is |
| 738 // O(|B| + max(loop_depth) * max(|loop|)) | 732 // O(|B| + max(loop_depth) * max(|loop|)) |
| 739 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); | 733 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); |
| 740 while (stack_depth > 0) { | 734 while (stack_depth > 0) { |
| 741 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); | 735 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); |
| 742 BasicBlock* block = frame->block; | 736 BasicBlock* block = frame->block; |
| 743 BasicBlock* succ = NULL; | 737 BasicBlock* succ = NULL; |
| 744 | 738 |
| 745 if (frame->index < block->SuccessorCount()) { | 739 if (frame->index < block->SuccessorCount()) { |
| 746 // Process the next normal successor. | 740 // Process the next normal successor. |
| 747 succ = block->SuccessorAt(frame->index++); | 741 succ = block->SuccessorAt(frame->index++); |
| 748 } else if (HasLoopNumber(block)) { | 742 } else if (HasLoopNumber(block)) { |
| 749 // Process additional outgoing edges from the loop header. | 743 // Process additional outgoing edges from the loop header. |
| 750 if (block->rpo_number() == kBlockOnStack) { | 744 if (block->rpo_number() == kBlockOnStack) { |
| 751 // Finish the loop body the first time the header is left on the | 745 // Finish the loop body the first time the header is left on the |
| 752 // stack. | 746 // stack. |
| 753 DCHECK(loop != NULL && loop->header == block); | 747 DCHECK(loop != NULL && loop->header == block); |
| 754 loop->start = order_->Add(zone_, block); | 748 loop->start = order->Add(zone_, block); |
| 755 order_ = loop->end; | 749 order = loop->end; |
| 756 block->set_rpo_number(kBlockVisited2); | 750 block->set_rpo_number(kBlockVisited2); |
| 757 // Pop the loop stack and continue visiting outgoing edges within | 751 // Pop the loop stack and continue visiting outgoing edges within |
| 758 // the context of the outer loop, if any. | 752 // the context of the outer loop, if any. |
| 759 loop = loop->prev; | 753 loop = loop->prev; |
| 760 // We leave the loop header on the stack; the rest of this iteration | 754 // We leave the loop header on the stack; the rest of this iteration |
| 761 // and later iterations will go through its outgoing edges list. | 755 // and later iterations will go through its outgoing edges list. |
| 762 } | 756 } |
| 763 | 757 |
| 764 // Use the next outgoing edge if there are any. | 758 // Use the next outgoing edge if there are any. |
| 765 int outgoing_index = | 759 int outgoing_index = |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 782 // The successor is not in the current loop or any nested loop. | 776 // The successor is not in the current loop or any nested loop. |
| 783 // Add it to the outgoing edges of this loop and visit it later. | 777 // Add it to the outgoing edges of this loop and visit it later. |
| 784 loop->AddOutgoing(zone_, succ); | 778 loop->AddOutgoing(zone_, succ); |
| 785 } else { | 779 } else { |
| 786 // Push the successor onto the stack. | 780 // Push the successor onto the stack. |
| 787 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); | 781 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); |
| 788 if (HasLoopNumber(succ)) { | 782 if (HasLoopNumber(succ)) { |
| 789 // Push the inner loop onto the loop stack. | 783 // Push the inner loop onto the loop stack. |
| 790 DCHECK(GetLoopNumber(succ) < num_loops); | 784 DCHECK(GetLoopNumber(succ) < num_loops); |
| 791 LoopInfo* next = &loops_[GetLoopNumber(succ)]; | 785 LoopInfo* next = &loops_[GetLoopNumber(succ)]; |
| 792 next->end = order_; | 786 next->end = order; |
| 793 next->prev = loop; | 787 next->prev = loop; |
| 794 loop = next; | 788 loop = next; |
| 795 } | 789 } |
| 796 } | 790 } |
| 797 } else { | 791 } else { |
| 798 // Finished with all successors of the current block. | 792 // Finished with all successors of the current block. |
| 799 if (HasLoopNumber(block)) { | 793 if (HasLoopNumber(block)) { |
| 800 // If we are going to pop a loop header, then add its entire body. | 794 // If we are going to pop a loop header, then add its entire body. |
| 801 LoopInfo* info = &loops_[GetLoopNumber(block)]; | 795 LoopInfo* info = &loops_[GetLoopNumber(block)]; |
| 802 for (BlockList* l = info->start; true; l = l->next) { | 796 for (BlockList* l = info->start; true; l = l->next) { |
| 803 if (l->next == info->end) { | 797 if (l->next == info->end) { |
| 804 l->next = order_; | 798 l->next = order; |
| 805 info->end = order_; | 799 info->end = order; |
| 806 break; | 800 break; |
| 807 } | 801 } |
| 808 } | 802 } |
| 809 order_ = info->start; | 803 order = info->start; |
| 810 } else { | 804 } else { |
| 811 // Pop a single node off the stack and add it to the order. | 805 // Pop a single node off the stack and add it to the order. |
| 812 order_ = order_->Add(zone_, block); | 806 order = order->Add(zone_, block); |
| 813 block->set_rpo_number(kBlockVisited2); | 807 block->set_rpo_number(kBlockVisited2); |
| 814 } | 808 } |
| 815 stack_depth--; | 809 stack_depth--; |
| 816 } | 810 } |
| 817 } | 811 } |
| 818 } | 812 } |
| 819 | 813 |
| 814 // Insert result into existing order. | |
| 815 if (insert_head == NULL) { | |
| 816 order_ = order; | |
| 817 } else { | |
| 818 insert_head->next = order->next; | |
| 819 } | |
| 820 | |
| 820 // Compute the correct loop headers and set the correct loop ends. | 821 // Compute the correct loop headers and set the correct loop ends. |
| 821 LoopInfo* current_loop = NULL; | 822 LoopInfo* current_loop = NULL; |
| 822 BasicBlock* current_header = NULL; | 823 BasicBlock* current_header = entry->loop_header(); |
| 823 int loop_depth = 0; | 824 int32_t loop_depth = entry->loop_depth(); |
| 824 for (BlockList* l = order_; l != NULL; l = l->next) { | 825 for (BlockList* l = order; l != insert_tail; l = l->next) { |
| 825 BasicBlock* current = l->block; | 826 BasicBlock* current = l->block; |
| 826 | 827 |
| 828 // Reset BasicBlock::rpo_number again. | |
| 829 current->set_rpo_number(-1); | |
|
Jarin
2014/11/05 01:03:56
Could we use the constant defined above? (kBlockUn
Michael Starzinger
2014/11/05 10:18:40
Done.
| |
| 830 | |
| 827 // Finish the previous loop(s) if we just exited them. | 831 // Finish the previous loop(s) if we just exited them. |
| 828 while (current_header != NULL && current == current_header->loop_end()) { | 832 while (current_header != NULL && current == current_header->loop_end()) { |
| 829 DCHECK(current_header->IsLoopHeader()); | 833 DCHECK(current_header->IsLoopHeader()); |
| 830 DCHECK(current_loop != NULL); | 834 DCHECK(current_loop != NULL); |
| 831 current_loop = current_loop->prev; | 835 current_loop = current_loop->prev; |
| 832 current_header = current_loop == NULL ? NULL : current_loop->header; | 836 current_header = current_loop == NULL ? NULL : current_loop->header; |
| 833 --loop_depth; | 837 --loop_depth; |
| 834 } | 838 } |
| 835 current->set_loop_header(current_header); | 839 current->set_loop_header(current_header); |
| 836 | 840 |
| (...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1423 if (FLAG_trace_turbo_scheduler) { | 1427 if (FLAG_trace_turbo_scheduler) { |
| 1424 OFStream os(stdout); | 1428 OFStream os(stdout); |
| 1425 os << "Schedule before control flow fusion:\n" << *schedule_; | 1429 os << "Schedule before control flow fusion:\n" << *schedule_; |
| 1426 } | 1430 } |
| 1427 | 1431 |
| 1428 // Iterate on phase 1: Build control-flow graph. | 1432 // Iterate on phase 1: Build control-flow graph. |
| 1429 CFGBuilder cfg_builder(zone_, this); | 1433 CFGBuilder cfg_builder(zone_, this); |
| 1430 cfg_builder.Run(block, node); | 1434 cfg_builder.Run(block, node); |
| 1431 | 1435 |
| 1432 // Iterate on phase 2: Compute special RPO and dominator tree. | 1436 // Iterate on phase 2: Compute special RPO and dominator tree. |
| 1437 special_rpo_->UpdateSpecialRPO(block, schedule_->block(node)); | |
| 1433 // TODO(mstarzinger): Currently "iterate on" means "re-run". Fix that. | 1438 // TODO(mstarzinger): Currently "iterate on" means "re-run". Fix that. |
| 1434 for (BasicBlock* block : schedule_->all_blocks_) { | 1439 for (BasicBlock* block : schedule_->all_blocks_) { |
| 1435 block->set_rpo_number(-1); | |
| 1436 block->set_dominator_depth(-1); | 1440 block->set_dominator_depth(-1); |
| 1437 block->set_dominator(NULL); | 1441 block->set_dominator(NULL); |
| 1438 } | 1442 } |
| 1439 special_rpo_->UpdateSpecialRPO(block, schedule_->block(node)); | |
| 1440 GenerateImmediateDominatorTree(); | 1443 GenerateImmediateDominatorTree(); |
| 1441 | 1444 |
| 1442 // Move previously planned nodes. | 1445 // Move previously planned nodes. |
| 1443 // TODO(mstarzinger): Improve that by supporting bulk moves. | 1446 // TODO(mstarzinger): Improve that by supporting bulk moves. |
| 1444 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); | 1447 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); |
| 1445 MovePlannedNodes(block, schedule_->block(node)); | 1448 MovePlannedNodes(block, schedule_->block(node)); |
| 1446 | 1449 |
| 1447 if (FLAG_trace_turbo_scheduler) { | 1450 if (FLAG_trace_turbo_scheduler) { |
| 1448 OFStream os(stdout); | 1451 OFStream os(stdout); |
| 1449 os << "Schedule after control flow fusion:\n" << *schedule_; | 1452 os << "Schedule after control flow fusion:\n" << *schedule_; |
| 1450 } | 1453 } |
| 1451 } | 1454 } |
| 1452 | 1455 |
| 1453 | 1456 |
| 1454 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) { | 1457 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) { |
| 1455 Trace("Move planned nodes from B%d to B%d\n", from->id().ToInt(), | 1458 Trace("Move planned nodes from B%d to B%d\n", from->id().ToInt(), |
| 1456 to->id().ToInt()); | 1459 to->id().ToInt()); |
| 1457 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]); | 1460 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]); |
| 1458 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { | 1461 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { |
| 1459 schedule_->SetBlockForNode(to, *i); | 1462 schedule_->SetBlockForNode(to, *i); |
| 1460 scheduled_nodes_[to->id().ToSize()].push_back(*i); | 1463 scheduled_nodes_[to->id().ToSize()].push_back(*i); |
| 1461 } | 1464 } |
| 1462 nodes->clear(); | 1465 nodes->clear(); |
| 1463 } | 1466 } |
| 1464 | 1467 |
| 1465 } // namespace compiler | 1468 } // namespace compiler |
| 1466 } // namespace internal | 1469 } // namespace internal |
| 1467 } // namespace v8 | 1470 } // namespace v8 |
| OLD | NEW |