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 "src/compiler/scheduler.h" | 5 #include "src/compiler/scheduler.h" |
6 | 6 |
7 #include "src/compiler/graph.h" | 7 #include "src/compiler/graph.h" |
8 #include "src/compiler/graph-inl.h" | 8 #include "src/compiler/graph-inl.h" |
9 #include "src/compiler/node.h" | 9 #include "src/compiler/node.h" |
10 #include "src/compiler/node-properties.h" | 10 #include "src/compiler/node-properties.h" |
11 #include "src/compiler/node-properties-inl.h" | 11 #include "src/compiler/node-properties-inl.h" |
12 #include "src/data-flow.h" | 12 #include "src/data-flow.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 namespace compiler { | 16 namespace compiler { |
17 | 17 |
18 Scheduler::Scheduler(Zone* zone) | |
19 : zone_(zone), | |
20 graph_(NULL), | |
21 schedule_(NULL), | |
22 branches_(NodeVector::allocator_type(zone)), | |
23 calls_(NodeVector::allocator_type(zone)), | |
24 deopts_(NodeVector::allocator_type(zone)), | |
25 returns_(NodeVector::allocator_type(zone)), | |
26 loops_and_merges_(NodeVector::allocator_type(zone)), | |
27 node_block_placement_(BasicBlockVector::allocator_type(zone)), | |
28 unscheduled_uses_(IntVector::allocator_type(zone)), | |
29 scheduled_nodes_(NodeVectorVector::allocator_type(zone)), | |
30 schedule_root_nodes_(NodeVector::allocator_type(zone)), | |
31 schedule_early_rpo_index_(IntVector::allocator_type(zone)) {} | |
32 | |
33 | |
34 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule) | 18 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule) |
35 : zone_(zone), | 19 : zone_(zone), |
36 graph_(graph), | 20 graph_(graph), |
37 schedule_(schedule), | 21 schedule_(schedule), |
38 branches_(NodeVector::allocator_type(zone)), | 22 branches_(NodeVector::allocator_type(zone)), |
39 calls_(NodeVector::allocator_type(zone)), | 23 calls_(NodeVector::allocator_type(zone)), |
40 deopts_(NodeVector::allocator_type(zone)), | 24 deopts_(NodeVector::allocator_type(zone)), |
41 returns_(NodeVector::allocator_type(zone)), | 25 returns_(NodeVector::allocator_type(zone)), |
42 loops_and_merges_(NodeVector::allocator_type(zone)), | 26 loops_and_merges_(NodeVector::allocator_type(zone)), |
43 node_block_placement_(BasicBlockVector::allocator_type(zone)), | 27 node_block_placement_(BasicBlockVector::allocator_type(zone)), |
44 unscheduled_uses_(IntVector::allocator_type(zone)), | 28 unscheduled_uses_(IntVector::allocator_type(zone)), |
45 scheduled_nodes_(NodeVectorVector::allocator_type(zone)), | 29 scheduled_nodes_(NodeVectorVector::allocator_type(zone)), |
46 schedule_root_nodes_(NodeVector::allocator_type(zone)), | 30 schedule_root_nodes_(NodeVector::allocator_type(zone)), |
47 schedule_early_rpo_index_(IntVector::allocator_type(zone)) {} | 31 schedule_early_rpo_index_(IntVector::allocator_type(zone)) {} |
48 | 32 |
49 | 33 |
50 Schedule* Scheduler::NewSchedule(Graph* graph) { | 34 Schedule* Scheduler::ComputeSchedule(Graph* graph) { |
51 graph_ = graph; | 35 Zone tmp_zone(graph->zone()->isolate()); |
52 schedule_ = new (zone_) Schedule(zone_); | 36 Schedule* schedule = new (graph->zone()) Schedule(graph->zone()); |
| 37 Scheduler scheduler(&tmp_zone, graph, schedule); |
53 | 38 |
54 schedule_->AddNode(schedule_->end(), graph_->end()); | 39 schedule->AddNode(schedule->end(), graph->end()); |
55 | 40 |
56 PrepareAuxiliaryNodeData(); | 41 scheduler.PrepareAuxiliaryNodeData(); |
| 42 scheduler.CreateBlocks(); |
| 43 scheduler.WireBlocks(); |
| 44 scheduler.PrepareAuxiliaryBlockData(); |
57 | 45 |
58 // Create basic blocks for each block and merge node in the graph. | 46 Scheduler::ComputeSpecialRPO(schedule); |
59 CreateBlocks(); | 47 scheduler.GenerateImmediateDominatorTree(); |
60 | 48 |
61 // Wire the basic blocks together. | 49 scheduler.PrepareUses(); |
62 WireBlocks(); | 50 scheduler.ScheduleEarly(); |
| 51 scheduler.ScheduleLate(); |
63 | 52 |
64 PrepareAuxiliaryBlockData(); | 53 return schedule; |
65 | |
66 ComputeSpecialRPO(); | |
67 GenerateImmediateDominatorTree(); | |
68 | |
69 PrepareUses(); | |
70 ScheduleEarly(); | |
71 ScheduleLate(); | |
72 | |
73 return schedule_; | |
74 } | 54 } |
75 | 55 |
76 | 56 |
77 class CreateBlockVisitor : public NullNodeVisitor { | 57 class CreateBlockVisitor : public NullNodeVisitor { |
78 public: | 58 public: |
79 explicit CreateBlockVisitor(Scheduler* scheduler) : scheduler_(scheduler) {} | 59 explicit CreateBlockVisitor(Scheduler* scheduler) : scheduler_(scheduler) {} |
80 | 60 |
81 GenericGraphVisit::Control Post(Node* node) { | 61 GenericGraphVisit::Control Post(Node* node) { |
82 Schedule* schedule = scheduler_->schedule_; | 62 Schedule* schedule = scheduler_->schedule_; |
83 switch (node->opcode()) { | 63 switch (node->opcode()) { |
(...skipping 775 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 // a RPO of the graph where loop bodies are contiguous. Properties: | 839 // a RPO of the graph where loop bodies are contiguous. Properties: |
860 // 1. If block A is a predecessor of B, then A appears before B in the order, | 840 // 1. If block A is a predecessor of B, then A appears before B in the order, |
861 // unless B is a loop header and A is in the loop headed at B | 841 // unless B is a loop header and A is in the loop headed at B |
862 // (i.e. A -> B is a backedge). | 842 // (i.e. A -> B is a backedge). |
863 // => If block A dominates block B, then A appears before B in the order. | 843 // => If block A dominates block B, then A appears before B in the order. |
864 // => If block A is a loop header, A appears before all blocks in the loop | 844 // => If block A is a loop header, A appears before all blocks in the loop |
865 // headed at A. | 845 // headed at A. |
866 // 2. All loops are contiguous in the order (i.e. no intervening blocks that | 846 // 2. All loops are contiguous in the order (i.e. no intervening blocks that |
867 // do not belong to the loop.) | 847 // do not belong to the loop.) |
868 // Note a simple RPO traversal satisfies (1) but not (3). | 848 // Note a simple RPO traversal satisfies (1) but not (3). |
869 BasicBlockVector* Scheduler::ComputeSpecialRPO() { | 849 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) { |
| 850 Zone tmp_zone(schedule->zone()->isolate()); |
| 851 Zone* zone = &tmp_zone; |
870 if (FLAG_trace_turbo_scheduler) { | 852 if (FLAG_trace_turbo_scheduler) { |
871 PrintF("------------- COMPUTING SPECIAL RPO ---------------\n"); | 853 PrintF("------------- COMPUTING SPECIAL RPO ---------------\n"); |
872 } | 854 } |
873 // RPO should not have been computed for this schedule yet. | 855 // RPO should not have been computed for this schedule yet. |
874 CHECK_EQ(kBlockUnvisited1, schedule_->entry()->rpo_number_); | 856 CHECK_EQ(kBlockUnvisited1, schedule->entry()->rpo_number_); |
875 CHECK_EQ(0, static_cast<int>(schedule_->rpo_order_.size())); | 857 CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size())); |
876 | 858 |
877 // Perform an iterative RPO traversal using an explicit stack, | 859 // Perform an iterative RPO traversal using an explicit stack, |
878 // recording backedges that form cycles. O(|B|). | 860 // recording backedges that form cycles. O(|B|). |
879 ZoneList<std::pair<BasicBlock*, int> > backedges(1, zone_); | 861 ZoneList<std::pair<BasicBlock*, int> > backedges(1, zone); |
880 SpecialRPOStackFrame* stack = | 862 SpecialRPOStackFrame* stack = |
881 zone_->NewArray<SpecialRPOStackFrame>(schedule_->BasicBlockCount()); | 863 zone->NewArray<SpecialRPOStackFrame>(schedule->BasicBlockCount()); |
882 BasicBlock* entry = schedule_->entry(); | 864 BasicBlock* entry = schedule->entry(); |
883 BlockList* order = NULL; | 865 BlockList* order = NULL; |
884 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); | 866 int stack_depth = Push(stack, 0, entry, kBlockUnvisited1); |
885 int num_loops = 0; | 867 int num_loops = 0; |
886 | 868 |
887 while (stack_depth > 0) { | 869 while (stack_depth > 0) { |
888 int current = stack_depth - 1; | 870 int current = stack_depth - 1; |
889 SpecialRPOStackFrame* frame = stack + current; | 871 SpecialRPOStackFrame* frame = stack + current; |
890 | 872 |
891 if (frame->index < frame->block->SuccessorCount()) { | 873 if (frame->index < frame->block->SuccessorCount()) { |
892 // Process the next successor. | 874 // Process the next successor. |
893 BasicBlock* succ = frame->block->SuccessorAt(frame->index++); | 875 BasicBlock* succ = frame->block->SuccessorAt(frame->index++); |
894 if (succ->rpo_number_ == kBlockVisited1) continue; | 876 if (succ->rpo_number_ == kBlockVisited1) continue; |
895 if (succ->rpo_number_ == kBlockOnStack) { | 877 if (succ->rpo_number_ == kBlockOnStack) { |
896 // The successor is on the stack, so this is a backedge (cycle). | 878 // The successor is on the stack, so this is a backedge (cycle). |
897 backedges.Add( | 879 backedges.Add( |
898 std::pair<BasicBlock*, int>(frame->block, frame->index - 1), zone_); | 880 std::pair<BasicBlock*, int>(frame->block, frame->index - 1), zone); |
899 if (succ->loop_end_ < 0) { | 881 if (succ->loop_end_ < 0) { |
900 // Assign a new loop number to the header if it doesn't have one. | 882 // Assign a new loop number to the header if it doesn't have one. |
901 succ->loop_end_ = num_loops++; | 883 succ->loop_end_ = num_loops++; |
902 } | 884 } |
903 } else { | 885 } else { |
904 // Push the successor onto the stack. | 886 // Push the successor onto the stack. |
905 DCHECK(succ->rpo_number_ == kBlockUnvisited1); | 887 DCHECK(succ->rpo_number_ == kBlockUnvisited1); |
906 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); | 888 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited1); |
907 } | 889 } |
908 } else { | 890 } else { |
909 // Finished with all successors; pop the stack and add the block. | 891 // Finished with all successors; pop the stack and add the block. |
910 order = order->Add(zone_, frame->block); | 892 order = order->Add(zone, frame->block); |
911 frame->block->rpo_number_ = kBlockVisited1; | 893 frame->block->rpo_number_ = kBlockVisited1; |
912 stack_depth--; | 894 stack_depth--; |
913 } | 895 } |
914 } | 896 } |
915 | 897 |
916 // If no loops were encountered, then the order we computed was correct. | 898 // If no loops were encountered, then the order we computed was correct. |
917 LoopInfo* loops = NULL; | 899 LoopInfo* loops = NULL; |
918 if (num_loops != 0) { | 900 if (num_loops != 0) { |
919 // Otherwise, compute the loop information from the backedges in order | 901 // Otherwise, compute the loop information from the backedges in order |
920 // to perform a traversal that groups loop bodies together. | 902 // to perform a traversal that groups loop bodies together. |
921 loops = ComputeLoopInfo(zone_, stack, num_loops, | 903 loops = ComputeLoopInfo(zone, stack, num_loops, schedule->BasicBlockCount(), |
922 schedule_->BasicBlockCount(), &backedges); | 904 &backedges); |
923 | 905 |
924 // Initialize the "loop stack". Note the entry could be a loop header. | 906 // Initialize the "loop stack". Note the entry could be a loop header. |
925 LoopInfo* loop = entry->IsLoopHeader() ? &loops[entry->loop_end_] : NULL; | 907 LoopInfo* loop = entry->IsLoopHeader() ? &loops[entry->loop_end_] : NULL; |
926 order = NULL; | 908 order = NULL; |
927 | 909 |
928 // Perform an iterative post-order traversal, visiting loop bodies before | 910 // Perform an iterative post-order traversal, visiting loop bodies before |
929 // edges that lead out of loops. Visits each block once, but linking loop | 911 // edges that lead out of loops. Visits each block once, but linking loop |
930 // sections together is linear in the loop size, so overall is | 912 // sections together is linear in the loop size, so overall is |
931 // O(|B| + max(loop_depth) * max(|loop|)) | 913 // O(|B| + max(loop_depth) * max(|loop|)) |
932 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); | 914 stack_depth = Push(stack, 0, entry, kBlockUnvisited2); |
933 while (stack_depth > 0) { | 915 while (stack_depth > 0) { |
934 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); | 916 SpecialRPOStackFrame* frame = stack + (stack_depth - 1); |
935 BasicBlock* block = frame->block; | 917 BasicBlock* block = frame->block; |
936 BasicBlock* succ = NULL; | 918 BasicBlock* succ = NULL; |
937 | 919 |
938 if (frame->index < block->SuccessorCount()) { | 920 if (frame->index < block->SuccessorCount()) { |
939 // Process the next normal successor. | 921 // Process the next normal successor. |
940 succ = block->SuccessorAt(frame->index++); | 922 succ = block->SuccessorAt(frame->index++); |
941 } else if (block->IsLoopHeader()) { | 923 } else if (block->IsLoopHeader()) { |
942 // Process additional outgoing edges from the loop header. | 924 // Process additional outgoing edges from the loop header. |
943 if (block->rpo_number_ == kBlockOnStack) { | 925 if (block->rpo_number_ == kBlockOnStack) { |
944 // Finish the loop body the first time the header is left on the | 926 // Finish the loop body the first time the header is left on the |
945 // stack. | 927 // stack. |
946 DCHECK(loop != NULL && loop->header == block); | 928 DCHECK(loop != NULL && loop->header == block); |
947 loop->start = order->Add(zone_, block); | 929 loop->start = order->Add(zone, block); |
948 order = loop->end; | 930 order = loop->end; |
949 block->rpo_number_ = kBlockVisited2; | 931 block->rpo_number_ = kBlockVisited2; |
950 // Pop the loop stack and continue visiting outgoing edges within the | 932 // Pop the loop stack and continue visiting outgoing edges within the |
951 // the context of the outer loop, if any. | 933 // the context of the outer loop, if any. |
952 loop = loop->prev; | 934 loop = loop->prev; |
953 // We leave the loop header on the stack; the rest of this iteration | 935 // We leave the loop header on the stack; the rest of this iteration |
954 // and later iterations will go through its outgoing edges list. | 936 // and later iterations will go through its outgoing edges list. |
955 } | 937 } |
956 | 938 |
957 // Use the next outgoing edge if there are any. | 939 // Use the next outgoing edge if there are any. |
958 int outgoing_index = frame->index - block->SuccessorCount(); | 940 int outgoing_index = frame->index - block->SuccessorCount(); |
959 LoopInfo* info = &loops[block->loop_end_]; | 941 LoopInfo* info = &loops[block->loop_end_]; |
960 DCHECK(loop != info); | 942 DCHECK(loop != info); |
961 if (info->outgoing != NULL && | 943 if (info->outgoing != NULL && |
962 outgoing_index < info->outgoing->length()) { | 944 outgoing_index < info->outgoing->length()) { |
963 succ = info->outgoing->at(outgoing_index); | 945 succ = info->outgoing->at(outgoing_index); |
964 frame->index++; | 946 frame->index++; |
965 } | 947 } |
966 } | 948 } |
967 | 949 |
968 if (succ != NULL) { | 950 if (succ != NULL) { |
969 // Process the next successor. | 951 // Process the next successor. |
970 if (succ->rpo_number_ == kBlockOnStack) continue; | 952 if (succ->rpo_number_ == kBlockOnStack) continue; |
971 if (succ->rpo_number_ == kBlockVisited2) continue; | 953 if (succ->rpo_number_ == kBlockVisited2) continue; |
972 DCHECK(succ->rpo_number_ == kBlockUnvisited2); | 954 DCHECK(succ->rpo_number_ == kBlockUnvisited2); |
973 if (loop != NULL && !loop->members->Contains(succ->id())) { | 955 if (loop != NULL && !loop->members->Contains(succ->id())) { |
974 // The successor is not in the current loop or any nested loop. | 956 // The successor is not in the current loop or any nested loop. |
975 // Add it to the outgoing edges of this loop and visit it later. | 957 // Add it to the outgoing edges of this loop and visit it later. |
976 loop->AddOutgoing(zone_, succ); | 958 loop->AddOutgoing(zone, succ); |
977 } else { | 959 } else { |
978 // Push the successor onto the stack. | 960 // Push the successor onto the stack. |
979 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); | 961 stack_depth = Push(stack, stack_depth, succ, kBlockUnvisited2); |
980 if (succ->IsLoopHeader()) { | 962 if (succ->IsLoopHeader()) { |
981 // Push the inner loop onto the loop stack. | 963 // Push the inner loop onto the loop stack. |
982 DCHECK(succ->loop_end_ >= 0 && succ->loop_end_ < num_loops); | 964 DCHECK(succ->loop_end_ >= 0 && succ->loop_end_ < num_loops); |
983 LoopInfo* next = &loops[succ->loop_end_]; | 965 LoopInfo* next = &loops[succ->loop_end_]; |
984 next->end = order; | 966 next->end = order; |
985 next->prev = loop; | 967 next->prev = loop; |
986 loop = next; | 968 loop = next; |
987 } | 969 } |
988 } | 970 } |
989 } else { | 971 } else { |
990 // Finished with all successors of the current block. | 972 // Finished with all successors of the current block. |
991 if (block->IsLoopHeader()) { | 973 if (block->IsLoopHeader()) { |
992 // If we are going to pop a loop header, then add its entire body. | 974 // If we are going to pop a loop header, then add its entire body. |
993 LoopInfo* info = &loops[block->loop_end_]; | 975 LoopInfo* info = &loops[block->loop_end_]; |
994 for (BlockList* l = info->start; true; l = l->next) { | 976 for (BlockList* l = info->start; true; l = l->next) { |
995 if (l->next == info->end) { | 977 if (l->next == info->end) { |
996 l->next = order; | 978 l->next = order; |
997 info->end = order; | 979 info->end = order; |
998 break; | 980 break; |
999 } | 981 } |
1000 } | 982 } |
1001 order = info->start; | 983 order = info->start; |
1002 } else { | 984 } else { |
1003 // Pop a single node off the stack and add it to the order. | 985 // Pop a single node off the stack and add it to the order. |
1004 order = order->Add(zone_, block); | 986 order = order->Add(zone, block); |
1005 block->rpo_number_ = kBlockVisited2; | 987 block->rpo_number_ = kBlockVisited2; |
1006 } | 988 } |
1007 stack_depth--; | 989 stack_depth--; |
1008 } | 990 } |
1009 } | 991 } |
1010 } | 992 } |
1011 | 993 |
1012 // Construct the final order from the list. | 994 // Construct the final order from the list. |
1013 BasicBlockVector* final_order = &schedule_->rpo_order_; | 995 BasicBlockVector* final_order = &schedule->rpo_order_; |
1014 order->Serialize(final_order); | 996 order->Serialize(final_order); |
1015 | 997 |
1016 // Compute the correct loop header for every block and set the correct loop | 998 // Compute the correct loop header for every block and set the correct loop |
1017 // ends. | 999 // ends. |
1018 LoopInfo* current_loop = NULL; | 1000 LoopInfo* current_loop = NULL; |
1019 BasicBlock* current_header = NULL; | 1001 BasicBlock* current_header = NULL; |
1020 int loop_depth = 0; | 1002 int loop_depth = 0; |
1021 for (BasicBlockVectorIter i = final_order->begin(); i != final_order->end(); | 1003 for (BasicBlockVectorIter i = final_order->begin(); i != final_order->end(); |
1022 ++i) { | 1004 ++i) { |
1023 BasicBlock* current = *i; | 1005 BasicBlock* current = *i; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1058 | 1040 |
1059 #if DEBUG | 1041 #if DEBUG |
1060 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); | 1042 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); |
1061 VerifySpecialRPO(num_loops, loops, final_order); | 1043 VerifySpecialRPO(num_loops, loops, final_order); |
1062 #endif | 1044 #endif |
1063 return final_order; | 1045 return final_order; |
1064 } | 1046 } |
1065 } | 1047 } |
1066 } | 1048 } |
1067 } // namespace v8::internal::compiler | 1049 } // namespace v8::internal::compiler |
OLD | NEW |