| 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 bool Scheduler::IsCoupledControlEdge(Node* node, int index) { |
| 160 return GetPlacement(node) == kCoupled && |
| 161 NodeProperties::FirstControlIndex(node) == index; |
| 162 } |
| 163 |
| 164 |
| 165 void Scheduler::IncrementUnscheduledUseCount(Node* node, int index, |
| 166 Node* from) { |
| 167 // Make sure that control edges from coupled nodes are not counted. |
| 168 if (IsCoupledControlEdge(from, index)) return; |
| 169 |
| 170 // Use count for coupled nodes is summed up on their control. |
| 164 if (GetPlacement(node) == kCoupled) { | 171 if (GetPlacement(node) == kCoupled) { |
| 165 // Use count for coupled nodes is summed up on their control. | |
| 166 Node* control = NodeProperties::GetControlInput(node); | 172 Node* control = NodeProperties::GetControlInput(node); |
| 167 return IncrementUnscheduledUseCount(control, from); | 173 return IncrementUnscheduledUseCount(control, index, from); |
| 168 } | 174 } |
| 175 |
| 169 ++(GetData(node)->unscheduled_count_); | 176 ++(GetData(node)->unscheduled_count_); |
| 170 if (FLAG_trace_turbo_scheduler) { | 177 if (FLAG_trace_turbo_scheduler) { |
| 171 Trace(" Use count of #%d:%s (used by #%d:%s)++ = %d\n", node->id(), | 178 Trace(" Use count of #%d:%s (used by #%d:%s)++ = %d\n", node->id(), |
| 172 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), | 179 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), |
| 173 GetData(node)->unscheduled_count_); | 180 GetData(node)->unscheduled_count_); |
| 174 } | 181 } |
| 175 } | 182 } |
| 176 | 183 |
| 177 | 184 |
| 178 void Scheduler::DecrementUnscheduledUseCount(Node* node, Node* from) { | 185 void Scheduler::DecrementUnscheduledUseCount(Node* node, int index, |
| 186 Node* from) { |
| 187 // Make sure that control edges from coupled nodes are not counted. |
| 188 if (IsCoupledControlEdge(from, index)) return; |
| 189 |
| 190 // Use count for coupled nodes is summed up on their control. |
| 179 if (GetPlacement(node) == kCoupled) { | 191 if (GetPlacement(node) == kCoupled) { |
| 180 // Use count for coupled nodes is summed up on their control. | |
| 181 Node* control = NodeProperties::GetControlInput(node); | 192 Node* control = NodeProperties::GetControlInput(node); |
| 182 return DecrementUnscheduledUseCount(control, from); | 193 return DecrementUnscheduledUseCount(control, index, from); |
| 183 } | 194 } |
| 195 |
| 184 DCHECK(GetData(node)->unscheduled_count_ > 0); | 196 DCHECK(GetData(node)->unscheduled_count_ > 0); |
| 185 --(GetData(node)->unscheduled_count_); | 197 --(GetData(node)->unscheduled_count_); |
| 186 if (FLAG_trace_turbo_scheduler) { | 198 if (FLAG_trace_turbo_scheduler) { |
| 187 Trace(" Use count of #%d:%s (used by #%d:%s)-- = %d\n", node->id(), | 199 Trace(" Use count of #%d:%s (used by #%d:%s)-- = %d\n", node->id(), |
| 188 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), | 200 node->op()->mnemonic(), from->id(), from->op()->mnemonic(), |
| 189 GetData(node)->unscheduled_count_); | 201 GetData(node)->unscheduled_count_); |
| 190 } | 202 } |
| 191 if (GetData(node)->unscheduled_count_ == 0) { | 203 if (GetData(node)->unscheduled_count_ == 0) { |
| 192 Trace(" newly eligible #%d:%s\n", node->id(), node->op()->mnemonic()); | 204 Trace(" newly eligible #%d:%s\n", node->id(), node->op()->mnemonic()); |
| 193 schedule_queue_.push(node); | 205 schedule_queue_.push(node); |
| (...skipping 809 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1003 DCHECK(block != NULL); | 1015 DCHECK(block != NULL); |
| 1004 schedule_->AddNode(block, node); | 1016 schedule_->AddNode(block, node); |
| 1005 } | 1017 } |
| 1006 } | 1018 } |
| 1007 | 1019 |
| 1008 return GenericGraphVisit::CONTINUE; | 1020 return GenericGraphVisit::CONTINUE; |
| 1009 } | 1021 } |
| 1010 | 1022 |
| 1011 void PostEdge(Node* from, int index, Node* to) { | 1023 void PostEdge(Node* from, int index, Node* to) { |
| 1012 // If the edge is from an unscheduled node, then tally it in the use count | 1024 // 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 | 1025 // 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. | 1026 // for decrementing use counts. |
| 1016 if (!schedule_->IsScheduled(from) && !IsCoupledControlEdge(from, index)) { | 1027 if (!schedule_->IsScheduled(from)) { |
| 1017 DCHECK_NE(Scheduler::kFixed, scheduler_->GetPlacement(from)); | 1028 DCHECK_NE(Scheduler::kFixed, scheduler_->GetPlacement(from)); |
| 1018 scheduler_->IncrementUnscheduledUseCount(to, from); | 1029 scheduler_->IncrementUnscheduledUseCount(to, index, from); |
| 1019 } | 1030 } |
| 1020 } | 1031 } |
| 1021 | 1032 |
| 1022 bool IsCoupledControlEdge(Node* node, int index) { | |
| 1023 return scheduler_->GetPlacement(node) == Scheduler::kCoupled && | |
| 1024 NodeProperties::FirstControlIndex(node) == index; | |
| 1025 } | |
| 1026 | |
| 1027 private: | 1033 private: |
| 1028 Scheduler* scheduler_; | 1034 Scheduler* scheduler_; |
| 1029 Schedule* schedule_; | 1035 Schedule* schedule_; |
| 1030 }; | 1036 }; |
| 1031 | 1037 |
| 1032 | 1038 |
| 1033 void Scheduler::PrepareUses() { | 1039 void Scheduler::PrepareUses() { |
| 1034 Trace("--- PREPARE USES -------------------------------------------\n"); | 1040 Trace("--- PREPARE USES -------------------------------------------\n"); |
| 1035 | 1041 |
| 1036 // Count the uses of every node, it will be used to ensure that all of a | 1042 // 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) { | 1362 for (NodeVectorIter i = nodes->begin(); i != nodes->end(); ++i) { |
| 1357 schedule_->SetBlockForNode(to, *i); | 1363 schedule_->SetBlockForNode(to, *i); |
| 1358 scheduled_nodes_[to->id().ToSize()].push_back(*i); | 1364 scheduled_nodes_[to->id().ToSize()].push_back(*i); |
| 1359 } | 1365 } |
| 1360 nodes->clear(); | 1366 nodes->clear(); |
| 1361 } | 1367 } |
| 1362 | 1368 |
| 1363 } // namespace compiler | 1369 } // namespace compiler |
| 1364 } // namespace internal | 1370 } // namespace internal |
| 1365 } // namespace v8 | 1371 } // namespace v8 |
| OLD | NEW |