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

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