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 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 block->id().ToInt()); | 212 block->id().ToInt()); |
213 } else { | 213 } else { |
214 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), | 214 Trace("Connect #%d:%s, B%d -> B%d\n", node->id(), node->op()->mnemonic(), |
215 block->id().ToInt(), succ->id().ToInt()); | 215 block->id().ToInt(), succ->id().ToInt()); |
216 } | 216 } |
217 } | 217 } |
218 }; | 218 }; |
219 | 219 |
220 | 220 |
221 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { | 221 Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { |
222 SchedulerData def = {0, 0, false, false, kUnknown}; | 222 SchedulerData def = {0, -1, false, false, kUnknown}; |
223 return def; | 223 return def; |
224 } | 224 } |
225 | 225 |
226 | 226 |
227 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule) | 227 Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule) |
228 : zone_(zone), | 228 : zone_(zone), |
229 graph_(graph), | 229 graph_(graph), |
230 schedule_(schedule), | 230 schedule_(schedule), |
231 scheduled_nodes_(zone), | 231 scheduled_nodes_(zone), |
232 schedule_root_nodes_(zone), | 232 schedule_root_nodes_(zone), |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 Trace("Block %d's idom is %d\n", current_rpo->id().ToInt(), | 348 Trace("Block %d's idom is %d\n", current_rpo->id().ToInt(), |
349 dominator->id().ToInt()); | 349 dominator->id().ToInt()); |
350 } | 350 } |
351 } | 351 } |
352 } | 352 } |
353 | 353 |
354 | 354 |
355 class ScheduleEarlyNodeVisitor : public NullNodeVisitor { | 355 class ScheduleEarlyNodeVisitor : public NullNodeVisitor { |
356 public: | 356 public: |
357 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) | 357 explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) |
358 : has_changed_rpo_constraints_(true), | 358 : scheduler_(scheduler), schedule_(scheduler->schedule_) {} |
359 scheduler_(scheduler), | |
360 schedule_(scheduler->schedule_) {} | |
361 | 359 |
362 GenericGraphVisit::Control Pre(Node* node) { | 360 GenericGraphVisit::Control Pre(Node* node) { |
363 int max_rpo = 0; | |
364 // Fixed nodes already know their schedule early position. | |
365 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { | 361 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { |
| 362 // Fixed nodes already know their schedule early position. |
| 363 Scheduler::SchedulerData* data = scheduler_->GetData(node); |
366 BasicBlock* block = schedule_->block(node); | 364 BasicBlock* block = schedule_->block(node); |
367 DCHECK(block != NULL); | 365 DCHECK(block != NULL); |
368 max_rpo = block->rpo_number(); | 366 if (data->minimum_rpo_ < 0) { |
369 if (scheduler_->GetData(node)->minimum_rpo_ != max_rpo) { | 367 data->minimum_rpo_ = block->rpo_number(); |
370 has_changed_rpo_constraints_ = true; | 368 Trace("Preschedule #%d:%s minimum_rpo = %d (fixed)\n", node->id(), |
| 369 node->op()->mnemonic(), data->minimum_rpo_); |
371 } | 370 } |
372 scheduler_->GetData(node)->minimum_rpo_ = max_rpo; | 371 } else { |
373 Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(), | 372 // For unfixed nodes the minimum RPO is the max of all of the inputs. |
374 node->op()->mnemonic(), max_rpo); | 373 Scheduler::SchedulerData* data = scheduler_->GetData(node); |
| 374 if (data->minimum_rpo_ < 0) { |
| 375 data->minimum_rpo_ = ComputeMaximumInputRPO(node); |
| 376 if (data->minimum_rpo_ < 0) return GenericGraphVisit::REENTER; |
| 377 Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(), |
| 378 node->op()->mnemonic(), data->minimum_rpo_); |
| 379 } |
| 380 DCHECK_GE(data->minimum_rpo_, 0); |
375 } | 381 } |
376 return GenericGraphVisit::CONTINUE; | 382 return GenericGraphVisit::CONTINUE; |
377 } | 383 } |
378 | 384 |
379 GenericGraphVisit::Control Post(Node* node) { | 385 GenericGraphVisit::Control Post(Node* node) { |
380 int max_rpo = 0; | |
381 // Otherwise, the minimum rpo for the node is the max of all of the inputs. | |
382 if (scheduler_->GetPlacement(node) != Scheduler::kFixed) { | 386 if (scheduler_->GetPlacement(node) != Scheduler::kFixed) { |
383 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); | 387 Scheduler::SchedulerData* data = scheduler_->GetData(node); |
384 ++i) { | 388 // For unfixed nodes the minimum RPO is the max of all of the inputs. |
385 int control_rpo = scheduler_->GetData(*i)->minimum_rpo_; | 389 if (data->minimum_rpo_ < 0) { |
386 if (control_rpo > max_rpo) { | 390 data->minimum_rpo_ = ComputeMaximumInputRPO(node); |
387 max_rpo = control_rpo; | 391 Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(), |
388 } | 392 node->op()->mnemonic(), data->minimum_rpo_); |
389 } | 393 } |
390 if (scheduler_->GetData(node)->minimum_rpo_ != max_rpo) { | 394 DCHECK_GE(data->minimum_rpo_, 0); |
391 has_changed_rpo_constraints_ = true; | |
392 } | |
393 scheduler_->GetData(node)->minimum_rpo_ = max_rpo; | |
394 Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(), | |
395 node->op()->mnemonic(), max_rpo); | |
396 } | 395 } |
397 return GenericGraphVisit::CONTINUE; | 396 return GenericGraphVisit::CONTINUE; |
398 } | 397 } |
399 | 398 |
400 // TODO(mstarzinger): Dirty hack to unblock others, schedule early should be | 399 // Computes the maximum of the minimum RPOs for all inputs. If the maximum |
401 // rewritten to use a pre-order traversal from the start instead. | 400 // cannot be determined (i.e. minimum RPO for at least one input not known), |
402 bool has_changed_rpo_constraints_; | 401 // then a negative number is returned. |
| 402 int ComputeMaximumInputRPO(Node* node) { |
| 403 int max_rpo = 0; |
| 404 for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { |
| 405 DCHECK_NE(node, *i); // Loops only exist for fixed nodes. |
| 406 int control_rpo = scheduler_->GetData(*i)->minimum_rpo_; |
| 407 if (control_rpo > max_rpo) { |
| 408 max_rpo = control_rpo; |
| 409 } else if (control_rpo < 0) { |
| 410 return control_rpo; |
| 411 } |
| 412 } |
| 413 return max_rpo; |
| 414 } |
403 | 415 |
404 private: | 416 private: |
405 Scheduler* scheduler_; | 417 Scheduler* scheduler_; |
406 Schedule* schedule_; | 418 Schedule* schedule_; |
407 }; | 419 }; |
408 | 420 |
409 | 421 |
410 void Scheduler::ScheduleEarly() { | 422 void Scheduler::ScheduleEarly() { |
411 Trace("------------------- SCHEDULE EARLY ----------------\n"); | 423 Trace("------------------- SCHEDULE EARLY ----------------\n"); |
412 | 424 |
413 int fixpoint_count = 0; | 425 // Compute the minimum RPO for each node thereby determining the earliest |
| 426 // position each node could be placed within a valid schedule. |
414 ScheduleEarlyNodeVisitor visitor(this); | 427 ScheduleEarlyNodeVisitor visitor(this); |
415 while (visitor.has_changed_rpo_constraints_) { | 428 graph_->VisitNodeInputsFromEnd(&visitor); |
416 visitor.has_changed_rpo_constraints_ = false; | |
417 graph_->VisitNodeInputsFromEnd(&visitor); | |
418 fixpoint_count++; | |
419 } | |
420 | |
421 Trace("It took %d iterations to determine fixpoint\n", fixpoint_count); | |
422 } | 429 } |
423 | 430 |
424 | 431 |
425 class PrepareUsesVisitor : public NullNodeVisitor { | 432 class PrepareUsesVisitor : public NullNodeVisitor { |
426 public: | 433 public: |
427 explicit PrepareUsesVisitor(Scheduler* scheduler) | 434 explicit PrepareUsesVisitor(Scheduler* scheduler) |
428 : scheduler_(scheduler), schedule_(scheduler->schedule_) {} | 435 : scheduler_(scheduler), schedule_(scheduler->schedule_) {} |
429 | 436 |
430 GenericGraphVisit::Control Pre(Node* node) { | 437 GenericGraphVisit::Control Pre(Node* node) { |
431 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { | 438 if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { |
(...skipping 30 matching lines...) Expand all Loading... |
462 } | 469 } |
463 | 470 |
464 private: | 471 private: |
465 Scheduler* scheduler_; | 472 Scheduler* scheduler_; |
466 Schedule* schedule_; | 473 Schedule* schedule_; |
467 }; | 474 }; |
468 | 475 |
469 | 476 |
470 void Scheduler::PrepareUses() { | 477 void Scheduler::PrepareUses() { |
471 Trace("------------------- PREPARE USES ------------------\n"); | 478 Trace("------------------- PREPARE USES ------------------\n"); |
| 479 |
472 // Count the uses of every node, it will be used to ensure that all of a | 480 // Count the uses of every node, it will be used to ensure that all of a |
473 // node's uses are scheduled before the node itself. | 481 // node's uses are scheduled before the node itself. |
474 PrepareUsesVisitor prepare_uses(this); | 482 PrepareUsesVisitor prepare_uses(this); |
475 graph_->VisitNodeInputsFromEnd(&prepare_uses); | 483 graph_->VisitNodeInputsFromEnd(&prepare_uses); |
476 } | 484 } |
477 | 485 |
478 | 486 |
479 class ScheduleLateNodeVisitor : public NullNodeVisitor { | 487 class ScheduleLateNodeVisitor : public NullNodeVisitor { |
480 public: | 488 public: |
481 explicit ScheduleLateNodeVisitor(Scheduler* scheduler) | 489 explicit ScheduleLateNodeVisitor(Scheduler* scheduler) |
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1125 | 1133 |
1126 #if DEBUG | 1134 #if DEBUG |
1127 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); | 1135 if (FLAG_trace_turbo_scheduler) PrintRPO(num_loops, loops, final_order); |
1128 VerifySpecialRPO(num_loops, loops, final_order); | 1136 VerifySpecialRPO(num_loops, loops, final_order); |
1129 #endif | 1137 #endif |
1130 return final_order; | 1138 return final_order; |
1131 } | 1139 } |
1132 } | 1140 } |
1133 } | 1141 } |
1134 } // namespace v8::internal::compiler | 1142 } // namespace v8::internal::compiler |
OLD | NEW |