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 |