| 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 |