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

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

Issue 490483002: Refactor Scheduler to simplify construction of CFG from sea of nodes. Use PreEdge/Post as part of t… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 4 months 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 | « src/compiler/scheduler.h ('k') | no next file » | 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 "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 // Macro for outputting trace information during scheduling.
19 #define TRACE(x) \
20 if (FLAG_trace_turbo_scheduler) PrintF x
Jarin 2014/08/19 14:37:28 Please, do not use this macro. It could lead to ve
21
22 // Internal class to build a control flow graph (i.e the basic blocks and edges
23 // between them within a Schedule) from the node graph.
24 // Visits the graph backwards from end, following control and data edges.
25 class CFGBuilder : public NullNodeVisitor {
26 public:
27 Schedule* schedule_;
28
29 explicit CFGBuilder(Schedule* schedule) : schedule_(schedule) {}
30
31 // Create the blocks for the schedule in pre-order.
32 void PreEdge(Node* from, int index, Node* node) {
33 switch (node->opcode()) {
34 case IrOpcode::kLoop:
35 case IrOpcode::kMerge:
36 BuildBlockForNode(node);
37 break;
38 case IrOpcode::kBranch:
39 BuildBlocksForSuccessors(node, IrOpcode::kIfTrue, IrOpcode::kIfFalse);
40 break;
41 case IrOpcode::kCall:
42 if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
43 BuildBlocksForSuccessors(node, IrOpcode::kContinuation,
44 IrOpcode::kLazyDeoptimization);
45 }
46 break;
47 default:
48 break;
49 }
50 }
51
52 // Connect the blocks after nodes have been visited in post-order.
53 GenericGraphVisit::Control Post(Node* node) {
54 switch (node->opcode()) {
55 case IrOpcode::kLoop:
56 case IrOpcode::kMerge:
57 ConnectMerge(node);
58 break;
59 case IrOpcode::kBranch:
60 ConnectBranch(node);
61 break;
62 case IrOpcode::kDeoptimize:
63 ConnectDeoptimize(node);
64 case IrOpcode::kCall:
65 if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
66 ConnectCall(node);
67 }
68 break;
69 case IrOpcode::kReturn:
70 ConnectReturn(node);
71 break;
72 default:
73 break;
74 }
75 return GenericGraphVisit::CONTINUE;
76 }
77
78 void BuildBlockForNode(Node* node) {
79 if (schedule_->block(node) == NULL) {
80 BasicBlock* block = schedule_->NewBasicBlock();
81 TRACE(("Create block B%d for node %d (%s)\n", block->id(), node->id(),
82 IrOpcode::Mnemonic(node->opcode())));
83 schedule_->AddNode(block, node);
84 }
85 }
86
87 void BuildBlocksForSuccessors(Node* node, IrOpcode::Value a,
88 IrOpcode::Value b) {
89 Node* successors[2];
90 CollectSuccessorProjections(node, successors, a, b);
91 BuildBlockForNode(successors[0]);
92 BuildBlockForNode(successors[1]);
93 }
94
95 // Collect the branch-related projections from a node, such as IfTrue,
96 // IfFalse, Continuation, and LazyDeoptimization.
97 // TODO(titzer): consider moving this to node.h
98 void CollectSuccessorProjections(Node* node, Node** buffer,
99 IrOpcode::Value true_opcode,
100 IrOpcode::Value false_opcode) {
101 buffer[0] = NULL;
102 buffer[1] = NULL;
103 for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
104 if ((*i)->opcode() == true_opcode) {
105 DCHECK_EQ(NULL, buffer[0]);
106 buffer[0] = *i;
107 }
108 if ((*i)->opcode() == false_opcode) {
109 DCHECK_EQ(NULL, buffer[1]);
110 buffer[1] = *i;
111 }
112 }
113 DCHECK_NE(NULL, buffer[0]);
114 DCHECK_NE(NULL, buffer[1]);
115 }
116
117 void CollectSuccessorBlocks(Node* node, BasicBlock** buffer,
118 IrOpcode::Value true_opcode,
119 IrOpcode::Value false_opcode) {
120 Node* successors[2];
121 CollectSuccessorProjections(node, successors, true_opcode, false_opcode);
122 buffer[0] = schedule_->block(successors[0]);
123 buffer[1] = schedule_->block(successors[1]);
124 }
125
126 void ConnectBranch(Node* branch) {
127 Node* branch_block_node = NodeProperties::GetControlInput(branch);
128 BasicBlock* branch_block = schedule_->block(branch_block_node);
129 DCHECK(branch_block != NULL);
130
131 BasicBlock* successor_blocks[2];
132 CollectSuccessorBlocks(branch, successor_blocks, IrOpcode::kIfTrue,
133 IrOpcode::kIfFalse);
134
135 TraceConnect(branch, branch_block, successor_blocks[0]);
136 TraceConnect(branch, branch_block, successor_blocks[1]);
137
138 schedule_->AddBranch(branch_block, branch, successor_blocks[0],
139 successor_blocks[1]);
140 }
141
142 void ConnectMerge(Node* merge) {
143 BasicBlock* block = schedule_->block(merge);
144 DCHECK(block != NULL);
145 // For all of the merge's control inputs, add a goto at the end to the
146 // merge's basic block.
147 for (InputIter j = merge->inputs().begin(); j != merge->inputs().end();
148 ++j) {
149 BasicBlock* predecessor_block = schedule_->block(*j);
150 if ((*j)->opcode() != IrOpcode::kReturn &&
151 (*j)->opcode() != IrOpcode::kDeoptimize) {
152 TraceConnect(merge, predecessor_block, block);
153 schedule_->AddGoto(predecessor_block, block);
154 }
155 }
156 }
157
158 void ConnectDeoptimize(Node* deopt) {
159 Node* deopt_block_node = NodeProperties::GetControlInput(deopt);
160 BasicBlock* deopt_block = schedule_->block(deopt_block_node);
161 TraceConnect(deopt, deopt_block, NULL);
162 schedule_->AddDeoptimize(deopt_block, deopt);
163 }
164
165 void ConnectReturn(Node* ret) {
166 Node* return_block_node = NodeProperties::GetControlInput(ret);
167 BasicBlock* return_block = schedule_->block(return_block_node);
168 TraceConnect(ret, return_block, NULL);
169 schedule_->AddReturn(return_block, ret);
170 }
171
172 void ConnectCall(Node* call) {
173 Node* call_block_node = NodeProperties::GetControlInput(call);
174 BasicBlock* call_block = schedule_->block(call_block_node);
175
176 BasicBlock* successor_blocks[2];
177 CollectSuccessorBlocks(call, successor_blocks, IrOpcode::kContinuation,
178 IrOpcode::kLazyDeoptimization);
179
180 TraceConnect(call, call_block, successor_blocks[0]);
181 TraceConnect(call, call_block, successor_blocks[1]);
182
183 schedule_->AddCall(call_block, call, successor_blocks[0],
184 successor_blocks[1]);
185 }
186
187 void TraceConnect(Node* node, BasicBlock* block, BasicBlock* succ) {
188 DCHECK_NE(NULL, block);
189 if (succ == NULL) {
190 TRACE(("node %d (%s) in block %d -> end\n", node->id(),
191 IrOpcode::Mnemonic(node->opcode()), block->id()));
192 } else {
193 TRACE(("node %d (%s) in block %d -> block %d\n", node->id(),
194 IrOpcode::Mnemonic(node->opcode()), block->id(), succ->id()));
195 }
196 }
197 };
198
199
18 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule) 200 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule)
19 : zone_(zone), 201 : zone_(zone),
20 graph_(graph), 202 graph_(graph),
21 schedule_(schedule), 203 schedule_(schedule),
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 unscheduled_uses_(IntVector::allocator_type(zone)), 204 unscheduled_uses_(IntVector::allocator_type(zone)),
28 scheduled_nodes_(NodeVectorVector::allocator_type(zone)), 205 scheduled_nodes_(NodeVectorVector::allocator_type(zone)),
29 schedule_root_nodes_(NodeVector::allocator_type(zone)), 206 schedule_root_nodes_(NodeVector::allocator_type(zone)),
30 schedule_early_rpo_index_(IntVector::allocator_type(zone)) {} 207 schedule_early_rpo_index_(IntVector::allocator_type(zone)) {}
31 208
32 209
33 Schedule* Scheduler::ComputeSchedule(Graph* graph) { 210 Schedule* Scheduler::ComputeSchedule(Graph* graph) {
34 Zone tmp_zone(graph->zone()->isolate()); 211 Zone tmp_zone(graph->zone()->isolate());
35 Schedule* schedule = new (graph->zone()) Schedule(graph->zone()); 212 Schedule* schedule = new (graph->zone()) Schedule(graph->zone());
213
214 Scheduler::ComputeCFG(graph, schedule);
215
36 Scheduler scheduler(&tmp_zone, graph, schedule); 216 Scheduler scheduler(&tmp_zone, graph, schedule);
37 217
38 schedule->AddNode(schedule->end(), graph->end()); 218 scheduler.PrepareAuxiliaryNodeData();
39 219
40 scheduler.PrepareAuxiliaryNodeData();
41 scheduler.CreateBlocks();
42 scheduler.WireBlocks();
43 scheduler.PrepareAuxiliaryBlockData(); 220 scheduler.PrepareAuxiliaryBlockData();
44 221
45 Scheduler::ComputeSpecialRPO(schedule); 222 Scheduler::ComputeSpecialRPO(schedule);
46 scheduler.GenerateImmediateDominatorTree(); 223 scheduler.GenerateImmediateDominatorTree();
47 224
48 scheduler.PrepareUses(); 225 scheduler.PrepareUses();
49 scheduler.ScheduleEarly(); 226 scheduler.ScheduleEarly();
50 scheduler.ScheduleLate(); 227 scheduler.ScheduleLate();
51 228
52 return schedule; 229 return schedule;
53 } 230 }
54 231
55 232
56 bool Scheduler::IsBasicBlockBegin(Node* node) { 233 bool Scheduler::IsBasicBlockBegin(Node* node) {
57 return OperatorProperties::IsBasicBlockBegin(node->op()); 234 return OperatorProperties::IsBasicBlockBegin(node->op());
58 } 235 }
59 236
60 237
61 bool Scheduler::CanBeScheduled(Node* node) { return true; }
62
63
64 bool Scheduler::HasFixedSchedulePosition(Node* node) { 238 bool Scheduler::HasFixedSchedulePosition(Node* node) {
65 IrOpcode::Value opcode = node->opcode(); 239 IrOpcode::Value opcode = node->opcode();
66 return (IrOpcode::IsControlOpcode(opcode)) || 240 return (IrOpcode::IsControlOpcode(opcode)) ||
67 opcode == IrOpcode::kParameter || opcode == IrOpcode::kEffectPhi || 241 opcode == IrOpcode::kParameter || opcode == IrOpcode::kEffectPhi ||
68 opcode == IrOpcode::kPhi; 242 opcode == IrOpcode::kPhi;
69 } 243 }
70 244
71 245
72 bool Scheduler::IsScheduleRoot(Node* node) { 246 bool Scheduler::IsScheduleRoot(Node* node) {
73 IrOpcode::Value opcode = node->opcode(); 247 IrOpcode::Value opcode = node->opcode();
74 return opcode == IrOpcode::kEnd || opcode == IrOpcode::kEffectPhi || 248 return opcode == IrOpcode::kEnd || opcode == IrOpcode::kEffectPhi ||
75 opcode == IrOpcode::kPhi; 249 opcode == IrOpcode::kPhi;
76 } 250 }
77 251
78 252
79 class CreateBlockVisitor : public NullNodeVisitor { 253 void Scheduler::ComputeCFG(Graph* graph, Schedule* schedule) {
80 public: 254 CFGBuilder cfg_builder(schedule);
81 explicit CreateBlockVisitor(Scheduler* scheduler) : scheduler_(scheduler) {} 255 TRACE(("---------------- CREATING CFG ------------------\n"));
82 256 schedule->AddNode(schedule->start(), graph->start());
83 GenericGraphVisit::Control Post(Node* node) { 257 graph->VisitNodeInputsFromEnd(&cfg_builder);
84 Schedule* schedule = scheduler_->schedule_; 258 schedule->AddNode(schedule->end(), graph->end());
85 switch (node->opcode()) {
86 case IrOpcode::kIfTrue:
87 case IrOpcode::kIfFalse:
88 case IrOpcode::kContinuation:
89 case IrOpcode::kLazyDeoptimization: {
90 BasicBlock* block = schedule->NewBasicBlock();
91 schedule->AddNode(block, node);
92 break;
93 }
94 case IrOpcode::kLoop:
95 case IrOpcode::kMerge: {
96 BasicBlock* block = schedule->NewBasicBlock();
97 schedule->AddNode(block, node);
98 scheduler_->loops_and_merges_.push_back(node);
99 break;
100 }
101 case IrOpcode::kBranch: {
102 scheduler_->branches_.push_back(node);
103 break;
104 }
105 case IrOpcode::kDeoptimize: {
106 scheduler_->deopts_.push_back(node);
107 break;
108 }
109 case IrOpcode::kCall: {
110 if (OperatorProperties::CanLazilyDeoptimize(node->op())) {
111 scheduler_->calls_.push_back(node);
112 }
113 break;
114 }
115 case IrOpcode::kReturn:
116 scheduler_->returns_.push_back(node);
117 break;
118 default:
119 break;
120 }
121
122 return GenericGraphVisit::CONTINUE;
123 }
124
125 private:
126 Scheduler* scheduler_;
127 };
128
129
130 void Scheduler::CreateBlocks() {
131 CreateBlockVisitor create_blocks(this);
132 if (FLAG_trace_turbo_scheduler) {
133 PrintF("---------------- CREATING BLOCKS ------------------\n");
134 }
135 schedule_->AddNode(schedule_->start(), graph_->start());
136 graph_->VisitNodeInputsFromEnd(&create_blocks);
137 } 259 }
138 260
139 261
140 void Scheduler::WireBlocks() {
141 if (FLAG_trace_turbo_scheduler) {
142 PrintF("----------------- WIRING BLOCKS -------------------\n");
143 }
144 AddSuccessorsForBranches();
145 AddSuccessorsForReturns();
146 AddSuccessorsForCalls();
147 AddSuccessorsForDeopts();
148 AddPredecessorsForLoopsAndMerges();
149 // TODO(danno): Handle Throw, et al.
150 }
151
152
153 void Scheduler::PrepareAuxiliaryNodeData() { 262 void Scheduler::PrepareAuxiliaryNodeData() {
154 unscheduled_uses_.resize(graph_->NodeCount(), 0); 263 unscheduled_uses_.resize(graph_->NodeCount(), 0);
155 schedule_early_rpo_index_.resize(graph_->NodeCount(), 0); 264 schedule_early_rpo_index_.resize(graph_->NodeCount(), 0);
156 } 265 }
157 266
158 267
159 void Scheduler::PrepareAuxiliaryBlockData() { 268 void Scheduler::PrepareAuxiliaryBlockData() {
160 Zone* zone = schedule_->zone(); 269 Zone* zone = schedule_->zone();
161 scheduled_nodes_.resize(schedule_->BasicBlockCount(), 270 scheduled_nodes_.resize(schedule_->BasicBlockCount(),
162 NodeVector(NodeVector::allocator_type(zone))); 271 NodeVector(NodeVector::allocator_type(zone)));
163 schedule_->immediate_dominator_.resize(schedule_->BasicBlockCount(), NULL); 272 schedule_->immediate_dominator_.resize(schedule_->BasicBlockCount(), NULL);
164 } 273 }
165 274
166 275
167 void Scheduler::AddPredecessorsForLoopsAndMerges() {
168 for (NodeVectorIter i = loops_and_merges_.begin();
169 i != loops_and_merges_.end(); ++i) {
170 Node* merge_or_loop = *i;
171 BasicBlock* block = schedule_->block(merge_or_loop);
172 DCHECK(block != NULL);
173 // For all of the merge's control inputs, add a goto at the end to the
174 // merge's basic block.
175 for (InputIter j = (*i)->inputs().begin(); j != (*i)->inputs().end(); ++j) {
176 if (IsBasicBlockBegin((*i))) {
177 BasicBlock* predecessor_block = schedule_->block(*j);
178 if ((*j)->opcode() != IrOpcode::kReturn &&
179 (*j)->opcode() != IrOpcode::kDeoptimize) {
180 DCHECK(predecessor_block != NULL);
181 if (FLAG_trace_turbo_scheduler) {
182 IrOpcode::Value opcode = (*i)->opcode();
183 PrintF("node %d (%s) in block %d -> block %d\n", (*i)->id(),
184 IrOpcode::Mnemonic(opcode), predecessor_block->id(),
185 block->id());
186 }
187 schedule_->AddGoto(predecessor_block, block);
188 }
189 }
190 }
191 }
192 }
193
194
195 void Scheduler::AddSuccessorsForCalls() {
196 for (NodeVectorIter i = calls_.begin(); i != calls_.end(); ++i) {
197 Node* call = *i;
198 DCHECK(call->opcode() == IrOpcode::kCall);
199 DCHECK(OperatorProperties::CanLazilyDeoptimize(call->op()));
200
201 Node* lazy_deopt_node = NULL;
202 Node* cont_node = NULL;
203 // Find the continuation and lazy-deopt nodes among the uses.
204 for (UseIter use_iter = call->uses().begin();
205 use_iter != call->uses().end(); ++use_iter) {
206 switch ((*use_iter)->opcode()) {
207 case IrOpcode::kContinuation: {
208 DCHECK(cont_node == NULL);
209 cont_node = *use_iter;
210 break;
211 }
212 case IrOpcode::kLazyDeoptimization: {
213 DCHECK(lazy_deopt_node == NULL);
214 lazy_deopt_node = *use_iter;
215 break;
216 }
217 default:
218 break;
219 }
220 }
221 DCHECK(lazy_deopt_node != NULL);
222 DCHECK(cont_node != NULL);
223 BasicBlock* cont_successor_block = schedule_->block(cont_node);
224 BasicBlock* deopt_successor_block = schedule_->block(lazy_deopt_node);
225 Node* call_block_node = NodeProperties::GetControlInput(call);
226 BasicBlock* call_block = schedule_->block(call_block_node);
227 if (FLAG_trace_turbo_scheduler) {
228 IrOpcode::Value opcode = call->opcode();
229 PrintF("node %d (%s) in block %d -> block %d\n", call->id(),
230 IrOpcode::Mnemonic(opcode), call_block->id(),
231 cont_successor_block->id());
232 PrintF("node %d (%s) in block %d -> block %d\n", call->id(),
233 IrOpcode::Mnemonic(opcode), call_block->id(),
234 deopt_successor_block->id());
235 }
236 schedule_->AddCall(call_block, call, cont_successor_block,
237 deopt_successor_block);
238 }
239 }
240
241
242 void Scheduler::AddSuccessorsForDeopts() {
243 for (NodeVectorIter i = deopts_.begin(); i != deopts_.end(); ++i) {
244 Node* deopt_block_node = NodeProperties::GetControlInput(*i);
245 BasicBlock* deopt_block = schedule_->block(deopt_block_node);
246 DCHECK(deopt_block != NULL);
247 if (FLAG_trace_turbo_scheduler) {
248 IrOpcode::Value opcode = (*i)->opcode();
249 PrintF("node %d (%s) in block %d -> end\n", (*i)->id(),
250 IrOpcode::Mnemonic(opcode), deopt_block->id());
251 }
252 schedule_->AddDeoptimize(deopt_block, *i);
253 }
254 }
255
256
257 void Scheduler::AddSuccessorsForBranches() {
258 for (NodeVectorIter i = branches_.begin(); i != branches_.end(); ++i) {
259 Node* branch = *i;
260 DCHECK(branch->opcode() == IrOpcode::kBranch);
261 Node* branch_block_node = NodeProperties::GetControlInput(branch);
262 BasicBlock* branch_block = schedule_->block(branch_block_node);
263 DCHECK(branch_block != NULL);
264 UseIter use_iter = branch->uses().begin();
265 Node* first_successor = *use_iter;
266 ++use_iter;
267 DCHECK(use_iter != branch->uses().end());
268 Node* second_successor = *use_iter;
269 DCHECK(++use_iter == branch->uses().end());
270 Node* true_successor_node = first_successor->opcode() == IrOpcode::kIfTrue
271 ? first_successor
272 : second_successor;
273 Node* false_successor_node = first_successor->opcode() == IrOpcode::kIfTrue
274 ? second_successor
275 : first_successor;
276 DCHECK(true_successor_node->opcode() == IrOpcode::kIfTrue);
277 DCHECK(false_successor_node->opcode() == IrOpcode::kIfFalse);
278 BasicBlock* true_successor_block = schedule_->block(true_successor_node);
279 BasicBlock* false_successor_block = schedule_->block(false_successor_node);
280 DCHECK(true_successor_block != NULL);
281 DCHECK(false_successor_block != NULL);
282 if (FLAG_trace_turbo_scheduler) {
283 IrOpcode::Value opcode = branch->opcode();
284 PrintF("node %d (%s) in block %d -> block %d\n", branch->id(),
285 IrOpcode::Mnemonic(opcode), branch_block->id(),
286 true_successor_block->id());
287 PrintF("node %d (%s) in block %d -> block %d\n", branch->id(),
288 IrOpcode::Mnemonic(opcode), branch_block->id(),
289 false_successor_block->id());
290 }
291 schedule_->AddBranch(branch_block, branch, true_successor_block,
292 false_successor_block);
293 }
294 }
295
296
297 void Scheduler::AddSuccessorsForReturns() {
298 for (NodeVectorIter i = returns_.begin(); i != returns_.end(); ++i) {
299 Node* return_block_node = NodeProperties::GetControlInput(*i);
300 BasicBlock* return_block = schedule_->block(return_block_node);
301 DCHECK(return_block != NULL);
302 if (FLAG_trace_turbo_scheduler) {
303 IrOpcode::Value opcode = (*i)->opcode();
304 PrintF("node %d (%s) in block %d -> end\n", (*i)->id(),
305 IrOpcode::Mnemonic(opcode), return_block->id());
306 }
307 schedule_->AddReturn(return_block, *i);
308 }
309 }
310
311
312 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) { 276 BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
313 while (b1 != b2) { 277 while (b1 != b2) {
314 int b1_rpo = GetRPONumber(b1); 278 int b1_rpo = GetRPONumber(b1);
315 int b2_rpo = GetRPONumber(b2); 279 int b2_rpo = GetRPONumber(b2);
316 DCHECK(b1_rpo != b2_rpo); 280 DCHECK(b1_rpo != b2_rpo);
317 if (b1_rpo < b2_rpo) { 281 if (b1_rpo < b2_rpo) {
318 b2 = schedule_->immediate_dominator_[b2->id()]; 282 b2 = schedule_->immediate_dominator_[b2->id()];
319 } else { 283 } else {
320 b1 = schedule_->immediate_dominator_[b1->id()]; 284 b1 = schedule_->immediate_dominator_[b1->id()];
321 } 285 }
322 } 286 }
323 return b1; 287 return b1;
324 } 288 }
325 289
326 290
327 void Scheduler::GenerateImmediateDominatorTree() { 291 void Scheduler::GenerateImmediateDominatorTree() {
328 // Build the dominator graph. TODO(danno): consider using Lengauer & Tarjan's 292 // Build the dominator graph. TODO(danno): consider using Lengauer & Tarjan's
329 // if this becomes really slow. 293 // if this becomes really slow.
330 if (FLAG_trace_turbo_scheduler) { 294 TRACE(("------------ IMMEDIATE BLOCK DOMINATORS -----------\n"));
331 PrintF("------------ IMMEDIATE BLOCK DOMINATORS -----------\n");
332 }
333 for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) { 295 for (size_t i = 0; i < schedule_->rpo_order_.size(); i++) {
334 BasicBlock* current_rpo = schedule_->rpo_order_[i]; 296 BasicBlock* current_rpo = schedule_->rpo_order_[i];
335 if (current_rpo != schedule_->start()) { 297 if (current_rpo != schedule_->start()) {
336 BasicBlock::Predecessors::iterator current_pred = 298 BasicBlock::Predecessors::iterator current_pred =
337 current_rpo->predecessors().begin(); 299 current_rpo->predecessors().begin();
338 BasicBlock::Predecessors::iterator end = 300 BasicBlock::Predecessors::iterator end =
339 current_rpo->predecessors().end(); 301 current_rpo->predecessors().end();
340 DCHECK(current_pred != end); 302 DCHECK(current_pred != end);
341 BasicBlock* dominator = *current_pred; 303 BasicBlock* dominator = *current_pred;
342 ++current_pred; 304 ++current_pred;
343 // For multiple predecessors, walk up the rpo ordering until a common 305 // For multiple predecessors, walk up the rpo ordering until a common
344 // dominator is found. 306 // dominator is found.
345 int current_rpo_pos = GetRPONumber(current_rpo); 307 int current_rpo_pos = GetRPONumber(current_rpo);
346 while (current_pred != end) { 308 while (current_pred != end) {
347 // Don't examine backwards edges 309 // Don't examine backwards edges
348 BasicBlock* pred = *current_pred; 310 BasicBlock* pred = *current_pred;
349 if (GetRPONumber(pred) < current_rpo_pos) { 311 if (GetRPONumber(pred) < current_rpo_pos) {
350 dominator = GetCommonDominator(dominator, *current_pred); 312 dominator = GetCommonDominator(dominator, *current_pred);
351 } 313 }
352 ++current_pred; 314 ++current_pred;
353 } 315 }
354 schedule_->immediate_dominator_[current_rpo->id()] = dominator; 316 schedule_->immediate_dominator_[current_rpo->id()] = dominator;
355 if (FLAG_trace_turbo_scheduler) { 317 TRACE(("Block %d's idom is %d\n", current_rpo->id(), dominator->id()));
356 PrintF("Block %d's idom is %d\n", current_rpo->id(), dominator->id());
357 }
358 } 318 }
359 } 319 }
360 } 320 }
361 321
362 322
363 class ScheduleEarlyNodeVisitor : public NullNodeVisitor { 323 class ScheduleEarlyNodeVisitor : public NullNodeVisitor {
364 public: 324 public:
365 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) 325 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler)
366 : has_changed_rpo_constraints_(true), 326 : has_changed_rpo_constraints_(true),
367 scheduler_(scheduler), 327 scheduler_(scheduler),
368 schedule_(scheduler->schedule_) {} 328 schedule_(scheduler->schedule_) {}
369 329
370 GenericGraphVisit::Control Pre(Node* node) { 330 GenericGraphVisit::Control Pre(Node* node) {
371 int id = node->id(); 331 int id = node->id();
372 int max_rpo = 0; 332 int max_rpo = 0;
373 // Fixed nodes already know their schedule early position. 333 // Fixed nodes already know their schedule early position.
374 if (IsFixedNode(node)) { 334 if (scheduler_->HasFixedSchedulePosition(node)) {
375 BasicBlock* block = schedule_->block(node); 335 BasicBlock* block = schedule_->block(node);
376 DCHECK(block != NULL); 336 DCHECK(block != NULL);
377 max_rpo = block->rpo_number_; 337 max_rpo = block->rpo_number_;
378 if (scheduler_->schedule_early_rpo_index_[id] != max_rpo) { 338 if (scheduler_->schedule_early_rpo_index_[id] != max_rpo) {
379 has_changed_rpo_constraints_ = true; 339 has_changed_rpo_constraints_ = true;
380 } 340 }
381 scheduler_->schedule_early_rpo_index_[id] = max_rpo; 341 scheduler_->schedule_early_rpo_index_[id] = max_rpo;
382 if (FLAG_trace_turbo_scheduler) { 342 TRACE(("Node %d pre-scheduled early at rpo limit %d\n", id, max_rpo));
383 PrintF("Node %d pre-scheduled early at rpo limit %d\n", id, max_rpo);
384 }
385 } 343 }
386 return GenericGraphVisit::CONTINUE; 344 return GenericGraphVisit::CONTINUE;
387 } 345 }
388 346
389 GenericGraphVisit::Control Post(Node* node) { 347 GenericGraphVisit::Control Post(Node* node) {
390 int id = node->id(); 348 int id = node->id();
391 int max_rpo = 0; 349 int max_rpo = 0;
392 // Otherwise, the minimum rpo for the node is the max of all of the inputs. 350 // Otherwise, the minimum rpo for the node is the max of all of the inputs.
393 if (!IsFixedNode(node)) { 351 if (!scheduler_->HasFixedSchedulePosition(node)) {
394 DCHECK(!scheduler_->IsBasicBlockBegin(node));
395 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); 352 for (InputIter i = node->inputs().begin(); i != node->inputs().end();
396 ++i) { 353 ++i) {
397 int control_rpo = scheduler_->schedule_early_rpo_index_[(*i)->id()]; 354 int control_rpo = scheduler_->schedule_early_rpo_index_[(*i)->id()];
398 if (control_rpo > max_rpo) { 355 if (control_rpo > max_rpo) {
399 max_rpo = control_rpo; 356 max_rpo = control_rpo;
400 } 357 }
401 } 358 }
402 if (scheduler_->schedule_early_rpo_index_[id] != max_rpo) { 359 if (scheduler_->schedule_early_rpo_index_[id] != max_rpo) {
403 has_changed_rpo_constraints_ = true; 360 has_changed_rpo_constraints_ = true;
404 } 361 }
405 scheduler_->schedule_early_rpo_index_[id] = max_rpo; 362 scheduler_->schedule_early_rpo_index_[id] = max_rpo;
406 if (FLAG_trace_turbo_scheduler) { 363 TRACE(("Node %d post-scheduled early at rpo limit %d\n", id, max_rpo));
407 PrintF("Node %d post-scheduled early at rpo limit %d\n", id, max_rpo);
408 }
409 } 364 }
410 return GenericGraphVisit::CONTINUE; 365 return GenericGraphVisit::CONTINUE;
411 } 366 }
412 367
413 bool IsFixedNode(Node* node) {
414 return scheduler_->HasFixedSchedulePosition(node) ||
415 !scheduler_->CanBeScheduled(node);
416 }
417
418 // TODO(mstarzinger): Dirty hack to unblock others, schedule early should be 368 // TODO(mstarzinger): Dirty hack to unblock others, schedule early should be
419 // rewritten to use a pre-order traversal from the start instead. 369 // rewritten to use a pre-order traversal from the start instead.
420 bool has_changed_rpo_constraints_; 370 bool has_changed_rpo_constraints_;
421 371
422 private: 372 private:
423 Scheduler* scheduler_; 373 Scheduler* scheduler_;
424 Schedule* schedule_; 374 Schedule* schedule_;
425 }; 375 };
426 376
427 377
428 void Scheduler::ScheduleEarly() { 378 void Scheduler::ScheduleEarly() {
429 if (FLAG_trace_turbo_scheduler) { 379 TRACE(("------------------- SCHEDULE EARLY ----------------\n"));
430 PrintF("------------------- SCHEDULE EARLY ----------------\n");
431 }
432 380
433 int fixpoint_count = 0; 381 int fixpoint_count = 0;
434 ScheduleEarlyNodeVisitor visitor(this); 382 ScheduleEarlyNodeVisitor visitor(this);
435 while (visitor.has_changed_rpo_constraints_) { 383 while (visitor.has_changed_rpo_constraints_) {
436 visitor.has_changed_rpo_constraints_ = false; 384 visitor.has_changed_rpo_constraints_ = false;
437 graph_->VisitNodeInputsFromEnd(&visitor); 385 graph_->VisitNodeInputsFromEnd(&visitor);
438 fixpoint_count++; 386 fixpoint_count++;
439 } 387 }
440 388
441 if (FLAG_trace_turbo_scheduler) { 389 TRACE(("It took %d iterations to determine fixpoint\n", fixpoint_count));
442 PrintF("It took %d iterations to determine fixpoint\n", fixpoint_count);
443 }
444 } 390 }
445 391
446 392
447 class PrepareUsesVisitor : public NullNodeVisitor { 393 class PrepareUsesVisitor : public NullNodeVisitor {
448 public: 394 public:
449 explicit PrepareUsesVisitor(Scheduler* scheduler) 395 explicit PrepareUsesVisitor(Scheduler* scheduler)
450 : scheduler_(scheduler), schedule_(scheduler->schedule_) {} 396 : scheduler_(scheduler), schedule_(scheduler->schedule_) {}
451 397
452 GenericGraphVisit::Control Pre(Node* node) { 398 GenericGraphVisit::Control Pre(Node* node) {
453 // Some nodes must be scheduled explicitly to ensure they are in exactly the 399 // Some nodes must be scheduled explicitly to ensure they are in exactly the
454 // right place; it's a convenient place during the preparation of use counts 400 // right place; it's a convenient place during the preparation of use counts
455 // to schedule them. 401 // to schedule them.
456 if (!schedule_->IsScheduled(node) && 402 if (!schedule_->IsScheduled(node) &&
457 scheduler_->HasFixedSchedulePosition(node)) { 403 scheduler_->HasFixedSchedulePosition(node)) {
458 if (FLAG_trace_turbo_scheduler) { 404 TRACE(("Fixed position node %d is unscheduled, scheduling now\n",
459 PrintF("Fixed position node %d is unscheduled, scheduling now\n", 405 node->id()));
460 node->id());
461 }
462 IrOpcode::Value opcode = node->opcode(); 406 IrOpcode::Value opcode = node->opcode();
463 BasicBlock* block = 407 BasicBlock* block =
464 opcode == IrOpcode::kParameter 408 opcode == IrOpcode::kParameter
465 ? schedule_->start() 409 ? schedule_->start()
466 : schedule_->block(NodeProperties::GetControlInput(node)); 410 : schedule_->block(NodeProperties::GetControlInput(node));
467 DCHECK(block != NULL); 411 DCHECK(block != NULL);
468 schedule_->AddNode(block, node); 412 schedule_->AddNode(block, node);
469 } 413 }
470 414
471 if (scheduler_->IsScheduleRoot(node)) { 415 if (scheduler_->IsScheduleRoot(node)) {
472 scheduler_->schedule_root_nodes_.push_back(node); 416 scheduler_->schedule_root_nodes_.push_back(node);
473 } 417 }
474 418
475 return GenericGraphVisit::CONTINUE; 419 return GenericGraphVisit::CONTINUE;
476 } 420 }
477 421
478 void PostEdge(Node* from, int index, Node* to) { 422 void PostEdge(Node* from, int index, Node* to) {
479 // If the edge is from an unscheduled node, then tally it in the use count 423 // If the edge is from an unscheduled node, then tally it in the use count
480 // for all of its inputs. The same criterion will be used in ScheduleLate 424 // for all of its inputs. The same criterion will be used in ScheduleLate
481 // for decrementing use counts. 425 // for decrementing use counts.
482 if (!schedule_->IsScheduled(from) && scheduler_->CanBeScheduled(from)) { 426 if (!schedule_->IsScheduled(from)) {
483 DCHECK(!scheduler_->HasFixedSchedulePosition(from)); 427 DCHECK(!scheduler_->HasFixedSchedulePosition(from));
484 ++scheduler_->unscheduled_uses_[to->id()]; 428 ++scheduler_->unscheduled_uses_[to->id()];
485 if (FLAG_trace_turbo_scheduler) { 429 TRACE(("Incrementing uses of node %d from %d to %d\n", to->id(),
486 PrintF("Incrementing uses of node %d from %d to %d\n", to->id(), 430 from->id(), scheduler_->unscheduled_uses_[to->id()]));
487 from->id(), scheduler_->unscheduled_uses_[to->id()]);
488 }
489 } 431 }
490 } 432 }
491 433
492 private: 434 private:
493 Scheduler* scheduler_; 435 Scheduler* scheduler_;
494 Schedule* schedule_; 436 Schedule* schedule_;
495 }; 437 };
496 438
497 439
498 void Scheduler::PrepareUses() { 440 void Scheduler::PrepareUses() {
499 if (FLAG_trace_turbo_scheduler) { 441 TRACE(("------------------- PREPARE USES ------------------\n"));
500 PrintF("------------------- PREPARE USES ------------------\n");
501 }
502 // Count the uses of every node, it will be used to ensure that all of a 442 // Count the uses of every node, it will be used to ensure that all of a
503 // node's uses are scheduled before the node itself. 443 // node's uses are scheduled before the node itself.
504 PrepareUsesVisitor prepare_uses(this); 444 PrepareUsesVisitor prepare_uses(this);
505 graph_->VisitNodeInputsFromEnd(&prepare_uses); 445 graph_->VisitNodeInputsFromEnd(&prepare_uses);
506 } 446 }
507 447
508 448
509 class ScheduleLateNodeVisitor : public NullNodeVisitor { 449 class ScheduleLateNodeVisitor : public NullNodeVisitor {
510 public: 450 public:
511 explicit ScheduleLateNodeVisitor(Scheduler* scheduler) 451 explicit ScheduleLateNodeVisitor(Scheduler* scheduler)
512 : scheduler_(scheduler), schedule_(scheduler_->schedule_) {} 452 : scheduler_(scheduler), schedule_(scheduler_->schedule_) {}
513 453
514 GenericGraphVisit::Control Pre(Node* node) { 454 GenericGraphVisit::Control Pre(Node* node) {
515 // Don't schedule nodes that cannot be scheduled or are already scheduled. 455 // Don't schedule nodes that are already scheduled.
516 if (!scheduler_->CanBeScheduled(node) || schedule_->IsScheduled(node)) { 456 if (schedule_->IsScheduled(node)) {
517 return GenericGraphVisit::CONTINUE; 457 return GenericGraphVisit::CONTINUE;
518 } 458 }
519 DCHECK(!scheduler_->HasFixedSchedulePosition(node)); 459 DCHECK(!scheduler_->HasFixedSchedulePosition(node));
520 460
521 // If all the uses of a node have been scheduled, then the node itself can 461 // If all the uses of a node have been scheduled, then the node itself can
522 // be scheduled. 462 // be scheduled.
523 bool eligible = scheduler_->unscheduled_uses_[node->id()] == 0; 463 bool eligible = scheduler_->unscheduled_uses_[node->id()] == 0;
524 if (FLAG_trace_turbo_scheduler) { 464 TRACE(("Testing for schedule eligibility for node %d -> %s\n", node->id(),
525 PrintF("Testing for schedule eligibility for node %d -> %s\n", node->id(), 465 eligible ? "true" : "false"));
526 eligible ? "true" : "false");
527 }
528 if (!eligible) return GenericGraphVisit::DEFER; 466 if (!eligible) return GenericGraphVisit::DEFER;
529 467
530 // Determine the dominating block for all of the uses of this node. It is 468 // Determine the dominating block for all of the uses of this node. It is
531 // the latest block that this node can be scheduled in. 469 // the latest block that this node can be scheduled in.
532 BasicBlock* block = NULL; 470 BasicBlock* block = NULL;
533 for (Node::Uses::iterator i = node->uses().begin(); i != node->uses().end(); 471 for (Node::Uses::iterator i = node->uses().begin(); i != node->uses().end();
534 ++i) { 472 ++i) {
535 BasicBlock* use_block = GetBlockForUse(i.edge()); 473 BasicBlock* use_block = GetBlockForUse(i.edge());
536 block = block == NULL ? use_block : use_block == NULL 474 block = block == NULL ? use_block : use_block == NULL
537 ? block 475 ? block
538 : scheduler_->GetCommonDominator( 476 : scheduler_->GetCommonDominator(
539 block, use_block); 477 block, use_block);
540 } 478 }
541 DCHECK(block != NULL); 479 DCHECK(block != NULL);
542 480
543 int min_rpo = scheduler_->schedule_early_rpo_index_[node->id()]; 481 int min_rpo = scheduler_->schedule_early_rpo_index_[node->id()];
544 if (FLAG_trace_turbo_scheduler) { 482 TRACE(
545 PrintF( 483 ("Schedule late conservative for node %d is block %d at "
546 "Schedule late conservative for node %d is block %d at " 484 "loop depth %d, min rpo = %d\n",
547 "loop depth %d, min rpo = %d\n", 485 node->id(), block->id(), block->loop_depth_, min_rpo));
548 node->id(), block->id(), block->loop_depth_, min_rpo);
549 }
550 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively 486 // Hoist nodes out of loops if possible. Nodes can be hoisted iteratively
551 // into enlcosing loop pre-headers until they would preceed their 487 // into enlcosing loop pre-headers until they would preceed their
552 // ScheduleEarly position. 488 // ScheduleEarly position.
553 BasicBlock* hoist_block = block; 489 BasicBlock* hoist_block = block;
554 while (hoist_block != NULL && hoist_block->rpo_number_ >= min_rpo) { 490 while (hoist_block != NULL && hoist_block->rpo_number_ >= min_rpo) {
555 if (hoist_block->loop_depth_ < block->loop_depth_) { 491 if (hoist_block->loop_depth_ < block->loop_depth_) {
556 block = hoist_block; 492 block = hoist_block;
557 if (FLAG_trace_turbo_scheduler) { 493 TRACE(("Hoisting node %d to block %d\n", node->id(), block->id()));
558 PrintF("Hoisting node %d to block %d\n", node->id(), block->id());
559 }
560 } 494 }
561 // Try to hoist to the pre-header of the loop header. 495 // Try to hoist to the pre-header of the loop header.
562 hoist_block = hoist_block->loop_header(); 496 hoist_block = hoist_block->loop_header();
563 if (hoist_block != NULL) { 497 if (hoist_block != NULL) {
564 BasicBlock* pre_header = schedule_->dominator(hoist_block); 498 BasicBlock* pre_header = schedule_->dominator(hoist_block);
565 DCHECK(pre_header == NULL || 499 DCHECK(pre_header == NULL ||
566 *hoist_block->predecessors().begin() == pre_header); 500 *hoist_block->predecessors().begin() == pre_header);
567 if (FLAG_trace_turbo_scheduler) { 501 TRACE(
568 PrintF( 502 ("Try hoist to pre-header block %d of loop header block %d,"
569 "Try hoist to pre-header block %d of loop header block %d," 503 " depth would be %d\n",
570 " depth would be %d\n", 504 pre_header->id(), hoist_block->id(), pre_header->loop_depth_));
571 pre_header->id(), hoist_block->id(), pre_header->loop_depth_);
572 }
573 hoist_block = pre_header; 505 hoist_block = pre_header;
574 } 506 }
575 } 507 }
576 508
577 ScheduleNode(block, node); 509 ScheduleNode(block, node);
578 510
579 return GenericGraphVisit::CONTINUE; 511 return GenericGraphVisit::CONTINUE;
580 } 512 }
581 513
582 private: 514 private:
583 BasicBlock* GetBlockForUse(Node::Edge edge) { 515 BasicBlock* GetBlockForUse(Node::Edge edge) {
584 Node* use = edge.from(); 516 Node* use = edge.from();
585 IrOpcode::Value opcode = use->opcode(); 517 IrOpcode::Value opcode = use->opcode();
586 // If the use is a phi, forward through the phi to the basic block 518 // If the use is a phi, forward through the phi to the basic block
587 // corresponding to the phi's input. 519 // corresponding to the phi's input.
588 if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) { 520 if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
589 int index = edge.index(); 521 int index = edge.index();
590 if (FLAG_trace_turbo_scheduler) { 522 TRACE(("Use %d is input %d to a phi\n", use->id(), index));
591 PrintF("Use %d is input %d to a phi\n", use->id(), index);
592 }
593 use = NodeProperties::GetControlInput(use, 0); 523 use = NodeProperties::GetControlInput(use, 0);
594 opcode = use->opcode(); 524 opcode = use->opcode();
595 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop); 525 DCHECK(opcode == IrOpcode::kMerge || opcode == IrOpcode::kLoop);
596 use = NodeProperties::GetControlInput(use, index); 526 use = NodeProperties::GetControlInput(use, index);
597 } 527 }
598 BasicBlock* result = schedule_->block(use); 528 BasicBlock* result = schedule_->block(use);
599 if (result == NULL) return NULL; 529 if (result == NULL) return NULL;
600 if (FLAG_trace_turbo_scheduler) { 530 TRACE(("Must dominate use %d in block %d\n", use->id(), result->id()));
601 PrintF("Must dominate use %d in block %d\n", use->id(), result->id());
602 }
603 return result; 531 return result;
604 } 532 }
605 533
606 void ScheduleNode(BasicBlock* block, Node* node) { 534 void ScheduleNode(BasicBlock* block, Node* node) {
607 schedule_->PlanNode(block, node); 535 schedule_->PlanNode(block, node);
608 scheduler_->scheduled_nodes_[block->id()].push_back(node); 536 scheduler_->scheduled_nodes_[block->id()].push_back(node);
609 537
610 // Reduce the use count of the node's inputs to potentially make them 538 // Reduce the use count of the node's inputs to potentially make them
611 // scheduable. 539 // scheduable.
612 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { 540 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
613 DCHECK(scheduler_->unscheduled_uses_[(*i)->id()] > 0); 541 DCHECK(scheduler_->unscheduled_uses_[(*i)->id()] > 0);
614 --scheduler_->unscheduled_uses_[(*i)->id()]; 542 --scheduler_->unscheduled_uses_[(*i)->id()];
615 if (FLAG_trace_turbo_scheduler) { 543 if (FLAG_trace_turbo_scheduler) {
616 PrintF("Decrementing use count for node %d from node %d (now %d)\n", 544 TRACE(("Decrementing use count for node %d from node %d (now %d)\n",
617 (*i)->id(), i.edge().from()->id(), 545 (*i)->id(), i.edge().from()->id(),
618 scheduler_->unscheduled_uses_[(*i)->id()]); 546 scheduler_->unscheduled_uses_[(*i)->id()]));
619 if (scheduler_->unscheduled_uses_[(*i)->id()] == 0) { 547 if (scheduler_->unscheduled_uses_[(*i)->id()] == 0) {
620 PrintF("node %d is now eligible for scheduling\n", (*i)->id()); 548 TRACE(("node %d is now eligible for scheduling\n", (*i)->id()));
621 } 549 }
622 } 550 }
623 } 551 }
624 } 552 }
625 553
626 Scheduler* scheduler_; 554 Scheduler* scheduler_;
627 Schedule* schedule_; 555 Schedule* schedule_;
628 }; 556 };
629 557
630 558
631 void Scheduler::ScheduleLate() { 559 void Scheduler::ScheduleLate() {
632 if (FLAG_trace_turbo_scheduler) { 560 TRACE(("------------------- SCHEDULE LATE -----------------\n"));
633 PrintF("------------------- SCHEDULE LATE -----------------\n");
634 }
635 561
636 // Schedule: Places nodes in dominator block of all their uses. 562 // Schedule: Places nodes in dominator block of all their uses.
637 ScheduleLateNodeVisitor schedule_late_visitor(this); 563 ScheduleLateNodeVisitor schedule_late_visitor(this);
638 564
639 { 565 {
640 Zone zone(zone_->isolate()); 566 Zone zone(zone_->isolate());
641 GenericGraphVisit::Visit<ScheduleLateNodeVisitor, 567 GenericGraphVisit::Visit<ScheduleLateNodeVisitor,
642 NodeInputIterationTraits<Node> >( 568 NodeInputIterationTraits<Node> >(
643 graph_, &zone, schedule_root_nodes_.begin(), schedule_root_nodes_.end(), 569 graph_, &zone, schedule_root_nodes_.begin(), schedule_root_nodes_.end(),
644 &schedule_late_visitor); 570 &schedule_late_visitor);
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 // (i.e. A -> B is a backedge). 784 // (i.e. A -> B is a backedge).
859 // => If block A dominates block B, then A appears before B in the order. 785 // => If block A dominates block B, then A appears before B in the order.
860 // => If block A is a loop header, A appears before all blocks in the loop 786 // => If block A is a loop header, A appears before all blocks in the loop
861 // headed at A. 787 // headed at A.
862 // 2. All loops are contiguous in the order (i.e. no intervening blocks that 788 // 2. All loops are contiguous in the order (i.e. no intervening blocks that
863 // do not belong to the loop.) 789 // do not belong to the loop.)
864 // Note a simple RPO traversal satisfies (1) but not (3). 790 // Note a simple RPO traversal satisfies (1) but not (3).
865 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) { 791 BasicBlockVector* Scheduler::ComputeSpecialRPO(Schedule* schedule) {
866 Zone tmp_zone(schedule->zone()->isolate()); 792 Zone tmp_zone(schedule->zone()->isolate());
867 Zone* zone = &tmp_zone; 793 Zone* zone = &tmp_zone;
868 if (FLAG_trace_turbo_scheduler) { 794 TRACE(("------------- COMPUTING SPECIAL RPO ---------------\n"));
869 PrintF("------------- COMPUTING SPECIAL RPO ---------------\n");
870 }
871 // RPO should not have been computed for this schedule yet. 795 // RPO should not have been computed for this schedule yet.
872 CHECK_EQ(kBlockUnvisited1, schedule->start()->rpo_number_); 796 CHECK_EQ(kBlockUnvisited1, schedule->start()->rpo_number_);
873 CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size())); 797 CHECK_EQ(0, static_cast<int>(schedule->rpo_order_.size()));
874 798
875 // Perform an iterative RPO traversal using an explicit stack, 799 // Perform an iterative RPO traversal using an explicit stack,
876 // recording backedges that form cycles. O(|B|). 800 // recording backedges that form cycles. O(|B|).
877 ZoneList<std::pair<BasicBlock*, int> > backedges(1, zone); 801 ZoneList<std::pair<BasicBlock*, int> > backedges(1, zone);
878 SpecialRPOStackFrame* stack = 802 SpecialRPOStackFrame* stack =
879 zone->NewArray<SpecialRPOStackFrame>(schedule->BasicBlockCount()); 803 zone->NewArray<SpecialRPOStackFrame>(schedule->BasicBlockCount());
880 BasicBlock* entry = schedule->start(); 804 BasicBlock* entry = schedule->start();
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
1020 ++i) { 944 ++i) {
1021 BasicBlock* current = *i; 945 BasicBlock* current = *i;
1022 current->loop_header_ = current_header; 946 current->loop_header_ = current_header;
1023 if (current->IsLoopHeader()) { 947 if (current->IsLoopHeader()) {
1024 loop_depth++; 948 loop_depth++;
1025 current_loop = &loops[current->loop_end_]; 949 current_loop = &loops[current->loop_end_];
1026 BlockList* end = current_loop->end; 950 BlockList* end = current_loop->end;
1027 current->loop_end_ = end == NULL ? static_cast<int>(final_order->size()) 951 current->loop_end_ = end == NULL ? static_cast<int>(final_order->size())
1028 : end->block->rpo_number_; 952 : end->block->rpo_number_;
1029 current_header = current_loop->header; 953 current_header = current_loop->header;
1030 if (FLAG_trace_turbo_scheduler) { 954 TRACE(("Block %d is a loop header, increment loop depth to %d\n",
1031 PrintF("Block %d is a loop header, increment loop depth to %d\n", 955 current->id(), loop_depth));
1032 current->id(), loop_depth);
1033 }
1034 } else { 956 } else {
1035 while (current_header != NULL && 957 while (current_header != NULL &&
1036 current->rpo_number_ >= current_header->loop_end_) { 958 current->rpo_number_ >= current_header->loop_end_) {
1037 DCHECK(current_header->IsLoopHeader()); 959 DCHECK(current_header->IsLoopHeader());
1038 DCHECK(current_loop != NULL); 960 DCHECK(current_loop != NULL);
1039 current_loop = current_loop->prev; 961 current_loop = current_loop->prev;
1040 current_header = current_loop == NULL ? NULL : current_loop->header; 962 current_header = current_loop == NULL ? NULL : current_loop->header;
1041 --loop_depth; 963 --loop_depth;
1042 } 964 }
1043 } 965 }
1044 current->loop_depth_ = loop_depth; 966 current->loop_depth_ = loop_depth;
1045 if (FLAG_trace_turbo_scheduler) { 967 TRACE(("Block %d's loop header is block %d, loop depth %d\n", current->id(),
1046 if (current->loop_header_ == NULL) { 968 current->loop_header_ == NULL ? -1 : current->loop_header_->id(),
1047 PrintF("Block %d's loop header is NULL, loop depth %d\n", current->id(), 969 current->loop_depth_));
1048 current->loop_depth_);
1049 } else {
1050 PrintF("Block %d's loop header is block %d, loop depth %d\n",
1051 current->id(), current->loop_header_->id(),
1052 current->loop_depth_);
1053 }
1054 }
1055 } 970 }
1056 971
1057 #if DEBUG 972 #if DEBUG
1058 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); 973 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order);
1059 VerifySpecialRPO(num_loops, loops, final_order); 974 VerifySpecialRPO(num_loops, loops, final_order);
1060 #endif 975 #endif
1061 return final_order; 976 return final_order;
1062 } 977 }
1063 } 978 }
1064 } 979 }
1065 } // namespace v8::internal::compiler 980 } // namespace v8::internal::compiler
OLDNEW
« no previous file with comments | « src/compiler/scheduler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698