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 509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 // 2. All loops are contiguous in the order (i.e. no intervening blocks that | 520 // 2. All loops are contiguous in the order (i.e. no intervening blocks that |
521 // do not belong to the loop.) | 521 // do not belong to the loop.) |
522 // Note a simple RPO traversal satisfies (1) but not (2). | 522 // Note a simple RPO traversal satisfies (1) but not (2). |
523 class SpecialRPONumberer : public ZoneObject { | 523 class SpecialRPONumberer : public ZoneObject { |
524 public: | 524 public: |
525 SpecialRPONumberer(Zone* zone, Schedule* schedule) | 525 SpecialRPONumberer(Zone* zone, Schedule* schedule) |
526 : zone_(zone), | 526 : zone_(zone), |
527 schedule_(schedule), | 527 schedule_(schedule), |
528 order_(NULL), | 528 order_(NULL), |
529 loops_(zone), | 529 loops_(zone), |
530 beyond_end_(NULL) {} | 530 beyond_end_(NULL), |
| 531 backedges_(1, zone), |
| 532 stack_(zone), |
| 533 previous_block_count_(0) {} |
531 | 534 |
532 // Computes the special reverse-post-order for the main control flow graph, | 535 // Computes the special reverse-post-order for the main control flow graph, |
533 // that is for the graph spanned between the schedule's start and end blocks. | 536 // that is for the graph spanned between the schedule's start and end blocks. |
534 void ComputeSpecialRPO() { | 537 void ComputeSpecialRPO() { |
535 DCHECK_EQ(NULL, order_); // Main order does not exist yet. | 538 DCHECK_EQ(NULL, order_); // Main order does not exist yet. |
536 // TODO(mstarzinger): Should use Schedule::end() after tests are fixed. | 539 // TODO(mstarzinger): Should use Schedule::end() after tests are fixed. |
537 ComputeAndInsertSpecialRPO(schedule_->start(), NULL); | 540 ComputeAndInsertSpecialRPO(schedule_->start(), NULL); |
538 } | 541 } |
539 | 542 |
540 // Computes the special reverse-post-order for a partial control flow graph, | 543 // Computes the special reverse-post-order for a partial control flow graph, |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 | 575 |
573 // Print and verify the special reverse-post-order. | 576 // Print and verify the special reverse-post-order. |
574 void PrintAndVerifySpecialRPO() { | 577 void PrintAndVerifySpecialRPO() { |
575 #if DEBUG | 578 #if DEBUG |
576 if (FLAG_trace_turbo_scheduler) PrintRPO(); | 579 if (FLAG_trace_turbo_scheduler) PrintRPO(); |
577 VerifySpecialRPO(); | 580 VerifySpecialRPO(); |
578 #endif | 581 #endif |
579 } | 582 } |
580 | 583 |
581 private: | 584 private: |
| 585 typedef std::pair<BasicBlock*, size_t> Backedge; |
| 586 |
582 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree. | 587 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree. |
583 friend class Scheduler; | 588 friend class Scheduler; |
584 | 589 |
585 // Numbering for BasicBlock::rpo_number for this block traversal: | 590 // Numbering for BasicBlock::rpo_number for this block traversal: |
586 static const int kBlockOnStack = -2; | 591 static const int kBlockOnStack = -2; |
587 static const int kBlockVisited1 = -3; | 592 static const int kBlockVisited1 = -3; |
588 static const int kBlockVisited2 = -4; | 593 static const int kBlockVisited2 = -4; |
589 static const int kBlockUnvisited1 = -1; | 594 static const int kBlockUnvisited1 = -1; |
590 static const int kBlockUnvisited2 = kBlockVisited1; | 595 static const int kBlockUnvisited2 = kBlockVisited1; |
591 | 596 |
(...skipping 30 matching lines...) Expand all Loading... |
622 BlockList* start; | 627 BlockList* start; |
623 | 628 |
624 void AddOutgoing(Zone* zone, BasicBlock* block) { | 629 void AddOutgoing(Zone* zone, BasicBlock* block) { |
625 if (outgoing == NULL) { | 630 if (outgoing == NULL) { |
626 outgoing = new (zone) ZoneList<BasicBlock*>(2, zone); | 631 outgoing = new (zone) ZoneList<BasicBlock*>(2, zone); |
627 } | 632 } |
628 outgoing->Add(block, zone); | 633 outgoing->Add(block, zone); |
629 } | 634 } |
630 }; | 635 }; |
631 | 636 |
632 int Push(SpecialRPOStackFrame* stack, int depth, BasicBlock* child, | 637 int Push(ZoneVector<SpecialRPOStackFrame>& stack, int depth, |
633 int unvisited) { | 638 BasicBlock* child, int unvisited) { |
634 if (child->rpo_number() == unvisited) { | 639 if (child->rpo_number() == unvisited) { |
635 stack[depth].block = child; | 640 stack[depth].block = child; |
636 stack[depth].index = 0; | 641 stack[depth].index = 0; |
637 child->set_rpo_number(kBlockOnStack); | 642 child->set_rpo_number(kBlockOnStack); |
638 return depth + 1; | 643 return depth + 1; |
639 } | 644 } |
640 return depth; | 645 return depth; |
641 } | 646 } |
642 | 647 |
643 // We are hijacking the {ao_number} to enumerate loops temporarily. Note that | 648 // We are hijacking the {ao_number} to enumerate loops temporarily. Note that |
(...skipping 25 matching lines...) Expand all Loading... |
669 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); | 674 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); |
670 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); | 675 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); |
671 | 676 |
672 // Find correct insertion point within existing order. | 677 // Find correct insertion point within existing order. |
673 BlockList* insert_before = order_->FindForBlock(entry); | 678 BlockList* insert_before = order_->FindForBlock(entry); |
674 BlockList* insert_after = insert_before ? insert_before->next : NULL; | 679 BlockList* insert_after = insert_before ? insert_before->next : NULL; |
675 BlockList* order = insert_after; | 680 BlockList* order = insert_after; |
676 | 681 |
677 // Perform an iterative RPO traversal using an explicit stack, | 682 // Perform an iterative RPO traversal using an explicit stack, |
678 // recording backedges that form cycles. O(|B|). | 683 // recording backedges that form cycles. O(|B|). |
679 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone_); | 684 DCHECK_LT(previous_block_count_, schedule_->BasicBlockCount()); |
680 SpecialRPOStackFrame* stack = zone_->NewArray<SpecialRPOStackFrame>( | 685 stack_.resize(schedule_->BasicBlockCount() - previous_block_count_); |
681 static_cast<int>(schedule_->BasicBlockCount())); | 686 previous_block_count_ = schedule_->BasicBlockCount(); |
682 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); | 687 int stack_depth = Push(stack_, 0, entry, kBlockUnvisited1); |
683 int num_loops = 0; | 688 int num_loops = 0; |
684 | 689 |
685 while (stack_depth > 0) { | 690 while (stack_depth > 0) { |
686 int current = stack_depth - 1; | 691 int current = stack_depth - 1; |
687 SpecialRPOStackFrame* frame = stack + current; | 692 SpecialRPOStackFrame* frame = &stack_[current]; |
688 | 693 |
689 if (frame->block != end && | 694 if (frame->block != end && |
690 frame->index < frame->block->SuccessorCount()) { | 695 frame->index < frame->block->SuccessorCount()) { |
691 // Process the next successor. | 696 // Process the next successor. |
692 BasicBlock* succ = frame->block->SuccessorAt(frame->index++); | 697 BasicBlock* succ = frame->block->SuccessorAt(frame->index++); |
693 if (succ->rpo_number() == kBlockVisited1) continue; | 698 if (succ->rpo_number() == kBlockVisited1) continue; |
694 if (succ->rpo_number() == kBlockOnStack) { | 699 if (succ->rpo_number() == kBlockOnStack) { |
695 // The successor is on the stack, so this is a backedge (cycle). | 700 // The successor is on the stack, so this is a backedge (cycle). |
696 backedges.Add( | 701 backedges_.Add(Backedge(frame->block, frame->index - 1), zone_); |
697 std::pair<BasicBlock*, size_t>(frame->block, frame->index - 1), | |
698 zone_); | |
699 if (!HasLoopNumber(succ)) { | 702 if (!HasLoopNumber(succ)) { |
700 // Assign a new loop number to the header if it doesn't have one. | 703 // Assign a new loop number to the header if it doesn't have one. |
701 SetLoopNumber(succ, num_loops++); | 704 SetLoopNumber(succ, num_loops++); |
702 } | 705 } |
703 } else { | 706 } else { |
704 // Push the successor onto the stack. | 707 // Push the successor onto the stack. |
705 DCHECK(succ->rpo_number() == kBlockUnvisited1); | 708 DCHECK(succ->rpo_number() == kBlockUnvisited1); |
706 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); | 709 stack_depth = Push(stack_, stack_depth, succ, kBlockUnvisited1); |
707 } | 710 } |
708 } else { | 711 } else { |
709 // Finished with all successors; pop the stack and add the block. | 712 // Finished with all successors; pop the stack and add the block. |
710 order = order->Add(zone_, frame->block); | 713 order = order->Add(zone_, frame->block); |
711 frame->block->set_rpo_number(kBlockVisited1); | 714 frame->block->set_rpo_number(kBlockVisited1); |
712 stack_depth--; | 715 stack_depth--; |
713 } | 716 } |
714 } | 717 } |
715 | 718 |
716 // If no loops were encountered, then the order we computed was correct. | 719 // If no loops were encountered, then the order we computed was correct. |
717 if (num_loops != 0) { | 720 if (num_loops != 0) { |
718 // Otherwise, compute the loop information from the backedges in order | 721 // Otherwise, compute the loop information from the backedges in order |
719 // to perform a traversal that groups loop bodies together. | 722 // to perform a traversal that groups loop bodies together. |
720 ComputeLoopInfo(stack, num_loops, &backedges); | 723 ComputeLoopInfo(stack_, num_loops, &backedges_); |
721 | 724 |
722 // Initialize the "loop stack". Note the entry could be a loop header. | 725 // Initialize the "loop stack". Note the entry could be a loop header. |
723 LoopInfo* loop = | 726 LoopInfo* loop = |
724 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL; | 727 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL; |
725 order = NULL; | 728 order = NULL; |
726 | 729 |
727 // Perform an iterative post-order traversal, visiting loop bodies before | 730 // Perform an iterative post-order traversal, visiting loop bodies before |
728 // edges that lead out of loops. Visits each block once, but linking loop | 731 // edges that lead out of loops. Visits each block once, but linking loop |
729 // sections together is linear in the loop size, so overall is | 732 // sections together is linear in the loop size, so overall is |
730 // O(|B| + max(loop_depth) * max(|loop|)) | 733 // O(|B| + max(loop_depth) * max(|loop|)) |
731 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); | 734 stack_depth = Push(stack_, 0, entry, kBlockUnvisited2); |
732 while (stack_depth > 0) { | 735 while (stack_depth > 0) { |
733 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); | 736 SpecialRPOStackFrame* frame = &stack_[stack_depth - 1]; |
734 BasicBlock* block = frame->block; | 737 BasicBlock* block = frame->block; |
735 BasicBlock* succ = NULL; | 738 BasicBlock* succ = NULL; |
736 | 739 |
737 if (frame->index < block->SuccessorCount()) { | 740 if (frame->index < block->SuccessorCount()) { |
738 // Process the next normal successor. | 741 // Process the next normal successor. |
739 succ = block->SuccessorAt(frame->index++); | 742 succ = block->SuccessorAt(frame->index++); |
740 } else if (HasLoopNumber(block)) { | 743 } else if (HasLoopNumber(block)) { |
741 // Process additional outgoing edges from the loop header. | 744 // Process additional outgoing edges from the loop header. |
742 if (block->rpo_number() == kBlockOnStack) { | 745 if (block->rpo_number() == kBlockOnStack) { |
743 // Finish the loop body the first time the header is left on the | 746 // Finish the loop body the first time the header is left on the |
(...skipping 25 matching lines...) Expand all Loading... |
769 // Process the next successor. | 772 // Process the next successor. |
770 if (succ->rpo_number() == kBlockOnStack) continue; | 773 if (succ->rpo_number() == kBlockOnStack) continue; |
771 if (succ->rpo_number() == kBlockVisited2) continue; | 774 if (succ->rpo_number() == kBlockVisited2) continue; |
772 DCHECK(succ->rpo_number() == kBlockUnvisited2); | 775 DCHECK(succ->rpo_number() == kBlockUnvisited2); |
773 if (loop != NULL && !loop->members->Contains(succ->id().ToInt())) { | 776 if (loop != NULL && !loop->members->Contains(succ->id().ToInt())) { |
774 // The successor is not in the current loop or any nested loop. | 777 // The successor is not in the current loop or any nested loop. |
775 // Add it to the outgoing edges of this loop and visit it later. | 778 // Add it to the outgoing edges of this loop and visit it later. |
776 loop->AddOutgoing(zone_, succ); | 779 loop->AddOutgoing(zone_, succ); |
777 } else { | 780 } else { |
778 // Push the successor onto the stack. | 781 // Push the successor onto the stack. |
779 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); | 782 stack_depth = Push(stack_, stack_depth, succ, kBlockUnvisited2); |
780 if (HasLoopNumber(succ)) { | 783 if (HasLoopNumber(succ)) { |
781 // Push the inner loop onto the loop stack. | 784 // Push the inner loop onto the loop stack. |
782 DCHECK(GetLoopNumber(succ) < num_loops); | 785 DCHECK(GetLoopNumber(succ) < num_loops); |
783 LoopInfo* next = &loops_[GetLoopNumber(succ)]; | 786 LoopInfo* next = &loops_[GetLoopNumber(succ)]; |
784 next->end = order; | 787 next->end = order; |
785 next->prev = loop; | 788 next->prev = loop; |
786 loop = next; | 789 loop = next; |
787 } | 790 } |
788 } | 791 } |
789 } else { | 792 } else { |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
857 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), | 860 Trace("B%d is not in a loop (depth == %d)\n", current->id().ToInt(), |
858 current->loop_depth()); | 861 current->loop_depth()); |
859 } else { | 862 } else { |
860 Trace("B%d has loop header B%d, (depth == %d)\n", current->id().ToInt(), | 863 Trace("B%d has loop header B%d, (depth == %d)\n", current->id().ToInt(), |
861 current->loop_header()->id().ToInt(), current->loop_depth()); | 864 current->loop_header()->id().ToInt(), current->loop_depth()); |
862 } | 865 } |
863 } | 866 } |
864 } | 867 } |
865 | 868 |
866 // Computes loop membership from the backedges of the control flow graph. | 869 // Computes loop membership from the backedges of the control flow graph. |
867 void ComputeLoopInfo(SpecialRPOStackFrame* queue, size_t num_loops, | 870 void ComputeLoopInfo(ZoneVector<SpecialRPOStackFrame>& queue, |
868 ZoneList<std::pair<BasicBlock*, size_t> >* backedges) { | 871 size_t num_loops, ZoneList<Backedge>* backedges) { |
869 loops_.resize(num_loops, LoopInfo()); | 872 loops_.resize(num_loops, LoopInfo()); |
870 | 873 |
871 // Compute loop membership starting from backedges. | 874 // Compute loop membership starting from backedges. |
872 // O(max(loop_depth) * max(|loop|) | 875 // O(max(loop_depth) * max(|loop|) |
873 for (int i = 0; i < backedges->length(); i++) { | 876 for (int i = 0; i < backedges->length(); i++) { |
874 BasicBlock* member = backedges->at(i).first; | 877 BasicBlock* member = backedges->at(i).first; |
875 BasicBlock* header = member->SuccessorAt(backedges->at(i).second); | 878 BasicBlock* header = member->SuccessorAt(backedges->at(i).second); |
876 size_t loop_num = GetLoopNumber(header); | 879 size_t loop_num = GetLoopNumber(header); |
877 if (loops_[loop_num].header == NULL) { | 880 if (loops_[loop_num].header == NULL) { |
878 loops_[loop_num].header = header; | 881 loops_[loop_num].header = header; |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 DCHECK(links == count); | 1012 DCHECK(links == count); |
1010 } | 1013 } |
1011 } | 1014 } |
1012 #endif // DEBUG | 1015 #endif // DEBUG |
1013 | 1016 |
1014 Zone* zone_; | 1017 Zone* zone_; |
1015 Schedule* schedule_; | 1018 Schedule* schedule_; |
1016 BlockList* order_; | 1019 BlockList* order_; |
1017 ZoneVector<LoopInfo> loops_; | 1020 ZoneVector<LoopInfo> loops_; |
1018 BasicBlock* beyond_end_; | 1021 BasicBlock* beyond_end_; |
| 1022 ZoneList<Backedge> backedges_; |
| 1023 ZoneVector<SpecialRPOStackFrame> stack_; |
| 1024 size_t previous_block_count_; |
1019 }; | 1025 }; |
1020 | 1026 |
1021 | 1027 |
1022 BasicBlockVector* Scheduler::ComputeSpecialRPO(ZonePool* zone_pool, | 1028 BasicBlockVector* Scheduler::ComputeSpecialRPO(ZonePool* zone_pool, |
1023 Schedule* schedule) { | 1029 Schedule* schedule) { |
1024 ZonePool::Scope zone_scope(zone_pool); | 1030 ZonePool::Scope zone_scope(zone_pool); |
1025 Zone* zone = zone_scope.zone(); | 1031 Zone* zone = zone_scope.zone(); |
1026 | 1032 |
1027 SpecialRPONumberer numberer(zone, schedule); | 1033 SpecialRPONumberer numberer(zone, schedule); |
1028 numberer.ComputeSpecialRPO(); | 1034 numberer.ComputeSpecialRPO(); |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1468 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { | 1474 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { |
1469 schedule_->SetBlockForNode(to, *i); | 1475 schedule_->SetBlockForNode(to, *i); |
1470 scheduled_nodes_[to->id().ToSize()].push_back(*i); | 1476 scheduled_nodes_[to->id().ToSize()].push_back(*i); |
1471 } | 1477 } |
1472 nodes->clear(); | 1478 nodes->clear(); |
1473 } | 1479 } |
1474 | 1480 |
1475 } // namespace compiler | 1481 } // namespace compiler |
1476 } // namespace internal | 1482 } // namespace internal |
1477 } // namespace v8 | 1483 } // namespace v8 |
OLD | NEW |