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/compiler/graph.h" | 10 #include "src/compiler/graph.h" |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 UNREACHABLE(); | 115 UNREACHABLE(); |
116 break; | 116 break; |
117 case IrOpcode::kPhi: | 117 case IrOpcode::kPhi: |
118 case IrOpcode::kEffectPhi: { | 118 case IrOpcode::kEffectPhi: { |
119 // Phis and effect phis are coupled to their respective blocks. | 119 // Phis and effect phis are coupled to their respective blocks. |
120 DCHECK_EQ(Scheduler::kCoupled, data->placement_); | 120 DCHECK_EQ(Scheduler::kCoupled, data->placement_); |
121 DCHECK_EQ(Scheduler::kFixed, placement); | 121 DCHECK_EQ(Scheduler::kFixed, placement); |
122 Node* control = NodeProperties::GetControlInput(node); | 122 Node* control = NodeProperties::GetControlInput(node); |
123 BasicBlock* block = schedule_->block(control); | 123 BasicBlock* block = schedule_->block(control); |
124 schedule_->AddNode(block, node); | 124 schedule_->AddNode(block, node); |
125 // TODO(mstarzinger): Cheap hack to make sure unscheduled use count of | |
126 // control does not drop below zero. This might cause the control to be | |
127 // queued for scheduling more than once, which makes this ugly! | |
128 ++(GetData(control)->unscheduled_count_); | |
129 break; | 125 break; |
130 } | 126 } |
131 #define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V: | 127 #define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V: |
132 CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE) | 128 CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE) |
133 #undef DEFINE_FLOATING_CONTROL_CASE | 129 #undef DEFINE_FLOATING_CONTROL_CASE |
134 { | 130 { |
135 // Control nodes force coupled uses to be placed. | 131 // Control nodes force coupled uses to be placed. |
136 Node::Uses uses = node->uses(); | 132 Node::Uses uses = node->uses(); |
137 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) { | 133 for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) { |
138 if (GetPlacement(*i) == Scheduler::kCoupled) { | 134 if (GetPlacement(*i) == Scheduler::kCoupled) { |
139 DCHECK_EQ(node, NodeProperties::GetControlInput(*i)); | 135 DCHECK_EQ(node, NodeProperties::GetControlInput(*i)); |
140 UpdatePlacement(*i, placement); | 136 UpdatePlacement(*i, placement); |
141 } | 137 } |
142 } | 138 } |
143 break; | 139 break; |
144 } | 140 } |
145 default: | 141 default: |
146 DCHECK_EQ(Scheduler::kSchedulable, data->placement_); | 142 DCHECK_EQ(Scheduler::kSchedulable, data->placement_); |
147 DCHECK_EQ(Scheduler::kScheduled, placement); | 143 DCHECK_EQ(Scheduler::kScheduled, placement); |
148 break; | 144 break; |
149 } | 145 } |
150 // Reduce the use count of the node's inputs to potentially make them | 146 // Reduce the use count of the node's inputs to potentially make them |
151 // schedulable. If all the uses of a node have been scheduled, then the node | 147 // schedulable. If all the uses of a node have been scheduled, then the node |
152 // itself can be scheduled. | 148 // itself can be scheduled. |
153 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { | 149 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { |
154 // TODO(mstarzinger): Another cheap hack for use counts. | 150 // TODO(mstarzinger): Another cheap hack for use counts. |
155 if (GetData(*i)->placement_ == kFixed) continue; | 151 if (GetData(*i)->placement_ == kFixed) continue; |
156 DecrementUnscheduledUseCount(*i, i.edge().from()); | 152 DecrementUnscheduledUseCount(*i, i.index(), i.edge().from()); |
157 } | 153 } |
158 } | 154 } |
159 data->placement_ = placement; | 155 data->placement_ = placement; |
160 } | 156 } |
161 | 157 |
162 | 158 |
163 void Scheduler::IncrementUnscheduledUseCount(Node* node, Node* from) { | 159 static bool IsControlInputIndex(Node* node, int idx) { |
160 return NodeProperties::FirstControlIndex(node) == idx; | |
161 } | |
162 | |
163 | |
164 void Scheduler::IncrementUnscheduledUseCount(Node* node, int idx, Node* from) { | |
titzer
2014/10/29 16:53:39
index
Michael Starzinger
2014/10/29 17:10:03
Done. Nooooo, 81 characters, the worst torture. :)
| |
165 if (GetPlacement(from) == kCoupled && IsControlInputIndex(from, idx)) { | |
titzer
2014/10/29 16:55:07
What about a different predicate, IsControlInputTo
Michael Starzinger
2014/10/29 17:10:03
Done. Called it IsCoupledControlEdge() as before.
| |
166 // Make sure that control edges from coupled nodes are not counted. | |
167 return; | |
168 } | |
164 if (GetPlacement(node) == kCoupled) { | 169 if (GetPlacement(node) == kCoupled) { |
165 // Use count for coupled nodes is summed up on their control. | 170 // Use count for coupled nodes is summed up on their control. |
166 Node* control = NodeProperties::GetControlInput(node); | 171 Node* control = NodeProperties::GetControlInput(node); |
167 return IncrementUnscheduledUseCount(control, from); | 172 return IncrementUnscheduledUseCount(control, idx, from); |
168 } | 173 } |
169 ++(GetData(node)->unscheduled_count_); | 174 ++(GetData(node)->unscheduled_count_); |
170 if (FLAG_trace_turbo_scheduler) { | 175 if (FLAG_trace_turbo_scheduler) { |
171 Trace(" Use count of #%d:%s (used by #%d:%s)++ = %d\n", node->id(), | 176 Trace(" Use count of #%d:%s (used by #%d:%s)++ = %d\n", node->id(), |
172 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), | 177 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), |
173 GetData(node)->unscheduled_count_); | 178 GetData(node)->unscheduled_count_); |
174 } | 179 } |
175 } | 180 } |
176 | 181 |
177 | 182 |
178 void Scheduler::DecrementUnscheduledUseCount(Node* node, Node* from) { | 183 void Scheduler::DecrementUnscheduledUseCount(Node* node, int idx, Node* from) { |
184 if (GetPlacement(from) == kCoupled && IsControlInputIndex(from, idx)) { | |
185 // Make sure that control edges from coupled nodes are not counted. | |
186 return; | |
187 } | |
179 if (GetPlacement(node) == kCoupled) { | 188 if (GetPlacement(node) == kCoupled) { |
180 // Use count for coupled nodes is summed up on their control. | 189 // Use count for coupled nodes is summed up on their control. |
181 Node* control = NodeProperties::GetControlInput(node); | 190 Node* control = NodeProperties::GetControlInput(node); |
182 return DecrementUnscheduledUseCount(control, from); | 191 return DecrementUnscheduledUseCount(control, idx, from); |
183 } | 192 } |
184 DCHECK(GetData(node)->unscheduled_count_ > 0); | 193 DCHECK(GetData(node)->unscheduled_count_ > 0); |
185 --(GetData(node)->unscheduled_count_); | 194 --(GetData(node)->unscheduled_count_); |
186 if (FLAG_trace_turbo_scheduler) { | 195 if (FLAG_trace_turbo_scheduler) { |
187 Trace(" Use count of #%d:%s (used by #%d:%s)-- = %d\n", node->id(), | 196 Trace(" Use count of #%d:%s (used by #%d:%s)-- = %d\n", node->id(), |
188 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), | 197 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), |
189 GetData(node)->unscheduled_count_); | 198 GetData(node)->unscheduled_count_); |
190 } | 199 } |
191 if (GetData(node)->unscheduled_count_ == 0) { | 200 if (GetData(node)->unscheduled_count_ == 0) { |
192 Trace(" newly eligible #%d:%s\n", node->id(), node->op()->mnemonic()); | 201 Trace(" newly eligible #%d:%s\n", node->id(), node->op()->mnemonic()); |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1003 DCHECK(block != NULL); | 1012 DCHECK(block != NULL); |
1004 schedule_->AddNode(block, node); | 1013 schedule_->AddNode(block, node); |
1005 } | 1014 } |
1006 } | 1015 } |
1007 | 1016 |
1008 return GenericGraphVisit::CONTINUE; | 1017 return GenericGraphVisit::CONTINUE; |
1009 } | 1018 } |
1010 | 1019 |
1011 void PostEdge(Node* from, int index, Node* to) { | 1020 void PostEdge(Node* from, int index, Node* to) { |
1012 // If the edge is from an unscheduled node, then tally it in the use count | 1021 // If the edge is from an unscheduled node, then tally it in the use count |
1013 // for all of its inputs. Also make sure that control edges from coupled | 1022 // for all of its inputs. The same criterion will be used in ScheduleLate |
1014 // nodes are not counted. The same criterion will be used in ScheduleLate | |
1015 // for decrementing use counts. | 1023 // for decrementing use counts. |
1016 if (!schedule_->IsScheduled(from) && !IsCoupledControlEdge(from, index)) { | 1024 if (!schedule_->IsScheduled(from)) { |
1017 DCHECK_NE(Scheduler::kFixed, scheduler_->GetPlacement(from)); | 1025 DCHECK_NE(Scheduler::kFixed, scheduler_->GetPlacement(from)); |
1018 scheduler_->IncrementUnscheduledUseCount(to, from); | 1026 scheduler_->IncrementUnscheduledUseCount(to, index, from); |
1019 } | 1027 } |
1020 } | 1028 } |
1021 | 1029 |
1022 bool IsCoupledControlEdge(Node* node, int index) { | |
1023 return scheduler_->GetPlacement(node) == Scheduler::kCoupled && | |
1024 NodeProperties::FirstControlIndex(node) == index; | |
1025 } | |
1026 | |
1027 private: | 1030 private: |
1028 Scheduler* scheduler_; | 1031 Scheduler* scheduler_; |
1029 Schedule* schedule_; | 1032 Schedule* schedule_; |
1030 }; | 1033 }; |
1031 | 1034 |
1032 | 1035 |
1033 void Scheduler::PrepareUses() { | 1036 void Scheduler::PrepareUses() { |
1034 Trace("--- PREPARE USES -------------------------------------------\n"); | 1037 Trace("--- PREPARE USES -------------------------------------------\n"); |
1035 | 1038 |
1036 // Count the uses of every node, it will be used to ensure that all of a | 1039 // Count the uses of every node, it will be used to ensure that all of a |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1356 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { | 1359 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { |
1357 schedule_->SetBlockForNode(to, *i); | 1360 schedule_->SetBlockForNode(to, *i); |
1358 scheduled_nodes_[to->id().ToSize()].push_back(*i); | 1361 scheduled_nodes_[to->id().ToSize()].push_back(*i); |
1359 } | 1362 } |
1360 nodes->clear(); | 1363 nodes->clear(); |
1361 } | 1364 } |
1362 | 1365 |
1363 } // namespace compiler | 1366 } // namespace compiler |
1364 } // namespace internal | 1367 } // namespace internal |
1365 } // namespace v8 | 1368 } // namespace v8 |
OLD | NEW |