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

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

Issue 696363002: Make special RPO computation iterative during scheduling. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebased. Created 6 years, 1 month 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 | Annotate | Revision Log
« no previous file with comments | « src/compiler/scheduler.h ('k') | test/cctest/compiler/test-instruction.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 <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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 Scheduler scheduler(zone_scope.zone(), graph, schedule); 45 Scheduler scheduler(zone_scope.zone(), graph, schedule);
46 46
47 scheduler.BuildCFG(); 47 scheduler.BuildCFG();
48 scheduler.ComputeSpecialRPONumbering(); 48 scheduler.ComputeSpecialRPONumbering();
49 scheduler.GenerateImmediateDominatorTree(); 49 scheduler.GenerateImmediateDominatorTree();
50 50
51 scheduler.PrepareUses(); 51 scheduler.PrepareUses();
52 scheduler.ScheduleEarly(); 52 scheduler.ScheduleEarly();
53 scheduler.ScheduleLate(); 53 scheduler.ScheduleLate();
54 54
55 scheduler.SealFinalSchedule();
56
55 return schedule; 57 return schedule;
56 } 58 }
57 59
58 60
59 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { 61 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() {
60 SchedulerData def = {schedule_->start(), 0, false, false, kUnknown}; 62 SchedulerData def = {schedule_->start(), 0, false, false, kUnknown};
61 return def; 63 return def;
62 } 64 }
63 65
64 66
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
204 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), 206 node->op()->mnemonic(), from->id(), from->op()->mnemonic(),
205 GetData(node)->unscheduled_count_); 207 GetData(node)->unscheduled_count_);
206 } 208 }
207 if (GetData(node)->unscheduled_count_ == 0) { 209 if (GetData(node)->unscheduled_count_ == 0) {
208 Trace(" newly eligible #%d:%s\n", node->id(), node->op()->mnemonic()); 210 Trace(" newly eligible #%d:%s\n", node->id(), node->op()->mnemonic());
209 schedule_queue_.push(node); 211 schedule_queue_.push(node);
210 } 212 }
211 } 213 }
212 214
213 215
214 int Scheduler::GetRPONumber(BasicBlock* block) {
215 DCHECK(block->rpo_number() >= 0 &&
216 block->rpo_number() < static_cast<int>(schedule_->rpo_order_.size()));
217 DCHECK(schedule_->rpo_order_[block->rpo_number()] == block);
218 return block->rpo_number();
219 }
220
221
222 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) { 216 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
223 while (b1 != b2) { 217 while (b1 != b2) {
224 int b1_rpo = GetRPONumber(b1); 218 int32_t b1_depth = b1->dominator_depth();
225 int b2_rpo = GetRPONumber(b2); 219 int32_t b2_depth = b2->dominator_depth();
226 DCHECK(b1_rpo != b2_rpo); 220 if (b1_depth < b2_depth) {
227 if (b1_rpo < b2_rpo) {
228 b2 = b2->dominator(); 221 b2 = b2->dominator();
229 } else { 222 } else {
230 b1 = b1->dominator(); 223 b1 = b1->dominator();
231 } 224 }
232 } 225 }
233 return b1; 226 return b1;
234 } 227 }
235 228
236 229
237 // ----------------------------------------------------------------------------- 230 // -----------------------------------------------------------------------------
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 // a RPO of the graph where loop bodies are contiguous. Properties: 515 // a RPO of the graph where loop bodies are contiguous. Properties:
523 // 1. If block A is a predecessor of B, then A appears before B in the order, 516 // 1. If block A is a predecessor of B, then A appears before B in the order,
524 // unless B is a loop header and A is in the loop headed at B 517 // unless B is a loop header and A is in the loop headed at B
525 // (i.e. A -> B is a backedge). 518 // (i.e. A -> B is a backedge).
526 // => If block A dominates block B, then A appears before B in the order. 519 // => If block A dominates block B, then A appears before B in the order.
527 // => If block A is a loop header, A appears before all blocks in the loop 520 // => If block A is a loop header, A appears before all blocks in the loop
528 // headed at A. 521 // headed at A.
529 // 2. All loops are contiguous in the order (i.e. no intervening blocks that 522 // 2. All loops are contiguous in the order (i.e. no intervening blocks that
530 // do not belong to the loop.) 523 // do not belong to the loop.)
531 // Note a simple RPO traversal satisfies (1) but not (2). 524 // Note a simple RPO traversal satisfies (1) but not (2).
532 class SpecialRPONumberer { 525 class SpecialRPONumberer : public ZoneObject {
533 public: 526 public:
534 SpecialRPONumberer(Zone* zone, Schedule* schedule) 527 SpecialRPONumberer(Zone* zone, Schedule* schedule)
535 : zone_(zone), schedule_(schedule) {} 528 : zone_(zone),
529 schedule_(schedule),
530 order_(NULL),
531 loops_(zone),
532 beyond_end_(NULL) {}
536 533
534 // Computes the special reverse-post-order for the main control flow graph,
535 // that is for the graph spanned between the schedule's start and end blocks.
537 void ComputeSpecialRPO() { 536 void ComputeSpecialRPO() {
538 // RPO should not have been computed for this schedule yet. 537 DCHECK_EQ(NULL, order_); // Main order does not exist yet.
538 // TODO(mstarzinger): Should use Schedule::end() after tests are fixed.
539 ComputeAndInsertSpecialRPO(schedule_->start(), NULL);
540 }
541
542 // Computes the special reverse-post-order for a partial control flow graph,
543 // that is for the graph spanned between the given {entry} and {end} blocks,
544 // then updates the existing ordering with this new information.
545 void UpdateSpecialRPO(BasicBlock* entry, BasicBlock* end) {
546 DCHECK_NE(NULL, order_); // Main order to be updated is present.
547 ComputeAndInsertSpecialRPO(entry, end);
548 }
549
550 // Serialize the previously computed order as an assembly order (non-deferred
551 // code first, deferred code afterwards) into the final schedule.
552 void SerializeAOIntoSchedule() {
553 int32_t number = 0;
554 for (BlockList* l = order_; l != NULL; l = l->next) {
555 if (l->block->deferred()) continue;
556 l->block->set_ao_number(number++);
557 }
558 for (BlockList* l = order_; l != NULL; l = l->next) {
559 if (!l->block->deferred()) continue;
560 l->block->set_ao_number(number++);
561 }
562 }
563
564 // Serialize the previously computed order as a special reverse-post-order
565 // numbering for basic blocks into the final schedule.
566 void SerializeRPOIntoSchedule() {
567 int32_t number = 0;
568 for (BlockList* l = order_; l != NULL; l = l->next) {
569 l->block->set_rpo_number(number++);
570 schedule_->rpo_order()->push_back(l->block);
571 }
572 BeyondEndSentinel()->set_rpo_number(number);
573 }
574
575 // Print and verify the special reverse-post-order.
576 void PrintAndVerifySpecialRPO() {
577 #if DEBUG
578 if (FLAG_trace_turbo_scheduler) PrintRPO();
579 VerifySpecialRPO();
580 #endif
581 }
582
583 private:
584 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree.
585 friend class Scheduler;
586
587 // Numbering for BasicBlockData.rpo_number_ for this block traversal:
588 static const int kBlockOnStack = -2;
589 static const int kBlockVisited1 = -3;
590 static const int kBlockVisited2 = -4;
591 static const int kBlockUnvisited1 = -1;
592 static const int kBlockUnvisited2 = kBlockVisited1;
593
594 struct SpecialRPOStackFrame {
595 BasicBlock* block;
596 size_t index;
597 };
598
599 struct BlockList {
600 BasicBlock* block;
601 BlockList* next;
602
603 BlockList* Add(Zone* zone, BasicBlock* b) {
604 BlockList* list = static_cast<BlockList*>(zone->New(sizeof(BlockList)));
605 list->block = b;
606 list->next = this;
607 return list;
608 }
609
610 BlockList* FindForBlock(BasicBlock* b) {
611 for (BlockList* l = this; l != NULL; l = l->next) {
612 if (l->block == b) return l;
613 }
614 return NULL;
615 }
616 };
617
618 struct LoopInfo {
619 BasicBlock* header;
620 ZoneList<BasicBlock*>* outgoing;
621 BitVector* members;
622 LoopInfo* prev;
623 BlockList* end;
624 BlockList* start;
625
626 void AddOutgoing(Zone* zone, BasicBlock* block) {
627 if (outgoing == NULL) {
628 outgoing = new (zone) ZoneList<BasicBlock*>(2, zone);
629 }
630 outgoing->Add(block, zone);
631 }
632 };
633
634 int Push(SpecialRPOStackFrame* stack, int depth, BasicBlock* child,
635 int unvisited) {
636 if (child->rpo_number() == unvisited) {
637 stack[depth].block = child;
638 stack[depth].index = 0;
639 child->set_rpo_number(kBlockOnStack);
640 return depth + 1;
641 }
642 return depth;
643 }
644
645 // We are hijacking the {ao_number} to enumerate loops temporarily. Note that
646 // these numbers are only valid within this class.
647 static int GetLoopNumber(BasicBlock* block) { return block->ao_number(); }
648 static void SetLoopNumber(BasicBlock* block, int loop_number) {
649 return block->set_ao_number(loop_number);
650 }
651 static bool HasLoopNumber(BasicBlock* block) {
652 return block->ao_number() >= 0;
653 }
654
655 // TODO(mstarzinger): We only need this special sentinel because some tests
656 // use the schedule's end block in actual control flow (e.g. with end having
657 // successors). Once this has been cleaned up we can use the end block here.
658 BasicBlock* BeyondEndSentinel() {
659 if (beyond_end_ == NULL) {
660 BasicBlock::Id id = BasicBlock::Id::FromInt(-1);
661 beyond_end_ = new (schedule_->zone()) BasicBlock(schedule_->zone(), id);
662 }
663 return beyond_end_;
664 }
665
666 // Compute special RPO for the control flow graph between {entry} and {end},
667 // mutating any existing order so that the result is still valid.
668 void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) {
669 // RPO should not have been serialized for this schedule yet.
670 CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number());
539 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); 671 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number());
540 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); 672 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size()));
541 673
674 // Find correct insertion point within existing order.
675 BlockList* insert_before = order_->FindForBlock(entry);
676 BlockList* insert_after = insert_before ? insert_before->next : NULL;
677
542 // Perform an iterative RPO traversal using an explicit stack, 678 // Perform an iterative RPO traversal using an explicit stack,
543 // recording backedges that form cycles. O(|B|). 679 // recording backedges that form cycles. O(|B|).
544 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone_); 680 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone_);
545 SpecialRPOStackFrame* stack = zone_->NewArray<SpecialRPOStackFrame>( 681 SpecialRPOStackFrame* stack = zone_->NewArray<SpecialRPOStackFrame>(
546 static_cast<int>(schedule_->BasicBlockCount())); 682 static_cast<int>(schedule_->BasicBlockCount()));
547 BasicBlock* entry = schedule_->start();
548 BlockList* order = NULL;
549 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); 683 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1);
550 int num_loops = 0; 684 int num_loops = 0;
551 685
552 while (stack_depth > 0) { 686 while (stack_depth > 0) {
553 int current = stack_depth - 1; 687 int current = stack_depth - 1;
554 SpecialRPOStackFrame* frame = stack + current; 688 SpecialRPOStackFrame* frame = stack + current;
555 689
556 if (frame->index < frame->block->SuccessorCount()) { 690 if (frame->block != end &&
691 frame->index < frame->block->SuccessorCount()) {
557 // Process the next successor. 692 // Process the next successor.
558 BasicBlock* succ = frame->block->SuccessorAt(frame->index++); 693 BasicBlock* succ = frame->block->SuccessorAt(frame->index++);
559 if (succ->rpo_number() == kBlockVisited1) continue; 694 if (succ->rpo_number() == kBlockVisited1) continue;
560 if (succ->rpo_number() == kBlockOnStack) { 695 if (succ->rpo_number() == kBlockOnStack) {
561 // The successor is on the stack, so this is a backedge (cycle). 696 // The successor is on the stack, so this is a backedge (cycle).
562 backedges.Add( 697 backedges.Add(
563 std::pair<BasicBlock*, size_t>(frame->block, frame->index - 1), 698 std::pair<BasicBlock*, size_t>(frame->block, frame->index - 1),
564 zone_); 699 zone_);
565 if (succ->loop_end() < 0) { 700 if (!HasLoopNumber(succ)) {
566 // Assign a new loop number to the header if it doesn't have one. 701 // Assign a new loop number to the header if it doesn't have one.
567 succ->set_loop_end(num_loops++); 702 SetLoopNumber(succ, num_loops++);
568 } 703 }
569 } else { 704 } else {
570 // Push the successor onto the stack. 705 // Push the successor onto the stack.
571 DCHECK(succ->rpo_number() == kBlockUnvisited1); 706 DCHECK(succ->rpo_number() == kBlockUnvisited1);
572 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); 707 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1);
573 } 708 }
574 } else { 709 } else {
575 // Finished with all successors; pop the stack and add the block. 710 // Finished with all successors; pop the stack and add the block.
576 order = order->Add(zone_, frame->block); 711 insert_after = insert_after->Add(zone_, frame->block);
577 frame->block->set_rpo_number(kBlockVisited1); 712 frame->block->set_rpo_number(kBlockVisited1);
578 stack_depth--; 713 stack_depth--;
579 } 714 }
580 } 715 }
581 716
717 // Insert the result into any existing order.
718 if (insert_before == NULL) {
719 order_ = insert_after;
720 } else {
721 // There already is a list element for the entry block in the list, hence
722 // we skip the first element of the sub-list to compensate duplication.
723 DCHECK_EQ(insert_before->block, insert_after->block);
724 insert_before->next = insert_after->next;
725 }
726
582 // If no loops were encountered, then the order we computed was correct. 727 // If no loops were encountered, then the order we computed was correct.
583 LoopInfo* loops = NULL;
584 if (num_loops != 0) { 728 if (num_loops != 0) {
585 // Otherwise, compute the loop information from the backedges in order 729 // Otherwise, compute the loop information from the backedges in order
586 // to perform a traversal that groups loop bodies together. 730 // to perform a traversal that groups loop bodies together.
587 loops = ComputeLoopInfo(stack, num_loops, schedule_->BasicBlockCount(), 731 ComputeLoopInfo(stack, num_loops, &backedges);
588 &backedges);
589 732
590 // Initialize the "loop stack". Note the entry could be a loop header. 733 // Initialize the "loop stack". Note the entry could be a loop header.
591 LoopInfo* loop = entry->IsLoopHeader() ? &loops[entry->loop_end()] : NULL; 734 LoopInfo* loop =
592 order = NULL; 735 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL;
736 order_ = NULL;
593 737
594 // Perform an iterative post-order traversal, visiting loop bodies before 738 // Perform an iterative post-order traversal, visiting loop bodies before
595 // edges that lead out of loops. Visits each block once, but linking loop 739 // edges that lead out of loops. Visits each block once, but linking loop
596 // sections together is linear in the loop size, so overall is 740 // sections together is linear in the loop size, so overall is
597 // O(|B| + max(loop_depth) * max(|loop|)) 741 // O(|B| + max(loop_depth) * max(|loop|))
598 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); 742 stack_depth = Push(stack, 0, entry, kBlockUnvisited2);
599 while (stack_depth > 0) { 743 while (stack_depth > 0) {
600 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); 744 SpecialRPOStackFrame* frame = stack + (stack_depth - 1);
601 BasicBlock* block = frame->block; 745 BasicBlock* block = frame->block;
602 BasicBlock* succ = NULL; 746 BasicBlock* succ = NULL;
603 747
604 if (frame->index < block->SuccessorCount()) { 748 if (frame->index < block->SuccessorCount()) {
605 // Process the next normal successor. 749 // Process the next normal successor.
606 succ = block->SuccessorAt(frame->index++); 750 succ = block->SuccessorAt(frame->index++);
607 } else if (block->IsLoopHeader()) { 751 } else if (HasLoopNumber(block)) {
608 // Process additional outgoing edges from the loop header. 752 // Process additional outgoing edges from the loop header.
609 if (block->rpo_number() == kBlockOnStack) { 753 if (block->rpo_number() == kBlockOnStack) {
610 // Finish the loop body the first time the header is left on the 754 // Finish the loop body the first time the header is left on the
611 // stack. 755 // stack.
612 DCHECK(loop != NULL && loop->header == block); 756 DCHECK(loop != NULL && loop->header == block);
613 loop->start = order->Add(zone_, block); 757 loop->start = order_->Add(zone_, block);
614 order = loop->end; 758 order_ = loop->end;
615 block->set_rpo_number(kBlockVisited2); 759 block->set_rpo_number(kBlockVisited2);
616 // Pop the loop stack and continue visiting outgoing edges within 760 // Pop the loop stack and continue visiting outgoing edges within
617 // the context of the outer loop, if any. 761 // the context of the outer loop, if any.
618 loop = loop->prev; 762 loop = loop->prev;
619 // We leave the loop header on the stack; the rest of this iteration 763 // We leave the loop header on the stack; the rest of this iteration
620 // and later iterations will go through its outgoing edges list. 764 // and later iterations will go through its outgoing edges list.
621 } 765 }
622 766
623 // Use the next outgoing edge if there are any. 767 // Use the next outgoing edge if there are any.
624 int outgoing_index = 768 int outgoing_index =
625 static_cast<int>(frame->index - block->SuccessorCount()); 769 static_cast<int>(frame->index - block->SuccessorCount());
626 LoopInfo* info = &loops[block->loop_end()]; 770 LoopInfo* info = &loops_[GetLoopNumber(block)];
627 DCHECK(loop != info); 771 DCHECK(loop != info);
628 if (info->outgoing != NULL && 772 if (info->outgoing != NULL &&
629 outgoing_index < info->outgoing->length()) { 773 outgoing_index < info->outgoing->length()) {
630 succ = info->outgoing->at(outgoing_index); 774 succ = info->outgoing->at(outgoing_index);
631 frame->index++; 775 frame->index++;
632 } 776 }
633 } 777 }
634 778
635 if (succ != NULL) { 779 if (succ != NULL) {
636 // Process the next successor. 780 // Process the next successor.
637 if (succ->rpo_number() == kBlockOnStack) continue; 781 if (succ->rpo_number() == kBlockOnStack) continue;
638 if (succ->rpo_number() == kBlockVisited2) continue; 782 if (succ->rpo_number() == kBlockVisited2) continue;
639 DCHECK(succ->rpo_number() == kBlockUnvisited2); 783 DCHECK(succ->rpo_number() == kBlockUnvisited2);
640 if (loop != NULL && !loop->members->Contains(succ->id().ToInt())) { 784 if (loop != NULL && !loop->members->Contains(succ->id().ToInt())) {
641 // The successor is not in the current loop or any nested loop. 785 // The successor is not in the current loop or any nested loop.
642 // Add it to the outgoing edges of this loop and visit it later. 786 // Add it to the outgoing edges of this loop and visit it later.
643 loop->AddOutgoing(zone_, succ); 787 loop->AddOutgoing(zone_, succ);
644 } else { 788 } else {
645 // Push the successor onto the stack. 789 // Push the successor onto the stack.
646 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); 790 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2);
647 if (succ->IsLoopHeader()) { 791 if (HasLoopNumber(succ)) {
648 // Push the inner loop onto the loop stack. 792 // Push the inner loop onto the loop stack.
649 DCHECK(succ->loop_end() >= 0 && succ->loop_end() < num_loops); 793 DCHECK(GetLoopNumber(succ) < num_loops);
650 LoopInfo* next = &loops[succ->loop_end()]; 794 LoopInfo* next = &loops_[GetLoopNumber(succ)];
651 next->end = order; 795 next->end = order_;
652 next->prev = loop; 796 next->prev = loop;
653 loop = next; 797 loop = next;
654 } 798 }
655 } 799 }
656 } else { 800 } else {
657 // Finished with all successors of the current block. 801 // Finished with all successors of the current block.
658 if (block->IsLoopHeader()) { 802 if (HasLoopNumber(block)) {
659 // If we are going to pop a loop header, then add its entire body. 803 // If we are going to pop a loop header, then add its entire body.
660 LoopInfo* info = &loops[block->loop_end()]; 804 LoopInfo* info = &loops_[GetLoopNumber(block)];
661 for (BlockList* l = info->start; true; l = l->next) { 805 for (BlockList* l = info->start; true; l = l->next) {
662 if (l->next == info->end) { 806 if (l->next == info->end) {
663 l->next = order; 807 l->next = order_;
664 info->end = order; 808 info->end = order_;
665 break; 809 break;
666 } 810 }
667 } 811 }
668 order = info->start; 812 order_ = info->start;
669 } else { 813 } else {
670 // Pop a single node off the stack and add it to the order. 814 // Pop a single node off the stack and add it to the order.
671 order = order->Add(zone_, block); 815 order_ = order_->Add(zone_, block);
672 block->set_rpo_number(kBlockVisited2); 816 block->set_rpo_number(kBlockVisited2);
673 } 817 }
674 stack_depth--; 818 stack_depth--;
675 } 819 }
676 } 820 }
677 } 821 }
678 822
679 // Construct the final order from the list.
680 BasicBlockVector* final_order = schedule_->rpo_order();
681 order->Serialize(final_order);
682
683 // Compute the correct loop headers and set the correct loop ends. 823 // Compute the correct loop headers and set the correct loop ends.
684 LoopInfo* current_loop = NULL; 824 LoopInfo* current_loop = NULL;
685 BasicBlock* current_header = NULL; 825 BasicBlock* current_header = NULL;
686 int loop_depth = 0; 826 int loop_depth = 0;
687 for (BasicBlockVectorIter i = final_order->begin(); i != final_order->end(); 827 for (BlockList* l = order_; l != NULL; l = l->next) {
688 ++i) { 828 BasicBlock* current = l->block;
689 BasicBlock* current = *i;
690 829
691 // Finish the previous loop(s) if we just exited them. 830 // Finish the previous loop(s) if we just exited them.
692 while (current_header != NULL && 831 while (current_header != NULL && current == current_header->loop_end()) {
693 current->rpo_number() >= current_header->loop_end()) {
694 DCHECK(current_header->IsLoopHeader()); 832 DCHECK(current_header->IsLoopHeader());
695 DCHECK(current_loop != NULL); 833 DCHECK(current_loop != NULL);
696 current_loop = current_loop->prev; 834 current_loop = current_loop->prev;
697 current_header = current_loop == NULL ? NULL : current_loop->header; 835 current_header = current_loop == NULL ? NULL : current_loop->header;
698 --loop_depth; 836 --loop_depth;
699 } 837 }
700 current->set_loop_header(current_header); 838 current->set_loop_header(current_header);
701 839
702 // Push a new loop onto the stack if this loop is a loop header. 840 // Push a new loop onto the stack if this loop is a loop header.
703 if (current->IsLoopHeader()) { 841 if (HasLoopNumber(current)) {
704 loop_depth++; 842 loop_depth++;
705 current_loop = &loops[current->loop_end()]; 843 current_loop = &loops_[GetLoopNumber(current)];
706 BlockList* end = current_loop->end; 844 BlockList* end = current_loop->end;
707 current->set_loop_end(end == NULL 845 current->set_loop_end(end == NULL ? BeyondEndSentinel() : end->block);
708 ? static_cast<int>(final_order->size())
709 : end->block->rpo_number());
710 current_header = current_loop->header; 846 current_header = current_loop->header;
711 Trace("B%d is a loop header, increment loop depth to %d\n", 847 Trace("B%d is a loop header, increment loop depth to %d\n",
712 current->id().ToInt(), loop_depth); 848 current->id().ToInt(), loop_depth);
713 } 849 }
714 850
715 current->set_loop_depth(loop_depth); 851 current->set_loop_depth(loop_depth);
716 852
717 if (current->loop_header() == NULL) { 853 if (current->loop_header() == NULL) {
718 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), 854 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(),
719 current->loop_depth()); 855 current->loop_depth());
720 } else { 856 } else {
721 Trace("B%d has loop header B%d, (depth == %d)\n", current->id().ToInt(), 857 Trace("B%d has loop header B%d, (depth == %d)\n", current->id().ToInt(),
722 current->loop_header()->id().ToInt(), current->loop_depth()); 858 current->loop_header()->id().ToInt(), current->loop_depth());
723 } 859 }
724 } 860 }
725
726 // Compute the assembly order (non-deferred code first, deferred code
727 // afterwards).
728 int32_t number = 0;
729 for (auto block : *final_order) {
730 if (block->deferred()) continue;
731 block->set_ao_number(number++);
732 }
733 for (auto block : *final_order) {
734 if (!block->deferred()) continue;
735 block->set_ao_number(number++);
736 }
737
738 #if DEBUG
739 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order);
740 VerifySpecialRPO(num_loops, loops, final_order);
741 #endif
742 }
743
744 private:
745 // Numbering for BasicBlockData.rpo_number_ for this block traversal:
746 static const int kBlockOnStack = -2;
747 static const int kBlockVisited1 = -3;
748 static const int kBlockVisited2 = -4;
749 static const int kBlockUnvisited1 = -1;
750 static const int kBlockUnvisited2 = kBlockVisited1;
751
752 struct SpecialRPOStackFrame {
753 BasicBlock* block;
754 size_t index;
755 };
756
757 struct BlockList {
758 BasicBlock* block;
759 BlockList* next;
760
761 BlockList* Add(Zone* zone, BasicBlock* b) {
762 BlockList* list = static_cast<BlockList*>(zone->New(sizeof(BlockList)));
763 list->block = b;
764 list->next = this;
765 return list;
766 }
767
768 void Serialize(BasicBlockVector* final_order) {
769 for (BlockList* l = this; l != NULL; l = l->next) {
770 l->block->set_rpo_number(static_cast<int>(final_order->size()));
771 final_order->push_back(l->block);
772 }
773 }
774 };
775
776 struct LoopInfo {
777 BasicBlock* header;
778 ZoneList<BasicBlock*>* outgoing;
779 BitVector* members;
780 LoopInfo* prev;
781 BlockList* end;
782 BlockList* start;
783
784 void AddOutgoing(Zone* zone, BasicBlock* block) {
785 if (outgoing == NULL) {
786 outgoing = new (zone) ZoneList<BasicBlock*>(2, zone);
787 }
788 outgoing->Add(block, zone);
789 }
790 };
791
792 int Push(SpecialRPOStackFrame* stack, int depth, BasicBlock* child,
793 int unvisited) {
794 if (child->rpo_number() == unvisited) {
795 stack[depth].block = child;
796 stack[depth].index = 0;
797 child->set_rpo_number(kBlockOnStack);
798 return depth + 1;
799 }
800 return depth;
801 } 861 }
802 862
803 // Computes loop membership from the backedges of the control flow graph. 863 // Computes loop membership from the backedges of the control flow graph.
804 LoopInfo* ComputeLoopInfo( 864 void ComputeLoopInfo(SpecialRPOStackFrame* queue, size_t num_loops,
805 SpecialRPOStackFrame* queue, int num_loops, size_t num_blocks, 865 ZoneList<std::pair<BasicBlock*, size_t> >* backedges) {
806 ZoneList<std::pair<BasicBlock*, size_t> >* backedges) { 866 loops_.resize(num_loops, LoopInfo());
807 LoopInfo* loops = zone_->NewArray<LoopInfo>(num_loops);
808 memset(loops, 0, num_loops * sizeof(LoopInfo));
809 867
810 // Compute loop membership starting from backedges. 868 // Compute loop membership starting from backedges.
811 // O(max(loop_depth) * max(|loop|) 869 // O(max(loop_depth) * max(|loop|)
812 for (int i = 0; i < backedges->length(); i++) { 870 for (int i = 0; i < backedges->length(); i++) {
813 BasicBlock* member = backedges->at(i).first; 871 BasicBlock* member = backedges->at(i).first;
814 BasicBlock* header = member->SuccessorAt(backedges->at(i).second); 872 BasicBlock* header = member->SuccessorAt(backedges->at(i).second);
815 int loop_num = header->loop_end(); 873 size_t loop_num = GetLoopNumber(header);
816 if (loops[loop_num].header == NULL) { 874 if (loops_[loop_num].header == NULL) {
817 loops[loop_num].header = header; 875 loops_[loop_num].header = header;
818 loops[loop_num].members = 876 loops_[loop_num].members = new (zone_)
819 new (zone_) BitVector(static_cast<int>(num_blocks), zone_); 877 BitVector(static_cast<int>(schedule_->BasicBlockCount()), zone_);
820 } 878 }
821 879
822 int queue_length = 0; 880 int queue_length = 0;
823 if (member != header) { 881 if (member != header) {
824 // As long as the header doesn't have a backedge to itself, 882 // As long as the header doesn't have a backedge to itself,
825 // Push the member onto the queue and process its predecessors. 883 // Push the member onto the queue and process its predecessors.
826 if (!loops[loop_num].members->Contains(member->id().ToInt())) { 884 if (!loops_[loop_num].members->Contains(member->id().ToInt())) {
827 loops[loop_num].members->Add(member->id().ToInt()); 885 loops_[loop_num].members->Add(member->id().ToInt());
828 } 886 }
829 queue[queue_length++].block = member; 887 queue[queue_length++].block = member;
830 } 888 }
831 889
832 // Propagate loop membership backwards. All predecessors of M up to the 890 // Propagate loop membership backwards. All predecessors of M up to the
833 // loop header H are members of the loop too. O(|blocks between M and H|). 891 // loop header H are members of the loop too. O(|blocks between M and H|).
834 while (queue_length > 0) { 892 while (queue_length > 0) {
835 BasicBlock* block = queue[--queue_length].block; 893 BasicBlock* block = queue[--queue_length].block;
836 for (size_t i = 0; i < block->PredecessorCount(); i++) { 894 for (size_t i = 0; i < block->PredecessorCount(); i++) {
837 BasicBlock* pred = block->PredecessorAt(i); 895 BasicBlock* pred = block->PredecessorAt(i);
838 if (pred != header) { 896 if (pred != header) {
839 if (!loops[loop_num].members->Contains(pred->id().ToInt())) { 897 if (!loops_[loop_num].members->Contains(pred->id().ToInt())) {
840 loops[loop_num].members->Add(pred->id().ToInt()); 898 loops_[loop_num].members->Add(pred->id().ToInt());
841 queue[queue_length++].block = pred; 899 queue[queue_length++].block = pred;
842 } 900 }
843 } 901 }
844 } 902 }
845 } 903 }
846 } 904 }
847 return loops;
848 } 905 }
849 906
850 #if DEBUG 907 #if DEBUG
851 void PrintRPO(int num_loops, LoopInfo* loops, BasicBlockVector* order) { 908 void PrintRPO() {
852 OFStream os(stdout); 909 OFStream os(stdout);
853 os << "-- RPO with " << num_loops << " loops "; 910 os << "RPO with " << loops_.size() << " loops";
854 if (num_loops > 0) { 911 if (loops_.size() > 0) {
855 os << "("; 912 os << " (";
856 for (int i = 0; i < num_loops; i++) { 913 for (size_t i = 0; i < loops_.size(); i++) {
857 if (i > 0) os << " "; 914 if (i > 0) os << " ";
858 os << "B" << loops[i].header->id(); 915 os << "B" << loops_[i].header->id();
859 } 916 }
860 os << ") "; 917 os << ")";
861 } 918 }
862 os << "-- \n"; 919 os << ":\n";
863 920
864 for (size_t i = 0; i < order->size(); i++) { 921 for (BlockList* l = order_; l != NULL; l = l->next) {
865 BasicBlock* block = (*order)[i]; 922 BasicBlock* block = l->block;
866 BasicBlock::Id bid = block->id(); 923 BasicBlock::Id bid = block->id();
867 // TODO(jarin,svenpanne): Add formatting here once we have support for 924 // TODO(jarin,svenpanne): Add formatting here once we have support for
868 // that in streams (we want an equivalent of PrintF("%5d:", i) here). 925 // that in streams (we want an equivalent of PrintF("%5d:", x) here).
869 os << i << ":"; 926 os << " " << block->rpo_number() << ":";
870 for (int j = 0; j < num_loops; j++) { 927 for (size_t j = 0; j < loops_.size(); j++) {
871 bool membership = loops[j].members->Contains(bid.ToInt()); 928 bool membership = loops_[j].members->Contains(bid.ToInt());
872 bool range = loops[j].header->LoopContains(block); 929 bool range = loops_[j].header->LoopContains(block);
873 os << (membership ? " |" : " "); 930 os << (membership ? " |" : " ");
874 os << (range ? "x" : " "); 931 os << (range ? "x" : " ");
875 } 932 }
876 os << " B" << bid << ": "; 933 os << " B" << bid << ": ";
877 if (block->loop_end() >= 0) { 934 if (block->loop_end() != NULL) {
878 os << " range: [" << block->rpo_number() << ", " << block->loop_end() 935 os << " range: [" << block->rpo_number() << ", "
879 << ")"; 936 << block->loop_end()->rpo_number() << ")";
880 } 937 }
881 if (block->loop_header() != NULL) { 938 if (block->loop_header() != NULL) {
882 os << " header: B" << block->loop_header()->id(); 939 os << " header: B" << block->loop_header()->id();
883 } 940 }
884 if (block->loop_depth() > 0) { 941 if (block->loop_depth() > 0) {
885 os << " depth: " << block->loop_depth(); 942 os << " depth: " << block->loop_depth();
886 } 943 }
887 os << "\n"; 944 os << "\n";
888 } 945 }
889 } 946 }
890 947
891 void VerifySpecialRPO(int num_loops, LoopInfo* loops, 948 void VerifySpecialRPO() {
892 BasicBlockVector* order) { 949 BasicBlockVector* order = schedule_->rpo_order();
893 DCHECK(order->size() > 0); 950 DCHECK(order->size() > 0);
894 DCHECK((*order)[0]->id().ToInt() == 0); // entry should be first. 951 DCHECK((*order)[0]->id().ToInt() == 0); // entry should be first.
895 952
896 for (int i = 0; i < num_loops; i++) { 953 for (size_t i = 0; i < loops_.size(); i++) {
897 LoopInfo* loop = &loops[i]; 954 LoopInfo* loop = &loops_[i];
898 BasicBlock* header = loop->header; 955 BasicBlock* header = loop->header;
956 BasicBlock* end = header->loop_end();
899 957
900 DCHECK(header != NULL); 958 DCHECK(header != NULL);
901 DCHECK(header->rpo_number() >= 0); 959 DCHECK(header->rpo_number() >= 0);
902 DCHECK(header->rpo_number() < static_cast<int>(order->size())); 960 DCHECK(header->rpo_number() < static_cast<int>(order->size()));
903 DCHECK(header->loop_end() >= 0); 961 DCHECK(end != NULL);
904 DCHECK(header->loop_end() <= static_cast<int>(order->size())); 962 DCHECK(end->rpo_number() <= static_cast<int>(order->size()));
905 DCHECK(header->loop_end() > header->rpo_number()); 963 DCHECK(end->rpo_number() > header->rpo_number());
906 DCHECK(header->loop_header() != header); 964 DCHECK(header->loop_header() != header);
907 965
908 // Verify the start ... end list relationship. 966 // Verify the start ... end list relationship.
909 int links = 0; 967 int links = 0;
910 BlockList* l = loop->start; 968 BlockList* l = loop->start;
911 DCHECK(l != NULL && l->block == header); 969 DCHECK(l != NULL && l->block == header);
912 bool end_found; 970 bool end_found;
913 while (true) { 971 while (true) {
914 if (l == NULL || l == loop->end) { 972 if (l == NULL || l == loop->end) {
915 end_found = (loop->end == l); 973 end_found = (loop->end == l);
916 break; 974 break;
917 } 975 }
918 // The list should be in same order as the final result. 976 // The list should be in same order as the final result.
919 DCHECK(l->block->rpo_number() == links + loop->header->rpo_number()); 977 DCHECK(l->block->rpo_number() == links + loop->header->rpo_number());
920 links++; 978 links++;
921 l = l->next; 979 l = l->next;
922 DCHECK(links < static_cast<int>(2 * order->size())); // cycle? 980 DCHECK(links < static_cast<int>(2 * order->size())); // cycle?
923 } 981 }
924 DCHECK(links > 0); 982 DCHECK(links > 0);
925 DCHECK(links == (header->loop_end() - header->rpo_number())); 983 DCHECK(links == end->rpo_number() - header->rpo_number());
926 DCHECK(end_found); 984 DCHECK(end_found);
927 985
928 // Check the contiguousness of loops. 986 // Check the contiguousness of loops.
929 int count = 0; 987 // TODO(mstarzinger): Loop membership bit-vector becomes stale.
988 /*int count = 0;
930 for (int j = 0; j < static_cast<int>(order->size()); j++) { 989 for (int j = 0; j < static_cast<int>(order->size()); j++) {
931 BasicBlock* block = order->at(j); 990 BasicBlock* block = order->at(j);
932 DCHECK(block->rpo_number() == j); 991 DCHECK(block->rpo_number() == j);
933 if (j < header->rpo_number() || j >= header->loop_end()) { 992 if (j < header->rpo_number() || j >= end->rpo_number()) {
934 DCHECK(!loop->members->Contains(block->id().ToInt())); 993 DCHECK(!loop->members->Contains(block->id().ToInt()));
935 } else { 994 } else {
936 if (block == header) { 995 if (block == header) {
937 DCHECK(!loop->members->Contains(block->id().ToInt())); 996 DCHECK(!loop->members->Contains(block->id().ToInt()));
938 } else { 997 } else {
939 DCHECK(loop->members->Contains(block->id().ToInt())); 998 DCHECK(loop->members->Contains(block->id().ToInt()));
940 } 999 }
941 count++; 1000 count++;
942 } 1001 }
943 } 1002 }
944 DCHECK(links == count); 1003 DCHECK(links == count);*/
945 } 1004 }
946 } 1005 }
947 #endif // DEBUG 1006 #endif // DEBUG
948 1007
949 Zone* zone_; 1008 Zone* zone_;
950 Schedule* schedule_; 1009 Schedule* schedule_;
1010 BlockList* order_;
1011 ZoneVector<LoopInfo> loops_;
1012 BasicBlock* beyond_end_;
951 }; 1013 };
952 1014
953 1015
954 BasicBlockVector* Scheduler::ComputeSpecialRPO(ZonePool* zone_pool, 1016 BasicBlockVector* Scheduler::ComputeSpecialRPO(ZonePool* zone_pool,
955 Schedule* schedule) { 1017 Schedule* schedule) {
956 ZonePool::Scope zone_scope(zone_pool); 1018 ZonePool::Scope zone_scope(zone_pool);
957 Zone* zone = zone_scope.zone(); 1019 Zone* zone = zone_scope.zone();
958 1020
959 SpecialRPONumberer numberer(zone, schedule); 1021 SpecialRPONumberer numberer(zone, schedule);
960 numberer.ComputeSpecialRPO(); 1022 numberer.ComputeSpecialRPO();
1023 numberer.SerializeAOIntoSchedule();
1024 numberer.SerializeRPOIntoSchedule();
1025 numberer.PrintAndVerifySpecialRPO();
961 return schedule->rpo_order(); 1026 return schedule->rpo_order();
962 } 1027 }
963 1028
964 1029
965 void Scheduler::ComputeSpecialRPONumbering() { 1030 void Scheduler::ComputeSpecialRPONumbering() {
966 Trace("--- COMPUTING SPECIAL RPO ----------------------------------\n"); 1031 Trace("--- COMPUTING SPECIAL RPO ----------------------------------\n");
967 1032
968 SpecialRPONumberer numberer(zone_, schedule_); 1033 // Compute the special reverse-post-order for basic blocks.
969 numberer.ComputeSpecialRPO(); 1034 special_rpo_ = new (zone_) SpecialRPONumberer(zone_, schedule_);
1035 special_rpo_->ComputeSpecialRPO();
970 } 1036 }
971 1037
972 1038
973 void Scheduler::GenerateImmediateDominatorTree() { 1039 void Scheduler::GenerateImmediateDominatorTree() {
974 Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n"); 1040 Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n");
975 1041
976 // Build the dominator graph. 1042 // TODO(danno): Consider using Lengauer & Tarjan's if this becomes too slow.
977 // TODO(danno): consider using Lengauer & Tarjan's if this becomes too slow. 1043
978 for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) { 1044 // Build the block dominator tree.
979 BasicBlock* current_rpo = schedule_->rpo_order_[i]; 1045 schedule_->start()->set_dominator_depth(0);
980 if (current_rpo != schedule_->start()) { 1046 typedef SpecialRPONumberer::BlockList BlockList;
981 BasicBlock::Predecessors::iterator current_pred = 1047 for (BlockList* l = special_rpo_->order_; l != NULL; l = l->next) {
982 current_rpo->predecessors_begin(); 1048 BasicBlock* current = l->block;
983 BasicBlock::Predecessors::iterator end = current_rpo->predecessors_end(); 1049 if (current == schedule_->start()) continue;
984 DCHECK(current_pred != end); 1050 BasicBlock::Predecessors::iterator pred = current->predecessors_begin();
985 BasicBlock* dominator = *current_pred; 1051 BasicBlock::Predecessors::iterator end = current->predecessors_end();
986 ++current_pred; 1052 DCHECK(pred != end); // All blocks except start have predecessors.
987 // For multiple predecessors, walk up the RPO ordering until a common 1053 BasicBlock* dominator = *pred;
988 // dominator is found. 1054 // For multiple predecessors, walk up the dominator tree until a common
989 int current_rpo_pos = GetRPONumber(current_rpo); 1055 // dominator is found. Visitation order guarantees that all predecessors
990 while (current_pred != end) { 1056 // except for backwards edges have been visited.
991 // Don't examine backwards edges 1057 for (++pred; pred != end; ++pred) {
992 BasicBlock* pred = *current_pred; 1058 // Don't examine backwards edges.
993 if (GetRPONumber(pred) < current_rpo_pos) { 1059 if ((*pred)->dominator_depth() < 0) continue;
994 dominator = GetCommonDominator(dominator, *current_pred); 1060 dominator = GetCommonDominator(dominator, *pred);
995 }
996 ++current_pred;
997 }
998 current_rpo->set_dominator(dominator);
999 Trace("Block %d's idom is %d\n", current_rpo->id().ToInt(),
1000 dominator->id().ToInt());
1001 } 1061 }
1062 current->set_dominator(dominator);
1063 current->set_dominator_depth(dominator->dominator_depth() + 1);
1064 Trace("Block B%d's idom is B%d, depth = %d\n", current->id().ToInt(),
1065 dominator->id().ToInt(), current->dominator_depth());
1002 } 1066 }
1003 } 1067 }
1004 1068
1005 1069
1006 // ----------------------------------------------------------------------------- 1070 // -----------------------------------------------------------------------------
1007 // Phase 3: Prepare use counts for nodes. 1071 // Phase 3: Prepare use counts for nodes.
1008 1072
1009 1073
1010 class PrepareUsesVisitor : public NullNodeVisitor { 1074 class PrepareUsesVisitor : public NullNodeVisitor {
1011 public: 1075 public:
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1080 private: 1144 private:
1081 // Visits one node from the queue and propagates its current schedule early 1145 // Visits one node from the queue and propagates its current schedule early
1082 // position to all uses. This in turn might push more nodes onto the queue. 1146 // position to all uses. This in turn might push more nodes onto the queue.
1083 void VisitNode(Node* node) { 1147 void VisitNode(Node* node) {
1084 Scheduler::SchedulerData* data = scheduler_->GetData(node); 1148 Scheduler::SchedulerData* data = scheduler_->GetData(node);
1085 1149
1086 // Fixed nodes already know their schedule early position. 1150 // Fixed nodes already know their schedule early position.
1087 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { 1151 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) {
1088 DCHECK_EQ(schedule_->start(), data->minimum_block_); 1152 DCHECK_EQ(schedule_->start(), data->minimum_block_);
1089 data->minimum_block_ = schedule_->block(node); 1153 data->minimum_block_ = schedule_->block(node);
1090 Trace("Fixing #%d:%s minimum_rpo = %d\n", node->id(), 1154 Trace("Fixing #%d:%s minimum_block = B%d, dominator_depth = %d\n",
1091 node->op()->mnemonic(), data->minimum_block_->rpo_number()); 1155 node->id(), node->op()->mnemonic(),
1156 data->minimum_block_->id().ToInt(),
1157 data->minimum_block_->dominator_depth());
1092 } 1158 }
1093 1159
1094 // No need to propagate unconstrained schedule early positions. 1160 // No need to propagate unconstrained schedule early positions.
1095 if (data->minimum_block_ == schedule_->start()) return; 1161 if (data->minimum_block_ == schedule_->start()) return;
1096 1162
1097 // Propagate schedule early position. 1163 // Propagate schedule early position.
1098 DCHECK(data->minimum_block_ != NULL); 1164 DCHECK(data->minimum_block_ != NULL);
1099 Node::Uses uses = node->uses(); 1165 Node::Uses uses = node->uses();
1100 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) { 1166 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) {
1101 PropagateMinimumRPOToNode(data->minimum_block_, *i); 1167 PropagateMinimumPositionToNode(data->minimum_block_, *i);
1102 } 1168 }
1103 } 1169 }
1104 1170
1105 // Propagates {block} as another minimum RPO placement into the given {node}. 1171 // Propagates {block} as another minimum position into the given {node}. This
1106 // This has the net effect of computing the maximum of the minimum RPOs for 1172 // has the net effect of computing the minimum dominator block of {node} that
1107 // all inputs to {node} when the queue has been fully processed. 1173 // still post-dominates all inputs to {node} when the queue is processed.
1108 void PropagateMinimumRPOToNode(BasicBlock* block, Node* node) { 1174 void PropagateMinimumPositionToNode(BasicBlock* block, Node* node) {
1109 Scheduler::SchedulerData* data = scheduler_->GetData(node); 1175 Scheduler::SchedulerData* data = scheduler_->GetData(node);
1110 1176
1111 // No need to propagate to fixed node, it's guaranteed to be a root. 1177 // No need to propagate to fixed node, it's guaranteed to be a root.
1112 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) return; 1178 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) return;
1113 1179
1114 // Coupled nodes influence schedule early position of their control. 1180 // Coupled nodes influence schedule early position of their control.
1115 if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) { 1181 if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) {
1116 Node* control = NodeProperties::GetControlInput(node); 1182 Node* control = NodeProperties::GetControlInput(node);
1117 PropagateMinimumRPOToNode(block, control); 1183 PropagateMinimumPositionToNode(block, control);
1118 } 1184 }
1119 1185
1120 // Propagate new position if it is larger than the current. 1186 // Propagate new position if it is deeper down the dominator tree than the
1121 if (block->rpo_number() > data->minimum_block_->rpo_number()) { 1187 // current. Note that all inputs need to have minimum block position inside
1188 // the dominator chain of {node}'s minimum block position.
1189 DCHECK(InsideSameDominatorChain(block, data->minimum_block_));
1190 if (block->dominator_depth() > data->minimum_block_->dominator_depth()) {
1122 data->minimum_block_ = block; 1191 data->minimum_block_ = block;
1123 queue_.push(node); 1192 queue_.push(node);
1124 Trace("Propagating #%d:%s minimum_rpo = %d\n", node->id(), 1193 Trace("Propagating #%d:%s minimum_block = B%d, dominator_depth = %d\n",
1125 node->op()->mnemonic(), data->minimum_block_->rpo_number()); 1194 node->id(), node->op()->mnemonic(),
1195 data->minimum_block_->id().ToInt(),
1196 data->minimum_block_->dominator_depth());
1126 } 1197 }
1127 } 1198 }
1128 1199
1200 #if DEBUG
1201 bool InsideSameDominatorChain(BasicBlock* b1, BasicBlock* b2) {
1202 BasicBlock* dominator = scheduler_->GetCommonDominator(b1, b2);
1203 return dominator == b1 || dominator == b2;
1204 }
1205 #endif
1206
1129 Scheduler* scheduler_; 1207 Scheduler* scheduler_;
1130 Schedule* schedule_; 1208 Schedule* schedule_;
1131 ZoneQueue<Node*> queue_; 1209 ZoneQueue<Node*> queue_;
1132 }; 1210 };
1133 1211
1134 1212
1135 void Scheduler::ScheduleEarly() { 1213 void Scheduler::ScheduleEarly() {
1136 Trace("--- SCHEDULE EARLY -----------------------------------------\n"); 1214 Trace("--- SCHEDULE EARLY -----------------------------------------\n");
1137 if (FLAG_trace_turbo_scheduler) { 1215 if (FLAG_trace_turbo_scheduler) {
1138 Trace("roots: "); 1216 Trace("roots: ");
1139 for (NodeVectorIter i = schedule_root_nodes_.begin(); 1217 for (Node* node : schedule_root_nodes_) {
1140 i != schedule_root_nodes_.end(); ++i) { 1218 Trace("#%d:%s ", node->id(), node->op()->mnemonic());
1141 Trace("#%d:%s ", (*i)->id(), (*i)->op()->mnemonic());
1142 } 1219 }
1143 Trace("\n"); 1220 Trace("\n");
1144 } 1221 }
1145 1222
1146 // Compute the minimum RPO for each node thereby determining the earliest 1223 // Compute the minimum block for each node thereby determining the earliest
1147 // position each node could be placed within a valid schedule. 1224 // position each node could be placed within a valid schedule.
1148 ScheduleEarlyNodeVisitor schedule_early_visitor(zone_, this); 1225 ScheduleEarlyNodeVisitor schedule_early_visitor(zone_, this);
1149 schedule_early_visitor.Run(&schedule_root_nodes_); 1226 schedule_early_visitor.Run(&schedule_root_nodes_);
1150 } 1227 }
1151 1228
1152 1229
1153 // ----------------------------------------------------------------------------- 1230 // -----------------------------------------------------------------------------
1154 // Phase 5: Schedule nodes late. 1231 // Phase 5: Schedule nodes late.
1155 1232
1156 1233
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 // Don't schedule nodes that are already scheduled. 1274 // Don't schedule nodes that are already scheduled.
1198 if (schedule_->IsScheduled(node)) return; 1275 if (schedule_->IsScheduled(node)) return;
1199 DCHECK_EQ(Scheduler::kSchedulable, scheduler_->GetPlacement(node)); 1276 DCHECK_EQ(Scheduler::kSchedulable, scheduler_->GetPlacement(node));
1200 1277
1201 // Determine the dominating block for all of the uses of this node. It is 1278 // Determine the dominating block for all of the uses of this node. It is
1202 // the latest block that this node can be scheduled in. 1279 // the latest block that this node can be scheduled in.
1203 Trace("Scheduling #%d:%s\n", node->id(), node->op()->mnemonic()); 1280 Trace("Scheduling #%d:%s\n", node->id(), node->op()->mnemonic());
1204 BasicBlock* block = GetCommonDominatorOfUses(node); 1281 BasicBlock* block = GetCommonDominatorOfUses(node);
1205 DCHECK_NOT_NULL(block); 1282 DCHECK_NOT_NULL(block);
1206 1283
1207 int min_rpo = scheduler_->GetData(node)->minimum_block_->rpo_number(); 1284 // The schedule early block dominates the schedule late block.
1208 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum_rpo = %d\n", 1285 BasicBlock* min_block = scheduler_->GetData(node)->minimum_block_;
1286 DCHECK_EQ(min_block, scheduler_->GetCommonDominator(block, min_block));
1287 Trace("Schedule late of #%d:%s is B%d at loop depth %d, minimum = B%d\n",
1209 node->id(), node->op()->mnemonic(), block->id().ToInt(), 1288 node->id(), node->op()->mnemonic(), block->id().ToInt(),
1210 block->loop_depth(), min_rpo); 1289 block->loop_depth(), min_block->id().ToInt());
1211 1290
1212 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively 1291 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively
1213 // into enclosing loop pre-headers until they would preceed their 1292 // into enclosing loop pre-headers until they would preceed their schedule
1214 // ScheduleEarly position. 1293 // early position.
1215 BasicBlock* hoist_block = GetPreHeader(block); 1294 BasicBlock* hoist_block = GetPreHeader(block);
1216 while (hoist_block != NULL && hoist_block->rpo_number() >= min_rpo) { 1295 while (hoist_block != NULL &&
1217 Trace(" hoisting #%d:%s to block %d\n", node->id(), 1296 hoist_block->dominator_depth() >= min_block->dominator_depth()) {
1297 Trace(" hoisting #%d:%s to block B%d\n", node->id(),
1218 node->op()->mnemonic(), hoist_block->id().ToInt()); 1298 node->op()->mnemonic(), hoist_block->id().ToInt());
1219 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth()); 1299 DCHECK_LT(hoist_block->loop_depth(), block->loop_depth());
1220 block = hoist_block; 1300 block = hoist_block;
1221 hoist_block = GetPreHeader(hoist_block); 1301 hoist_block = GetPreHeader(hoist_block);
1222 } 1302 }
1223 1303
1224 // Schedule the node or a floating control structure. 1304 // Schedule the node or a floating control structure.
1225 if (NodeProperties::IsControl(node)) { 1305 if (NodeProperties::IsControl(node)) {
1226 ScheduleFloatingControl(block, node); 1306 ScheduleFloatingControl(block, node);
1227 } else { 1307 } else {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 1375
1296 Scheduler* scheduler_; 1376 Scheduler* scheduler_;
1297 Schedule* schedule_; 1377 Schedule* schedule_;
1298 }; 1378 };
1299 1379
1300 1380
1301 void Scheduler::ScheduleLate() { 1381 void Scheduler::ScheduleLate() {
1302 Trace("--- SCHEDULE LATE ------------------------------------------\n"); 1382 Trace("--- SCHEDULE LATE ------------------------------------------\n");
1303 if (FLAG_trace_turbo_scheduler) { 1383 if (FLAG_trace_turbo_scheduler) {
1304 Trace("roots: "); 1384 Trace("roots: ");
1305 for (NodeVectorIter i = schedule_root_nodes_.begin(); 1385 for (Node* node : schedule_root_nodes_) {
1306 i != schedule_root_nodes_.end(); ++i) { 1386 Trace("#%d:%s ", node->id(), node->op()->mnemonic());
1307 Trace("#%d:%s ", (*i)->id(), (*i)->op()->mnemonic());
1308 } 1387 }
1309 Trace("\n"); 1388 Trace("\n");
1310 } 1389 }
1311 1390
1312 // Schedule: Places nodes in dominator block of all their uses. 1391 // Schedule: Places nodes in dominator block of all their uses.
1313 ScheduleLateNodeVisitor schedule_late_visitor(zone_, this); 1392 ScheduleLateNodeVisitor schedule_late_visitor(zone_, this);
1314 schedule_late_visitor.Run(&schedule_root_nodes_); 1393 schedule_late_visitor.Run(&schedule_root_nodes_);
1394 }
1395
1396
1397 // -----------------------------------------------------------------------------
1398 // Phase 6: Seal the final schedule.
1399
1400
1401 void Scheduler::SealFinalSchedule() {
1402 Trace("--- SEAL FINAL SCHEDULE ------------------------------------\n");
1403
1404 // Serialize the assembly order and reverse-post-order numbering.
1405 special_rpo_->SerializeAOIntoSchedule();
1406 special_rpo_->SerializeRPOIntoSchedule();
1407 special_rpo_->PrintAndVerifySpecialRPO();
1315 1408
1316 // Add collected nodes for basic blocks to their blocks in the right order. 1409 // Add collected nodes for basic blocks to their blocks in the right order.
1317 int block_num = 0; 1410 int block_num = 0;
1318 for (NodeVectorVectorIter i = scheduled_nodes_.begin(); 1411 for (NodeVector& nodes : scheduled_nodes_) {
1319 i != scheduled_nodes_.end(); ++i) { 1412 BasicBlock::Id id = BasicBlock::Id::FromInt(block_num++);
1320 for (NodeVectorRIter j = i->rbegin(); j != i->rend(); ++j) { 1413 BasicBlock* block = schedule_->GetBlockById(id);
1321 schedule_->AddNode(schedule_->all_blocks_.at(block_num), *j); 1414 for (NodeVectorRIter i = nodes.rbegin(); i != nodes.rend(); ++i) {
1415 schedule_->AddNode(block, *i);
1322 } 1416 }
1323 block_num++;
1324 } 1417 }
1325 } 1418 }
1326 1419
1327 1420
1328 // ----------------------------------------------------------------------------- 1421 // -----------------------------------------------------------------------------
1329 1422
1330 1423
1331 void Scheduler::FuseFloatingControl(BasicBlock* block, Node* node) { 1424 void Scheduler::FuseFloatingControl(BasicBlock* block, Node* node) {
1332 Trace("--- FUSE FLOATING CONTROL ----------------------------------\n"); 1425 Trace("--- FUSE FLOATING CONTROL ----------------------------------\n");
1333 if (FLAG_trace_turbo_scheduler) { 1426 if (FLAG_trace_turbo_scheduler) {
1334 OFStream os(stdout); 1427 OFStream os(stdout);
1335 os << "Schedule before control flow fusion:\n" << *schedule_; 1428 os << "Schedule before control flow fusion:\n" << *schedule_;
1336 } 1429 }
1337 1430
1338 // Iterate on phase 1: Build control-flow graph. 1431 // Iterate on phase 1: Build control-flow graph.
1339 CFGBuilder cfg_builder(zone_, this); 1432 CFGBuilder cfg_builder(zone_, this);
1340 cfg_builder.Run(block, node); 1433 cfg_builder.Run(block, node);
1341 1434
1342 // Iterate on phase 2: Compute special RPO and dominator tree. 1435 // Iterate on phase 2: Compute special RPO and dominator tree.
1343 // TODO(mstarzinger): Currently "iterate on" means "re-run". Fix that. 1436 // TODO(mstarzinger): Currently "iterate on" means "re-run". Fix that.
1344 BasicBlockVector* rpo = schedule_->rpo_order(); 1437 for (BasicBlock* block : schedule_->all_blocks_) {
1345 for (BasicBlockVectorIter i = rpo->begin(); i != rpo->end(); ++i) {
1346 BasicBlock* block = *i;
1347 block->set_rpo_number(-1); 1438 block->set_rpo_number(-1);
1348 block->set_loop_header(NULL); 1439 block->set_dominator_depth(-1);
1349 block->set_loop_depth(0); 1440 block->set_dominator(NULL);
1350 block->set_loop_end(-1);
1351 } 1441 }
1352 schedule_->rpo_order()->clear(); 1442 special_rpo_->UpdateSpecialRPO(block, schedule_->block(node));
1353 SpecialRPONumberer numberer(zone_, schedule_);
1354 numberer.ComputeSpecialRPO();
1355 GenerateImmediateDominatorTree(); 1443 GenerateImmediateDominatorTree();
1356 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_));
1357 1444
1358 // Move previously planned nodes. 1445 // Move previously planned nodes.
1359 // TODO(mstarzinger): Improve that by supporting bulk moves. 1446 // TODO(mstarzinger): Improve that by supporting bulk moves.
1447 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_));
1360 MovePlannedNodes(block, schedule_->block(node)); 1448 MovePlannedNodes(block, schedule_->block(node));
1361 1449
1362 if (FLAG_trace_turbo_scheduler) { 1450 if (FLAG_trace_turbo_scheduler) {
1363 OFStream os(stdout); 1451 OFStream os(stdout);
1364 os << "Schedule after control flow fusion:" << *schedule_; 1452 os << "Schedule after control flow fusion:\n" << *schedule_;
1365 } 1453 }
1366 } 1454 }
1367 1455
1368 1456
1369 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) { 1457 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) {
1370 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(),
1371 to->id().ToInt()); 1459 to->id().ToInt());
1372 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]); 1460 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]);
1373 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { 1461 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) {
1374 schedule_->SetBlockForNode(to, *i); 1462 schedule_->SetBlockForNode(to, *i);
1375 scheduled_nodes_[to->id().ToSize()].push_back(*i); 1463 scheduled_nodes_[to->id().ToSize()].push_back(*i);
1376 } 1464 }
1377 nodes->clear(); 1465 nodes->clear();
1378 } 1466 }
1379 1467
1380 } // namespace compiler 1468 } // namespace compiler
1381 } // namespace internal 1469 } // namespace internal
1382 } // namespace v8 1470 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/scheduler.h ('k') | test/cctest/compiler/test-instruction.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698