| 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 |