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