Chromium Code Reviews| 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 |