OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <deque> | 5 #include <deque> |
6 #include <queue> | 6 #include <queue> |
7 | 7 |
8 #include "src/compiler/scheduler.h" | 8 #include "src/compiler/scheduler.h" |
9 | 9 |
10 #include "src/bit-vector.h" | 10 #include "src/bit-vector.h" |
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
529 // headed at A. | 529 // headed at A. |
530 // 2. All loops are contiguous in the order (i.e. no intervening blocks that | 530 // 2. All loops are contiguous in the order (i.e. no intervening blocks that |
531 // do not belong to the loop.) | 531 // do not belong to the loop.) |
532 // Note a simple RPO traversal satisfies (1) but not (2). | 532 // Note a simple RPO traversal satisfies (1) but not (2). |
533 class SpecialRPONumberer : public ZoneObject { | 533 class SpecialRPONumberer : public ZoneObject { |
534 public: | 534 public: |
535 SpecialRPONumberer(Zone* zone, Schedule* schedule) | 535 SpecialRPONumberer(Zone* zone, Schedule* schedule) |
536 : zone_(zone), | 536 : zone_(zone), |
537 schedule_(schedule), | 537 schedule_(schedule), |
538 order_(NULL), | 538 order_(NULL), |
| 539 beyond_end_(NULL), |
539 loops_(zone), | 540 loops_(zone), |
540 beyond_end_(NULL), | |
541 backedges_(1, zone), | 541 backedges_(1, zone), |
542 stack_(zone), | 542 stack_(zone), |
543 previous_block_count_(0) {} | 543 previous_block_count_(0) {} |
544 | 544 |
545 // Computes the special reverse-post-order for the main control flow graph, | 545 // Computes the special reverse-post-order for the main control flow graph, |
546 // that is for the graph spanned between the schedule's start and end blocks. | 546 // that is for the graph spanned between the schedule's start and end blocks. |
547 void ComputeSpecialRPO() { | 547 void ComputeSpecialRPO() { |
548 DCHECK(schedule_->end()->SuccessorCount() == 0); | 548 DCHECK(schedule_->end()->SuccessorCount() == 0); |
549 DCHECK_EQ(NULL, order_); // Main order does not exist yet. | 549 DCHECK_EQ(NULL, order_); // Main order does not exist yet. |
550 ComputeAndInsertSpecialRPO(schedule_->start(), schedule_->end()); | 550 ComputeAndInsertSpecialRPO(schedule_->start(), schedule_->end()); |
551 } | 551 } |
552 | 552 |
553 // Computes the special reverse-post-order for a partial control flow graph, | 553 // Computes the special reverse-post-order for a partial control flow graph, |
554 // that is for the graph spanned between the given {entry} and {end} blocks, | 554 // that is for the graph spanned between the given {entry} and {end} blocks, |
555 // then updates the existing ordering with this new information. | 555 // then updates the existing ordering with this new information. |
556 void UpdateSpecialRPO(BasicBlock* entry, BasicBlock* end) { | 556 void UpdateSpecialRPO(BasicBlock* entry, BasicBlock* end) { |
557 DCHECK_NE(NULL, order_); // Main order to be updated is present. | 557 DCHECK_NE(NULL, order_); // Main order to be updated is present. |
558 ComputeAndInsertSpecialRPO(entry, end); | 558 ComputeAndInsertSpecialRPO(entry, end); |
559 } | 559 } |
560 | 560 |
561 // Serialize the previously computed order as an assembly order (non-deferred | 561 // Serialize the previously computed order as an assembly order (non-deferred |
562 // code first, deferred code afterwards) into the final schedule. | 562 // code first, deferred code afterwards) into the final schedule. |
563 void SerializeAOIntoSchedule() { | 563 void SerializeAOIntoSchedule() { |
564 int32_t number = 0; | 564 int32_t number = 0; |
565 for (BlockList* l = order_; l != NULL; l = l->next) { | 565 for (BasicBlock* b = order_; b != NULL; b = b->rpo_next()) { |
566 if (l->block->deferred()) continue; | 566 if (b->deferred()) continue; |
567 l->block->set_ao_number(number++); | 567 b->set_ao_number(number++); |
568 } | 568 } |
569 for (BlockList* l = order_; l != NULL; l = l->next) { | 569 for (BasicBlock* b = order_; b != NULL; b = b->rpo_next()) { |
570 if (!l->block->deferred()) continue; | 570 if (!b->deferred()) continue; |
571 l->block->set_ao_number(number++); | 571 b->set_ao_number(number++); |
572 } | 572 } |
573 } | 573 } |
574 | 574 |
575 // Serialize the previously computed order as a special reverse-post-order | 575 // Serialize the previously computed order as a special reverse-post-order |
576 // numbering for basic blocks into the final schedule. | 576 // numbering for basic blocks into the final schedule. |
577 void SerializeRPOIntoSchedule() { | 577 void SerializeRPOIntoSchedule() { |
578 int32_t number = 0; | 578 int32_t number = 0; |
579 for (BlockList* l = order_; l != NULL; l = l->next) { | 579 for (BasicBlock* b = order_; b != NULL; b = b->rpo_next()) { |
580 l->block->set_rpo_number(number++); | 580 b->set_rpo_number(number++); |
581 schedule_->rpo_order()->push_back(l->block); | 581 schedule_->rpo_order()->push_back(b); |
582 } | 582 } |
583 BeyondEndSentinel()->set_rpo_number(number); | 583 BeyondEndSentinel()->set_rpo_number(number); |
584 } | 584 } |
585 | 585 |
586 // Print and verify the special reverse-post-order. | 586 // Print and verify the special reverse-post-order. |
587 void PrintAndVerifySpecialRPO() { | 587 void PrintAndVerifySpecialRPO() { |
588 #if DEBUG | 588 #if DEBUG |
589 if (FLAG_trace_turbo_scheduler) PrintRPO(); | 589 if (FLAG_trace_turbo_scheduler) PrintRPO(); |
590 VerifySpecialRPO(); | 590 VerifySpecialRPO(); |
591 #endif | 591 #endif |
592 } | 592 } |
593 | 593 |
594 private: | 594 private: |
595 typedef std::pair<BasicBlock*, size_t> Backedge; | 595 typedef std::pair<BasicBlock*, size_t> Backedge; |
596 | 596 |
597 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree. | |
598 friend class Scheduler; | |
599 | |
600 // Numbering for BasicBlock::rpo_number for this block traversal: | 597 // Numbering for BasicBlock::rpo_number for this block traversal: |
601 static const int kBlockOnStack = -2; | 598 static const int kBlockOnStack = -2; |
602 static const int kBlockVisited1 = -3; | 599 static const int kBlockVisited1 = -3; |
603 static const int kBlockVisited2 = -4; | 600 static const int kBlockVisited2 = -4; |
604 static const int kBlockUnvisited1 = -1; | 601 static const int kBlockUnvisited1 = -1; |
605 static const int kBlockUnvisited2 = kBlockVisited1; | 602 static const int kBlockUnvisited2 = kBlockVisited1; |
606 | 603 |
607 struct SpecialRPOStackFrame { | 604 struct SpecialRPOStackFrame { |
608 BasicBlock* block; | 605 BasicBlock* block; |
609 size_t index; | 606 size_t index; |
610 }; | 607 }; |
611 | 608 |
612 struct BlockList { | |
613 BasicBlock* block; | |
614 BlockList* next; | |
615 | |
616 BlockList* Add(Zone* zone, BasicBlock* b) { | |
617 BlockList* list = static_cast<BlockList*>(zone->New(sizeof(BlockList))); | |
618 list->block = b; | |
619 list->next = this; | |
620 return list; | |
621 } | |
622 | |
623 BlockList* FindForBlock(BasicBlock* b) { | |
624 for (BlockList* l = this; l != NULL; l = l->next) { | |
625 if (l->block == b) return l; | |
626 } | |
627 return NULL; | |
628 } | |
629 }; | |
630 | |
631 struct LoopInfo { | 609 struct LoopInfo { |
632 BasicBlock* header; | 610 BasicBlock* header; |
633 ZoneList<BasicBlock*>* outgoing; | 611 ZoneList<BasicBlock*>* outgoing; |
634 BitVector* members; | 612 BitVector* members; |
635 LoopInfo* prev; | 613 LoopInfo* prev; |
636 BlockList* end; | 614 BasicBlock* end; |
637 BlockList* start; | 615 BasicBlock* start; |
638 | 616 |
639 void AddOutgoing(Zone* zone, BasicBlock* block) { | 617 void AddOutgoing(Zone* zone, BasicBlock* block) { |
640 if (outgoing == NULL) { | 618 if (outgoing == NULL) { |
641 outgoing = new (zone) ZoneList<BasicBlock*>(2, zone); | 619 outgoing = new (zone) ZoneList<BasicBlock*>(2, zone); |
642 } | 620 } |
643 outgoing->Add(block, zone); | 621 outgoing->Add(block, zone); |
644 } | 622 } |
645 }; | 623 }; |
646 | 624 |
647 int Push(ZoneVector<SpecialRPOStackFrame>& stack, int depth, | 625 int Push(ZoneVector<SpecialRPOStackFrame>& stack, int depth, |
648 BasicBlock* child, int unvisited) { | 626 BasicBlock* child, int unvisited) { |
649 if (child->rpo_number() == unvisited) { | 627 if (child->rpo_number() == unvisited) { |
650 stack[depth].block = child; | 628 stack[depth].block = child; |
651 stack[depth].index = 0; | 629 stack[depth].index = 0; |
652 child->set_rpo_number(kBlockOnStack); | 630 child->set_rpo_number(kBlockOnStack); |
653 return depth + 1; | 631 return depth + 1; |
654 } | 632 } |
655 return depth; | 633 return depth; |
656 } | 634 } |
657 | 635 |
| 636 BasicBlock* PushFront(BasicBlock* head, BasicBlock* block) { |
| 637 block->set_rpo_next(head); |
| 638 return block; |
| 639 } |
| 640 |
658 // We are hijacking the {ao_number} to enumerate loops temporarily. Note that | 641 // We are hijacking the {ao_number} to enumerate loops temporarily. Note that |
659 // these numbers are only valid within this class. | 642 // these numbers are only valid within this class. |
660 static int GetLoopNumber(BasicBlock* block) { return block->ao_number(); } | 643 static int GetLoopNumber(BasicBlock* block) { return block->ao_number(); } |
661 static void SetLoopNumber(BasicBlock* block, int loop_number) { | 644 static void SetLoopNumber(BasicBlock* block, int loop_number) { |
662 return block->set_ao_number(loop_number); | 645 return block->set_ao_number(loop_number); |
663 } | 646 } |
664 static bool HasLoopNumber(BasicBlock* block) { | 647 static bool HasLoopNumber(BasicBlock* block) { |
665 return block->ao_number() >= 0; | 648 return block->ao_number() >= 0; |
666 } | 649 } |
667 | 650 |
(...skipping 10 matching lines...) Expand all Loading... |
678 | 661 |
679 // Compute special RPO for the control flow graph between {entry} and {end}, | 662 // Compute special RPO for the control flow graph between {entry} and {end}, |
680 // mutating any existing order so that the result is still valid. | 663 // mutating any existing order so that the result is still valid. |
681 void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) { | 664 void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) { |
682 // RPO should not have been serialized for this schedule yet. | 665 // RPO should not have been serialized for this schedule yet. |
683 CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number()); | 666 CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number()); |
684 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); | 667 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); |
685 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); | 668 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); |
686 | 669 |
687 // Find correct insertion point within existing order. | 670 // Find correct insertion point within existing order. |
688 BlockList* insert_before = order_->FindForBlock(entry); | 671 BasicBlock* insertion_point = entry->rpo_next(); |
689 BlockList* insert_after = insert_before ? insert_before->next : NULL; | 672 BasicBlock* order = insertion_point; |
690 BlockList* order = insert_after; | |
691 | 673 |
692 // Perform an iterative RPO traversal using an explicit stack, | 674 // Perform an iterative RPO traversal using an explicit stack, |
693 // recording backedges that form cycles. O(|B|). | 675 // recording backedges that form cycles. O(|B|). |
694 DCHECK_LT(previous_block_count_, schedule_->BasicBlockCount()); | 676 DCHECK_LT(previous_block_count_, schedule_->BasicBlockCount()); |
695 stack_.resize(schedule_->BasicBlockCount() - previous_block_count_); | 677 stack_.resize(schedule_->BasicBlockCount() - previous_block_count_); |
696 previous_block_count_ = schedule_->BasicBlockCount(); | 678 previous_block_count_ = schedule_->BasicBlockCount(); |
697 int stack_depth = Push(stack_, 0, entry, kBlockUnvisited1); | 679 int stack_depth = Push(stack_, 0, entry, kBlockUnvisited1); |
698 int num_loops = static_cast<int>(loops_.size()); | 680 int num_loops = static_cast<int>(loops_.size()); |
699 | 681 |
700 while (stack_depth > 0) { | 682 while (stack_depth > 0) { |
(...skipping 12 matching lines...) Expand all Loading... |
713 // Assign a new loop number to the header if it doesn't have one. | 695 // Assign a new loop number to the header if it doesn't have one. |
714 SetLoopNumber(succ, num_loops++); | 696 SetLoopNumber(succ, num_loops++); |
715 } | 697 } |
716 } else { | 698 } else { |
717 // Push the successor onto the stack. | 699 // Push the successor onto the stack. |
718 DCHECK(succ->rpo_number() == kBlockUnvisited1); | 700 DCHECK(succ->rpo_number() == kBlockUnvisited1); |
719 stack_depth = Push(stack_, stack_depth, succ, kBlockUnvisited1); | 701 stack_depth = Push(stack_, stack_depth, succ, kBlockUnvisited1); |
720 } | 702 } |
721 } else { | 703 } else { |
722 // Finished with all successors; pop the stack and add the block. | 704 // Finished with all successors; pop the stack and add the block. |
723 order = order->Add(zone_, frame->block); | 705 order = PushFront(order, frame->block); |
724 frame->block->set_rpo_number(kBlockVisited1); | 706 frame->block->set_rpo_number(kBlockVisited1); |
725 stack_depth--; | 707 stack_depth--; |
726 } | 708 } |
727 } | 709 } |
728 | 710 |
729 // If no loops were encountered, then the order we computed was correct. | 711 // If no loops were encountered, then the order we computed was correct. |
730 if (num_loops > static_cast<int>(loops_.size())) { | 712 if (num_loops > static_cast<int>(loops_.size())) { |
731 // Otherwise, compute the loop information from the backedges in order | 713 // Otherwise, compute the loop information from the backedges in order |
732 // to perform a traversal that groups loop bodies together. | 714 // to perform a traversal that groups loop bodies together. |
733 ComputeLoopInfo(stack_, num_loops, &backedges_); | 715 ComputeLoopInfo(stack_, num_loops, &backedges_); |
734 | 716 |
735 // Initialize the "loop stack". Note the entry could be a loop header. | 717 // Initialize the "loop stack". Note the entry could be a loop header. |
736 LoopInfo* loop = | 718 LoopInfo* loop = |
737 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL; | 719 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL; |
738 order = insert_after; | 720 order = insertion_point; |
739 | 721 |
740 // Perform an iterative post-order traversal, visiting loop bodies before | 722 // Perform an iterative post-order traversal, visiting loop bodies before |
741 // edges that lead out of loops. Visits each block once, but linking loop | 723 // edges that lead out of loops. Visits each block once, but linking loop |
742 // sections together is linear in the loop size, so overall is | 724 // sections together is linear in the loop size, so overall is |
743 // O(|B| + max(loop_depth) * max(|loop|)) | 725 // O(|B| + max(loop_depth) * max(|loop|)) |
744 stack_depth = Push(stack_, 0, entry, kBlockUnvisited2); | 726 stack_depth = Push(stack_, 0, entry, kBlockUnvisited2); |
745 while (stack_depth > 0) { | 727 while (stack_depth > 0) { |
746 SpecialRPOStackFrame* frame = &stack_[stack_depth - 1]; | 728 SpecialRPOStackFrame* frame = &stack_[stack_depth - 1]; |
747 BasicBlock* block = frame->block; | 729 BasicBlock* block = frame->block; |
748 BasicBlock* succ = NULL; | 730 BasicBlock* succ = NULL; |
749 | 731 |
750 if (block != end && frame->index < block->SuccessorCount()) { | 732 if (block != end && frame->index < block->SuccessorCount()) { |
751 // Process the next normal successor. | 733 // Process the next normal successor. |
752 succ = block->SuccessorAt(frame->index++); | 734 succ = block->SuccessorAt(frame->index++); |
753 } else if (HasLoopNumber(block)) { | 735 } else if (HasLoopNumber(block)) { |
754 // Process additional outgoing edges from the loop header. | 736 // Process additional outgoing edges from the loop header. |
755 if (block->rpo_number() == kBlockOnStack) { | 737 if (block->rpo_number() == kBlockOnStack) { |
756 // Finish the loop body the first time the header is left on the | 738 // Finish the loop body the first time the header is left on the |
757 // stack. | 739 // stack. |
758 DCHECK(loop != NULL && loop->header == block); | 740 DCHECK(loop != NULL && loop->header == block); |
759 loop->start = order->Add(zone_, block); | 741 loop->start = PushFront(order, block); |
760 order = loop->end; | 742 order = loop->end; |
761 block->set_rpo_number(kBlockVisited2); | 743 block->set_rpo_number(kBlockVisited2); |
762 // Pop the loop stack and continue visiting outgoing edges within | 744 // Pop the loop stack and continue visiting outgoing edges within |
763 // the context of the outer loop, if any. | 745 // the context of the outer loop, if any. |
764 loop = loop->prev; | 746 loop = loop->prev; |
765 // We leave the loop header on the stack; the rest of this iteration | 747 // We leave the loop header on the stack; the rest of this iteration |
766 // and later iterations will go through its outgoing edges list. | 748 // and later iterations will go through its outgoing edges list. |
767 } | 749 } |
768 | 750 |
769 // Use the next outgoing edge if there are any. | 751 // Use the next outgoing edge if there are any. |
(...skipping 27 matching lines...) Expand all Loading... |
797 next->end = order; | 779 next->end = order; |
798 next->prev = loop; | 780 next->prev = loop; |
799 loop = next; | 781 loop = next; |
800 } | 782 } |
801 } | 783 } |
802 } else { | 784 } else { |
803 // Finished with all successors of the current block. | 785 // Finished with all successors of the current block. |
804 if (HasLoopNumber(block)) { | 786 if (HasLoopNumber(block)) { |
805 // If we are going to pop a loop header, then add its entire body. | 787 // If we are going to pop a loop header, then add its entire body. |
806 LoopInfo* info = &loops_[GetLoopNumber(block)]; | 788 LoopInfo* info = &loops_[GetLoopNumber(block)]; |
807 for (BlockList* l = info->start; true; l = l->next) { | 789 for (BasicBlock* b = info->start; true; b = b->rpo_next()) { |
808 if (l->next == info->end) { | 790 if (b->rpo_next() == info->end) { |
809 l->next = order; | 791 b->set_rpo_next(order); |
810 info->end = order; | 792 info->end = order; |
811 break; | 793 break; |
812 } | 794 } |
813 } | 795 } |
814 order = info->start; | 796 order = info->start; |
815 } else { | 797 } else { |
816 // Pop a single node off the stack and add it to the order. | 798 // Pop a single node off the stack and add it to the order. |
817 order = order->Add(zone_, block); | 799 order = PushFront(order, block); |
818 block->set_rpo_number(kBlockVisited2); | 800 block->set_rpo_number(kBlockVisited2); |
819 } | 801 } |
820 stack_depth--; | 802 stack_depth--; |
821 } | 803 } |
822 } | 804 } |
823 } | 805 } |
824 | 806 |
825 // Insert result into existing order. | 807 // Publish new order the first time. |
826 if (insert_before == NULL) { | 808 if (order_ == NULL) order_ = order; |
827 order_ = order; | |
828 } else { | |
829 // There already is a list element for the entry block in the list, hence | |
830 // we skip the first element of the sub-list to compensate duplication. | |
831 DCHECK_EQ(insert_before->block, order->block); | |
832 insert_before->next = order->next; | |
833 } | |
834 | 809 |
835 // Compute the correct loop headers and set the correct loop ends. | 810 // Compute the correct loop headers and set the correct loop ends. |
836 LoopInfo* current_loop = NULL; | 811 LoopInfo* current_loop = NULL; |
837 BasicBlock* current_header = entry->loop_header(); | 812 BasicBlock* current_header = entry->loop_header(); |
838 int32_t loop_depth = entry->loop_depth(); | 813 int32_t loop_depth = entry->loop_depth(); |
839 if (entry->IsLoopHeader()) --loop_depth; // Entry might be a loop header. | 814 if (entry->IsLoopHeader()) --loop_depth; // Entry might be a loop header. |
840 for (BlockList* l = order; l != insert_after; l = l->next) { | 815 for (BasicBlock* b = order; b != insertion_point; b = b->rpo_next()) { |
841 BasicBlock* current = l->block; | 816 BasicBlock* current = b; |
842 | 817 |
843 // Reset BasicBlock::rpo_number again. | 818 // Reset BasicBlock::rpo_number again. |
844 current->set_rpo_number(kBlockUnvisited1); | 819 current->set_rpo_number(kBlockUnvisited1); |
845 | 820 |
846 // Finish the previous loop(s) if we just exited them. | 821 // Finish the previous loop(s) if we just exited them. |
847 while (current_header != NULL && current == current_header->loop_end()) { | 822 while (current_header != NULL && current == current_header->loop_end()) { |
848 DCHECK(current_header->IsLoopHeader()); | 823 DCHECK(current_header->IsLoopHeader()); |
849 DCHECK(current_loop != NULL); | 824 DCHECK(current_loop != NULL); |
850 current_loop = current_loop->prev; | 825 current_loop = current_loop->prev; |
851 current_header = current_loop == NULL ? NULL : current_loop->header; | 826 current_header = current_loop == NULL ? NULL : current_loop->header; |
852 --loop_depth; | 827 --loop_depth; |
853 } | 828 } |
854 current->set_loop_header(current_header); | 829 current->set_loop_header(current_header); |
855 | 830 |
856 // Push a new loop onto the stack if this loop is a loop header. | 831 // Push a new loop onto the stack if this loop is a loop header. |
857 if (HasLoopNumber(current)) { | 832 if (HasLoopNumber(current)) { |
858 ++loop_depth; | 833 ++loop_depth; |
859 current_loop = &loops_[GetLoopNumber(current)]; | 834 current_loop = &loops_[GetLoopNumber(current)]; |
860 BlockList* end = current_loop->end; | 835 BasicBlock* end = current_loop->end; |
861 current->set_loop_end(end == NULL ? BeyondEndSentinel() : end->block); | 836 current->set_loop_end(end == NULL ? BeyondEndSentinel() : end); |
862 current_header = current_loop->header; | 837 current_header = current_loop->header; |
863 Trace("B%d is a loop header, increment loop depth to %d\n", | 838 Trace("B%d is a loop header, increment loop depth to %d\n", |
864 current->id().ToInt(), loop_depth); | 839 current->id().ToInt(), loop_depth); |
865 } | 840 } |
866 | 841 |
867 current->set_loop_depth(loop_depth); | 842 current->set_loop_depth(loop_depth); |
868 | 843 |
869 if (current->loop_header() == NULL) { | 844 if (current->loop_header() == NULL) { |
870 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), | 845 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), |
871 current->loop_depth()); | 846 current->loop_depth()); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
936 if (loops_.size() > 0) { | 911 if (loops_.size() > 0) { |
937 os << " ("; | 912 os << " ("; |
938 for (size_t i = 0; i < loops_.size(); i++) { | 913 for (size_t i = 0; i < loops_.size(); i++) { |
939 if (i > 0) os << " "; | 914 if (i > 0) os << " "; |
940 os << "B" << loops_[i].header->id(); | 915 os << "B" << loops_[i].header->id(); |
941 } | 916 } |
942 os << ")"; | 917 os << ")"; |
943 } | 918 } |
944 os << ":\n"; | 919 os << ":\n"; |
945 | 920 |
946 for (BlockList* l = order_; l != NULL; l = l->next) { | 921 for (BasicBlock* block = order_; block != NULL; block = block->rpo_next()) { |
947 BasicBlock* block = l->block; | |
948 BasicBlock::Id bid = block->id(); | 922 BasicBlock::Id bid = block->id(); |
949 // TODO(jarin,svenpanne): Add formatting here once we have support for | 923 // TODO(jarin,svenpanne): Add formatting here once we have support for |
950 // that in streams (we want an equivalent of PrintF("%5d:", x) here). | 924 // that in streams (we want an equivalent of PrintF("%5d:", x) here). |
951 os << " " << block->rpo_number() << ":"; | 925 os << " " << block->rpo_number() << ":"; |
952 for (size_t i = 0; i < loops_.size(); i++) { | 926 for (size_t i = 0; i < loops_.size(); i++) { |
953 bool range = loops_[i].header->LoopContains(block); | 927 bool range = loops_[i].header->LoopContains(block); |
954 bool membership = loops_[i].header != block && range; | 928 bool membership = loops_[i].header != block && range; |
955 os << (membership ? " |" : " "); | 929 os << (membership ? " |" : " "); |
956 os << (range ? "x" : " "); | 930 os << (range ? "x" : " "); |
957 } | 931 } |
(...skipping 25 matching lines...) Expand all Loading... |
983 DCHECK(header != NULL); | 957 DCHECK(header != NULL); |
984 DCHECK(header->rpo_number() >= 0); | 958 DCHECK(header->rpo_number() >= 0); |
985 DCHECK(header->rpo_number() < static_cast<int>(order->size())); | 959 DCHECK(header->rpo_number() < static_cast<int>(order->size())); |
986 DCHECK(end != NULL); | 960 DCHECK(end != NULL); |
987 DCHECK(end->rpo_number() <= static_cast<int>(order->size())); | 961 DCHECK(end->rpo_number() <= static_cast<int>(order->size())); |
988 DCHECK(end->rpo_number() > header->rpo_number()); | 962 DCHECK(end->rpo_number() > header->rpo_number()); |
989 DCHECK(header->loop_header() != header); | 963 DCHECK(header->loop_header() != header); |
990 | 964 |
991 // Verify the start ... end list relationship. | 965 // Verify the start ... end list relationship. |
992 int links = 0; | 966 int links = 0; |
993 BlockList* l = loop->start; | 967 BasicBlock* block = loop->start; |
994 DCHECK(l != NULL && l->block == header); | 968 DCHECK_EQ(header, block); |
995 bool end_found; | 969 bool end_found; |
996 while (true) { | 970 while (true) { |
997 if (l == NULL || l == loop->end) { | 971 if (block == NULL || block == loop->end) { |
998 end_found = (loop->end == l); | 972 end_found = (loop->end == block); |
999 break; | 973 break; |
1000 } | 974 } |
1001 // The list should be in same order as the final result. | 975 // The list should be in same order as the final result. |
1002 DCHECK(l->block->rpo_number() == links + header->rpo_number()); | 976 DCHECK(block->rpo_number() == links + header->rpo_number()); |
1003 links++; | 977 links++; |
1004 l = l->next; | 978 block = block->rpo_next(); |
1005 DCHECK(links < static_cast<int>(2 * order->size())); // cycle? | 979 DCHECK(links < static_cast<int>(2 * order->size())); // cycle? |
1006 } | 980 } |
1007 DCHECK(links > 0); | 981 DCHECK(links > 0); |
1008 DCHECK(links == end->rpo_number() - header->rpo_number()); | 982 DCHECK(links == end->rpo_number() - header->rpo_number()); |
1009 DCHECK(end_found); | 983 DCHECK(end_found); |
1010 | 984 |
1011 // Check loop depth of the header. | 985 // Check loop depth of the header. |
1012 int loop_depth = 0; | 986 int loop_depth = 0; |
1013 for (LoopInfo* outer = loop; outer != NULL; outer = outer->prev) { | 987 for (LoopInfo* outer = loop; outer != NULL; outer = outer->prev) { |
1014 loop_depth++; | 988 loop_depth++; |
(...skipping 13 matching lines...) Expand all Loading... |
1028 count++; | 1002 count++; |
1029 } | 1003 } |
1030 } | 1004 } |
1031 DCHECK(links == count); | 1005 DCHECK(links == count); |
1032 } | 1006 } |
1033 } | 1007 } |
1034 #endif // DEBUG | 1008 #endif // DEBUG |
1035 | 1009 |
1036 Zone* zone_; | 1010 Zone* zone_; |
1037 Schedule* schedule_; | 1011 Schedule* schedule_; |
1038 BlockList* order_; | 1012 BasicBlock* order_; |
| 1013 BasicBlock* beyond_end_; |
1039 ZoneVector<LoopInfo> loops_; | 1014 ZoneVector<LoopInfo> loops_; |
1040 BasicBlock* beyond_end_; | |
1041 ZoneList<Backedge> backedges_; | 1015 ZoneList<Backedge> backedges_; |
1042 ZoneVector<SpecialRPOStackFrame> stack_; | 1016 ZoneVector<SpecialRPOStackFrame> stack_; |
1043 size_t previous_block_count_; | 1017 size_t previous_block_count_; |
1044 }; | 1018 }; |
1045 | 1019 |
1046 | 1020 |
1047 BasicBlockVector* Scheduler::ComputeSpecialRPO(Zone* zone, Schedule* schedule) { | 1021 BasicBlockVector* Scheduler::ComputeSpecialRPO(Zone* zone, Schedule* schedule) { |
1048 SpecialRPONumberer numberer(zone, schedule); | 1022 SpecialRPONumberer numberer(zone, schedule); |
1049 numberer.ComputeSpecialRPO(); | 1023 numberer.ComputeSpecialRPO(); |
1050 numberer.SerializeAOIntoSchedule(); | 1024 numberer.SerializeAOIntoSchedule(); |
(...skipping 12 matching lines...) Expand all Loading... |
1063 } | 1037 } |
1064 | 1038 |
1065 | 1039 |
1066 void Scheduler::GenerateImmediateDominatorTree() { | 1040 void Scheduler::GenerateImmediateDominatorTree() { |
1067 Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n"); | 1041 Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n"); |
1068 | 1042 |
1069 // TODO(danno): Consider using Lengauer & Tarjan's if this becomes too slow. | 1043 // TODO(danno): Consider using Lengauer & Tarjan's if this becomes too slow. |
1070 | 1044 |
1071 // Build the block dominator tree. | 1045 // Build the block dominator tree. |
1072 schedule_->start()->set_dominator_depth(0); | 1046 schedule_->start()->set_dominator_depth(0); |
1073 typedef SpecialRPONumberer::BlockList BlockList; | 1047 BasicBlock* second = schedule_->start()->rpo_next(); |
1074 DCHECK_EQ(schedule_->start(), special_rpo_->order_->block); | 1048 for (BasicBlock* block = second; block != NULL; block = block->rpo_next()) { |
1075 for (BlockList* l = special_rpo_->order_->next; l != NULL; l = l->next) { | 1049 BasicBlock::Predecessors::iterator pred = block->predecessors_begin(); |
1076 BasicBlock* current = l->block; | 1050 BasicBlock::Predecessors::iterator end = block->predecessors_end(); |
1077 BasicBlock::Predecessors::iterator pred = current->predecessors_begin(); | |
1078 BasicBlock::Predecessors::iterator end = current->predecessors_end(); | |
1079 DCHECK(pred != end); // All blocks except start have predecessors. | 1051 DCHECK(pred != end); // All blocks except start have predecessors. |
1080 BasicBlock* dominator = *pred; | 1052 BasicBlock* dominator = *pred; |
1081 // For multiple predecessors, walk up the dominator tree until a common | 1053 // For multiple predecessors, walk up the dominator tree until a common |
1082 // dominator is found. Visitation order guarantees that all predecessors | 1054 // dominator is found. Visitation order guarantees that all predecessors |
1083 // except for backwards edges have been visited. | 1055 // except for backwards edges have been visited. |
1084 for (++pred; pred != end; ++pred) { | 1056 for (++pred; pred != end; ++pred) { |
1085 // Don't examine backwards edges. | 1057 // Don't examine backwards edges. |
1086 if ((*pred)->dominator_depth() < 0) continue; | 1058 if ((*pred)->dominator_depth() < 0) continue; |
1087 dominator = GetCommonDominator(dominator, *pred); | 1059 dominator = GetCommonDominator(dominator, *pred); |
1088 } | 1060 } |
1089 current->set_dominator(dominator); | 1061 block->set_dominator(dominator); |
1090 current->set_dominator_depth(dominator->dominator_depth() + 1); | 1062 block->set_dominator_depth(dominator->dominator_depth() + 1); |
1091 // Propagate "deferredness" of the dominator. | 1063 // Propagate "deferredness" of the dominator. |
1092 if (dominator->deferred()) current->set_deferred(true); | 1064 if (dominator->deferred()) block->set_deferred(true); |
1093 Trace("Block B%d's idom is B%d, depth = %d\n", current->id().ToInt(), | 1065 Trace("Block B%d's idom is B%d, depth = %d\n", block->id().ToInt(), |
1094 dominator->id().ToInt(), current->dominator_depth()); | 1066 dominator->id().ToInt(), block->dominator_depth()); |
1095 } | 1067 } |
1096 } | 1068 } |
1097 | 1069 |
1098 | 1070 |
1099 // ----------------------------------------------------------------------------- | 1071 // ----------------------------------------------------------------------------- |
1100 // Phase 3: Prepare use counts for nodes. | 1072 // Phase 3: Prepare use counts for nodes. |
1101 | 1073 |
1102 | 1074 |
1103 class PrepareUsesVisitor : public NullNodeVisitor { | 1075 class PrepareUsesVisitor : public NullNodeVisitor { |
1104 public: | 1076 public: |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { | 1482 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { |
1511 schedule_->SetBlockForNode(to, *i); | 1483 schedule_->SetBlockForNode(to, *i); |
1512 scheduled_nodes_[to->id().ToSize()].push_back(*i); | 1484 scheduled_nodes_[to->id().ToSize()].push_back(*i); |
1513 } | 1485 } |
1514 nodes->clear(); | 1486 nodes->clear(); |
1515 } | 1487 } |
1516 | 1488 |
1517 } // namespace compiler | 1489 } // namespace compiler |
1518 } // namespace internal | 1490 } // namespace internal |
1519 } // namespace v8 | 1491 } // namespace v8 |
OLD | NEW |