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

Side by Side Diff: src/compiler/scheduler.cc

Issue 702683002: Avoid redundant work in scheduler loop header/depth calculation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Remove scary printing again. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | test/cctest/compiler/test-scheduler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <deque> 5 #include <deque>
6 #include <queue> 6 #include <queue>
7 7
8 #include "src/compiler/scheduler.h" 8 #include "src/compiler/scheduler.h"
9 9
10 #include "src/bit-vector.h" 10 #include "src/bit-vector.h"
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 #if DEBUG 575 #if DEBUG
576 if (FLAG_trace_turbo_scheduler) PrintRPO(); 576 if (FLAG_trace_turbo_scheduler) PrintRPO();
577 VerifySpecialRPO(); 577 VerifySpecialRPO();
578 #endif 578 #endif
579 } 579 }
580 580
581 private: 581 private:
582 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree. 582 // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree.
583 friend class Scheduler; 583 friend class Scheduler;
584 584
585 // Numbering for BasicBlockData.rpo_number_ for this block traversal: 585 // Numbering for BasicBlock::rpo_number for this block traversal:
586 static const int kBlockOnStack = -2; 586 static const int kBlockOnStack = -2;
587 static const int kBlockVisited1 = -3; 587 static const int kBlockVisited1 = -3;
588 static const int kBlockVisited2 = -4; 588 static const int kBlockVisited2 = -4;
589 static const int kBlockUnvisited1 = -1; 589 static const int kBlockUnvisited1 = -1;
590 static const int kBlockUnvisited2 = kBlockVisited1; 590 static const int kBlockUnvisited2 = kBlockVisited1;
591 591
592 struct SpecialRPOStackFrame { 592 struct SpecialRPOStackFrame {
593 BasicBlock* block; 593 BasicBlock* block;
594 size_t index; 594 size_t index;
595 }; 595 };
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 // mutating any existing order so that the result is still valid. 665 // mutating any existing order so that the result is still valid.
666 void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) { 666 void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) {
667 // RPO should not have been serialized for this schedule yet. 667 // RPO should not have been serialized for this schedule yet.
668 CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number()); 668 CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number());
669 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number()); 669 CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number());
670 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size())); 670 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size()));
671 671
672 // Find correct insertion point within existing order. 672 // Find correct insertion point within existing order.
673 BlockList* insert_before = order_->FindForBlock(entry); 673 BlockList* insert_before = order_->FindForBlock(entry);
674 BlockList* insert_after = insert_before ? insert_before->next : NULL; 674 BlockList* insert_after = insert_before ? insert_before->next : NULL;
675 BlockList* order = insert_after;
675 676
676 // Perform an iterative RPO traversal using an explicit stack, 677 // Perform an iterative RPO traversal using an explicit stack,
677 // recording backedges that form cycles. O(|B|). 678 // recording backedges that form cycles. O(|B|).
678 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone_); 679 ZoneList<std::pair<BasicBlock*, size_t> > backedges(1, zone_);
679 SpecialRPOStackFrame* stack = zone_->NewArray<SpecialRPOStackFrame>( 680 SpecialRPOStackFrame* stack = zone_->NewArray<SpecialRPOStackFrame>(
680 static_cast<int>(schedule_->BasicBlockCount())); 681 static_cast<int>(schedule_->BasicBlockCount()));
681 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); 682 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1);
682 int num_loops = 0; 683 int num_loops = 0;
683 684
684 while (stack_depth > 0) { 685 while (stack_depth > 0) {
(...skipping 14 matching lines...) Expand all
699 // Assign a new loop number to the header if it doesn't have one. 700 // Assign a new loop number to the header if it doesn't have one.
700 SetLoopNumber(succ, num_loops++); 701 SetLoopNumber(succ, num_loops++);
701 } 702 }
702 } else { 703 } else {
703 // Push the successor onto the stack. 704 // Push the successor onto the stack.
704 DCHECK(succ->rpo_number() == kBlockUnvisited1); 705 DCHECK(succ->rpo_number() == kBlockUnvisited1);
705 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); 706 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1);
706 } 707 }
707 } else { 708 } else {
708 // Finished with all successors; pop the stack and add the block. 709 // Finished with all successors; pop the stack and add the block.
709 insert_after = insert_after->Add(zone_, frame->block); 710 order = order->Add(zone_, frame->block);
710 frame->block->set_rpo_number(kBlockVisited1); 711 frame->block->set_rpo_number(kBlockVisited1);
711 stack_depth--; 712 stack_depth--;
712 } 713 }
713 } 714 }
714 715
715 // Insert the result into any existing order.
716 if (insert_before == NULL) {
717 order_ = insert_after;
718 } else {
719 // There already is a list element for the entry block in the list, hence
720 // we skip the first element of the sub-list to compensate duplication.
721 DCHECK_EQ(insert_before->block, insert_after->block);
722 insert_before->next = insert_after->next;
723 }
724
725 // If no loops were encountered, then the order we computed was correct. 716 // If no loops were encountered, then the order we computed was correct.
726 if (num_loops != 0) { 717 if (num_loops != 0) {
727 // Otherwise, compute the loop information from the backedges in order 718 // Otherwise, compute the loop information from the backedges in order
728 // to perform a traversal that groups loop bodies together. 719 // to perform a traversal that groups loop bodies together.
729 ComputeLoopInfo(stack, num_loops, &backedges); 720 ComputeLoopInfo(stack, num_loops, &backedges);
730 721
731 // Initialize the "loop stack". Note the entry could be a loop header. 722 // Initialize the "loop stack". Note the entry could be a loop header.
732 LoopInfo* loop = 723 LoopInfo* loop =
733 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL; 724 HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL;
734 order_ = NULL; 725 order = NULL;
735 726
736 // Perform an iterative post-order traversal, visiting loop bodies before 727 // Perform an iterative post-order traversal, visiting loop bodies before
737 // edges that lead out of loops. Visits each block once, but linking loop 728 // edges that lead out of loops. Visits each block once, but linking loop
738 // sections together is linear in the loop size, so overall is 729 // sections together is linear in the loop size, so overall is
739 // O(|B| + max(loop_depth) * max(|loop|)) 730 // O(|B| + max(loop_depth) * max(|loop|))
740 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); 731 stack_depth = Push(stack, 0, entry, kBlockUnvisited2);
741 while (stack_depth > 0) { 732 while (stack_depth > 0) {
742 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); 733 SpecialRPOStackFrame* frame = stack + (stack_depth - 1);
743 BasicBlock* block = frame->block; 734 BasicBlock* block = frame->block;
744 BasicBlock* succ = NULL; 735 BasicBlock* succ = NULL;
745 736
746 if (frame->index < block->SuccessorCount()) { 737 if (frame->index < block->SuccessorCount()) {
747 // Process the next normal successor. 738 // Process the next normal successor.
748 succ = block->SuccessorAt(frame->index++); 739 succ = block->SuccessorAt(frame->index++);
749 } else if (HasLoopNumber(block)) { 740 } else if (HasLoopNumber(block)) {
750 // Process additional outgoing edges from the loop header. 741 // Process additional outgoing edges from the loop header.
751 if (block->rpo_number() == kBlockOnStack) { 742 if (block->rpo_number() == kBlockOnStack) {
752 // Finish the loop body the first time the header is left on the 743 // Finish the loop body the first time the header is left on the
753 // stack. 744 // stack.
754 DCHECK(loop != NULL && loop->header == block); 745 DCHECK(loop != NULL && loop->header == block);
755 loop->start = order_->Add(zone_, block); 746 loop->start = order->Add(zone_, block);
756 order_ = loop->end; 747 order = loop->end;
757 block->set_rpo_number(kBlockVisited2); 748 block->set_rpo_number(kBlockVisited2);
758 // Pop the loop stack and continue visiting outgoing edges within 749 // Pop the loop stack and continue visiting outgoing edges within
759 // the context of the outer loop, if any. 750 // the context of the outer loop, if any.
760 loop = loop->prev; 751 loop = loop->prev;
761 // We leave the loop header on the stack; the rest of this iteration 752 // We leave the loop header on the stack; the rest of this iteration
762 // and later iterations will go through its outgoing edges list. 753 // and later iterations will go through its outgoing edges list.
763 } 754 }
764 755
765 // Use the next outgoing edge if there are any. 756 // Use the next outgoing edge if there are any.
766 int outgoing_index = 757 int outgoing_index =
(...skipping 16 matching lines...) Expand all
783 // The successor is not in the current loop or any nested loop. 774 // The successor is not in the current loop or any nested loop.
784 // Add it to the outgoing edges of this loop and visit it later. 775 // Add it to the outgoing edges of this loop and visit it later.
785 loop->AddOutgoing(zone_, succ); 776 loop->AddOutgoing(zone_, succ);
786 } else { 777 } else {
787 // Push the successor onto the stack. 778 // Push the successor onto the stack.
788 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); 779 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2);
789 if (HasLoopNumber(succ)) { 780 if (HasLoopNumber(succ)) {
790 // Push the inner loop onto the loop stack. 781 // Push the inner loop onto the loop stack.
791 DCHECK(GetLoopNumber(succ) < num_loops); 782 DCHECK(GetLoopNumber(succ) < num_loops);
792 LoopInfo* next = &loops_[GetLoopNumber(succ)]; 783 LoopInfo* next = &loops_[GetLoopNumber(succ)];
793 next->end = order_; 784 next->end = order;
794 next->prev = loop; 785 next->prev = loop;
795 loop = next; 786 loop = next;
796 } 787 }
797 } 788 }
798 } else { 789 } else {
799 // Finished with all successors of the current block. 790 // Finished with all successors of the current block.
800 if (HasLoopNumber(block)) { 791 if (HasLoopNumber(block)) {
801 // If we are going to pop a loop header, then add its entire body. 792 // If we are going to pop a loop header, then add its entire body.
802 LoopInfo* info = &loops_[GetLoopNumber(block)]; 793 LoopInfo* info = &loops_[GetLoopNumber(block)];
803 for (BlockList* l = info->start; true; l = l->next) { 794 for (BlockList* l = info->start; true; l = l->next) {
804 if (l->next == info->end) { 795 if (l->next == info->end) {
805 l->next = order_; 796 l->next = order;
806 info->end = order_; 797 info->end = order;
807 break; 798 break;
808 } 799 }
809 } 800 }
810 order_ = info->start; 801 order = info->start;
811 } else { 802 } else {
812 // Pop a single node off the stack and add it to the order. 803 // Pop a single node off the stack and add it to the order.
813 order_ = order_->Add(zone_, block); 804 order = order->Add(zone_, block);
814 block->set_rpo_number(kBlockVisited2); 805 block->set_rpo_number(kBlockVisited2);
815 } 806 }
816 stack_depth--; 807 stack_depth--;
817 } 808 }
818 } 809 }
819 } 810 }
820 811
812 // Insert result into existing order.
813 if (insert_before == NULL) {
814 order_ = order;
815 } else {
816 // There already is a list element for the entry block in the list, hence
817 // we skip the first element of the sub-list to compensate duplication.
818 DCHECK_EQ(insert_before->block, order->block);
819 insert_before->next = order->next;
820 }
821
821 // Compute the correct loop headers and set the correct loop ends. 822 // Compute the correct loop headers and set the correct loop ends.
822 LoopInfo* current_loop = NULL; 823 LoopInfo* current_loop = NULL;
823 BasicBlock* current_header = NULL; 824 BasicBlock* current_header = entry->loop_header();
824 int loop_depth = 0; 825 int32_t loop_depth = entry->loop_depth();
825 for (BlockList* l = order_; l != NULL; l = l->next) { 826 if (entry->IsLoopHeader()) --loop_depth; // Entry might be a loop header.
827 for (BlockList* l = order; l != insert_after; l = l->next) {
826 BasicBlock* current = l->block; 828 BasicBlock* current = l->block;
827 829
830 // Reset BasicBlock::rpo_number again.
831 current->set_rpo_number(kBlockUnvisited1);
832
828 // Finish the previous loop(s) if we just exited them. 833 // Finish the previous loop(s) if we just exited them.
829 while (current_header != NULL && current == current_header->loop_end()) { 834 while (current_header != NULL && current == current_header->loop_end()) {
830 DCHECK(current_header->IsLoopHeader()); 835 DCHECK(current_header->IsLoopHeader());
831 DCHECK(current_loop != NULL); 836 DCHECK(current_loop != NULL);
832 current_loop = current_loop->prev; 837 current_loop = current_loop->prev;
833 current_header = current_loop == NULL ? NULL : current_loop->header; 838 current_header = current_loop == NULL ? NULL : current_loop->header;
834 --loop_depth; 839 --loop_depth;
835 } 840 }
836 current->set_loop_header(current_header); 841 current->set_loop_header(current_header);
837 842
838 // Push a new loop onto the stack if this loop is a loop header. 843 // Push a new loop onto the stack if this loop is a loop header.
839 if (HasLoopNumber(current)) { 844 if (HasLoopNumber(current)) {
840 loop_depth++; 845 ++loop_depth;
841 current_loop = &loops_[GetLoopNumber(current)]; 846 current_loop = &loops_[GetLoopNumber(current)];
842 BlockList* end = current_loop->end; 847 BlockList* end = current_loop->end;
843 current->set_loop_end(end == NULL ? BeyondEndSentinel() : end->block); 848 current->set_loop_end(end == NULL ? BeyondEndSentinel() : end->block);
844 current_header = current_loop->header; 849 current_header = current_loop->header;
845 Trace("B%d is a loop header, increment loop depth to %d\n", 850 Trace("B%d is a loop header, increment loop depth to %d\n",
846 current->id().ToInt(), loop_depth); 851 current->id().ToInt(), loop_depth);
847 } 852 }
848 853
849 current->set_loop_depth(loop_depth); 854 current->set_loop_depth(loop_depth);
850 855
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
965 int links = 0; 970 int links = 0;
966 BlockList* l = loop->start; 971 BlockList* l = loop->start;
967 DCHECK(l != NULL && l->block == header); 972 DCHECK(l != NULL && l->block == header);
968 bool end_found; 973 bool end_found;
969 while (true) { 974 while (true) {
970 if (l == NULL || l == loop->end) { 975 if (l == NULL || l == loop->end) {
971 end_found = (loop->end == l); 976 end_found = (loop->end == l);
972 break; 977 break;
973 } 978 }
974 // The list should be in same order as the final result. 979 // The list should be in same order as the final result.
975 DCHECK(l->block->rpo_number() == links + loop->header->rpo_number()); 980 DCHECK(l->block->rpo_number() == links + header->rpo_number());
976 links++; 981 links++;
977 l = l->next; 982 l = l->next;
978 DCHECK(links < static_cast<int>(2 * order->size())); // cycle? 983 DCHECK(links < static_cast<int>(2 * order->size())); // cycle?
979 } 984 }
980 DCHECK(links > 0); 985 DCHECK(links > 0);
981 DCHECK(links == end->rpo_number() - header->rpo_number()); 986 DCHECK(links == end->rpo_number() - header->rpo_number());
982 DCHECK(end_found); 987 DCHECK(end_found);
983 988
989 // Check loop depth of the header.
990 int loop_depth = 0;
991 for (LoopInfo* outer = loop; outer != NULL; outer = outer->prev) {
992 loop_depth++;
993 }
994 DCHECK_EQ(loop_depth, header->loop_depth());
995
984 // Check the contiguousness of loops. 996 // Check the contiguousness of loops.
985 int count = 0; 997 int count = 0;
986 for (int j = 0; j < static_cast<int>(order->size()); j++) { 998 for (int j = 0; j < static_cast<int>(order->size()); j++) {
987 BasicBlock* block = order->at(j); 999 BasicBlock* block = order->at(j);
988 DCHECK(block->rpo_number() == j); 1000 DCHECK(block->rpo_number() == j);
989 if (j < header->rpo_number() || j >= end->rpo_number()) { 1001 if (j < header->rpo_number() || j >= end->rpo_number()) {
990 DCHECK(!header->LoopContains(block)); 1002 DCHECK(!header->LoopContains(block));
991 } else { 1003 } else {
992 DCHECK(header->LoopContains(block)); 1004 DCHECK(header->LoopContains(block));
1005 DCHECK_GE(block->loop_depth(), loop_depth);
993 count++; 1006 count++;
994 } 1007 }
995 } 1008 }
996 DCHECK(links == count); 1009 DCHECK(links == count);
997 } 1010 }
998 } 1011 }
999 #endif // DEBUG 1012 #endif // DEBUG
1000 1013
1001 Zone* zone_; 1014 Zone* zone_;
1002 Schedule* schedule_; 1015 Schedule* schedule_;
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
1421 if (FLAG_trace_turbo_scheduler) { 1434 if (FLAG_trace_turbo_scheduler) {
1422 OFStream os(stdout); 1435 OFStream os(stdout);
1423 os << "Schedule before control flow fusion:\n" << *schedule_; 1436 os << "Schedule before control flow fusion:\n" << *schedule_;
1424 } 1437 }
1425 1438
1426 // Iterate on phase 1: Build control-flow graph. 1439 // Iterate on phase 1: Build control-flow graph.
1427 CFGBuilder cfg_builder(zone_, this); 1440 CFGBuilder cfg_builder(zone_, this);
1428 cfg_builder.Run(block, node); 1441 cfg_builder.Run(block, node);
1429 1442
1430 // Iterate on phase 2: Compute special RPO and dominator tree. 1443 // Iterate on phase 2: Compute special RPO and dominator tree.
1444 special_rpo_->UpdateSpecialRPO(block, schedule_->block(node));
1431 // TODO(mstarzinger): Currently "iterate on" means "re-run". Fix that. 1445 // TODO(mstarzinger): Currently "iterate on" means "re-run". Fix that.
1432 for (BasicBlock* block : schedule_->all_blocks_) { 1446 for (BasicBlock* block : schedule_->all_blocks_) {
1433 block->set_rpo_number(-1);
1434 block->set_dominator_depth(-1); 1447 block->set_dominator_depth(-1);
1435 block->set_dominator(NULL); 1448 block->set_dominator(NULL);
1436 } 1449 }
1437 special_rpo_->UpdateSpecialRPO(block, schedule_->block(node));
1438 GenerateImmediateDominatorTree(); 1450 GenerateImmediateDominatorTree();
1439 1451
1440 // Move previously planned nodes. 1452 // Move previously planned nodes.
1441 // TODO(mstarzinger): Improve that by supporting bulk moves. 1453 // TODO(mstarzinger): Improve that by supporting bulk moves.
1442 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_)); 1454 scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_));
1443 MovePlannedNodes(block, schedule_->block(node)); 1455 MovePlannedNodes(block, schedule_->block(node));
1444 1456
1445 if (FLAG_trace_turbo_scheduler) { 1457 if (FLAG_trace_turbo_scheduler) {
1446 OFStream os(stdout); 1458 OFStream os(stdout);
1447 os << "Schedule after control flow fusion:\n" << *schedule_; 1459 os << "Schedule after control flow fusion:\n" << *schedule_;
1448 } 1460 }
1449 } 1461 }
1450 1462
1451 1463
1452 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) { 1464 void Scheduler::MovePlannedNodes(BasicBlock* from, BasicBlock* to) {
1453 Trace("Move planned nodes from B%d to B%d\n", from->id().ToInt(), 1465 Trace("Move planned nodes from B%d to B%d\n", from->id().ToInt(),
1454 to->id().ToInt()); 1466 to->id().ToInt());
1455 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]); 1467 NodeVector* nodes = &(scheduled_nodes_[from->id().ToSize()]);
1456 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { 1468 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) {
1457 schedule_->SetBlockForNode(to, *i); 1469 schedule_->SetBlockForNode(to, *i);
1458 scheduled_nodes_[to->id().ToSize()].push_back(*i); 1470 scheduled_nodes_[to->id().ToSize()].push_back(*i);
1459 } 1471 }
1460 nodes->clear(); 1472 nodes->clear();
1461 } 1473 }
1462 1474
1463 } // namespace compiler 1475 } // namespace compiler
1464 } // namespace internal 1476 } // namespace internal
1465 } // namespace v8 1477 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | test/cctest/compiler/test-scheduler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698