Index: src/compiler/scheduler.cc |
diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc |
index 8cc1e78eaccd39faa6d40acd6b7860fccb2be416..e07c6b990db0497648bdfefd984e5a9f11eb72c6 100644 |
--- a/src/compiler/scheduler.cc |
+++ b/src/compiler/scheduler.cc |
@@ -219,7 +219,7 @@ class CFGBuilder { |
Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { |
- SchedulerData def = {0, 0, false, false, kUnknown}; |
+ SchedulerData def = {0, -1, false, false, kUnknown}; |
return def; |
} |
@@ -355,51 +355,63 @@ void Scheduler::GenerateImmediateDominatorTree() { |
class ScheduleEarlyNodeVisitor : public NullNodeVisitor { |
public: |
explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) |
- : has_changed_rpo_constraints_(true), |
- scheduler_(scheduler), |
- schedule_(scheduler->schedule_) {} |
+ : scheduler_(scheduler), schedule_(scheduler->schedule_) {} |
GenericGraphVisit::Control Pre(Node* node) { |
- int max_rpo = 0; |
- // Fixed nodes already know their schedule early position. |
if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { |
+ // Fixed nodes already know their schedule early position. |
+ Scheduler::SchedulerData* data = scheduler_->GetData(node); |
BasicBlock* block = schedule_->block(node); |
DCHECK(block != NULL); |
- max_rpo = block->rpo_number(); |
- if (scheduler_->GetData(node)->minimum_rpo_ != max_rpo) { |
- has_changed_rpo_constraints_ = true; |
+ if (data->minimum_rpo_ < 0) { |
+ data->minimum_rpo_ = block->rpo_number(); |
+ Trace("Preschedule #%d:%s minimum_rpo = %d (fixed)\n", node->id(), |
+ node->op()->mnemonic(), data->minimum_rpo_); |
+ } |
+ } else { |
+ // For unfixed nodes the minimum RPO is the max of all of the inputs. |
+ Scheduler::SchedulerData* data = scheduler_->GetData(node); |
+ if (data->minimum_rpo_ < 0) { |
+ data->minimum_rpo_ = ComputeMaximumInputRPO(node); |
+ if (data->minimum_rpo_ < 0) return GenericGraphVisit::REENTER; |
+ Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(), |
+ node->op()->mnemonic(), data->minimum_rpo_); |
} |
- scheduler_->GetData(node)->minimum_rpo_ = max_rpo; |
- Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(), |
- node->op()->mnemonic(), max_rpo); |
+ DCHECK_GE(data->minimum_rpo_, 0); |
} |
return GenericGraphVisit::CONTINUE; |
} |
GenericGraphVisit::Control Post(Node* node) { |
- int max_rpo = 0; |
- // Otherwise, the minimum rpo for the node is the max of all of the inputs. |
if (scheduler_->GetPlacement(node) != Scheduler::kFixed) { |
- for (InputIter i = node->inputs().begin(); i != node->inputs().end(); |
- ++i) { |
- int control_rpo = scheduler_->GetData(*i)->minimum_rpo_; |
- if (control_rpo > max_rpo) { |
- max_rpo = control_rpo; |
- } |
+ Scheduler::SchedulerData* data = scheduler_->GetData(node); |
+ // For unfixed nodes the minimum RPO is the max of all of the inputs. |
+ if (data->minimum_rpo_ < 0) { |
+ data->minimum_rpo_ = ComputeMaximumInputRPO(node); |
+ Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(), |
+ node->op()->mnemonic(), data->minimum_rpo_); |
} |
- if (scheduler_->GetData(node)->minimum_rpo_ != max_rpo) { |
- has_changed_rpo_constraints_ = true; |
- } |
- scheduler_->GetData(node)->minimum_rpo_ = max_rpo; |
- Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(), |
- node->op()->mnemonic(), max_rpo); |
+ DCHECK_GE(data->minimum_rpo_, 0); |
} |
return GenericGraphVisit::CONTINUE; |
} |
- // TODO(mstarzinger): Dirty hack to unblock others, schedule early should be |
- // rewritten to use a pre-order traversal from the start instead. |
- bool has_changed_rpo_constraints_; |
+ // Computes the maximum of the minimum RPOs for all inputs. If the maximum |
+ // cannot be determined (i.e. minimum RPO for at least one input not known), |
+ // then a negative number is returned. |
+ int ComputeMaximumInputRPO(Node* node) { |
+ int max_rpo = 0; |
+ for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { |
+ DCHECK_NE(node, *i); // Loops only exist for fixed nodes. |
+ int control_rpo = scheduler_->GetData(*i)->minimum_rpo_; |
+ if (control_rpo > max_rpo) { |
+ max_rpo = control_rpo; |
+ } else if (control_rpo < 0) { |
+ return control_rpo; |
+ } |
+ } |
+ return max_rpo; |
+ } |
private: |
Scheduler* scheduler_; |
@@ -410,15 +422,10 @@ class ScheduleEarlyNodeVisitor : public NullNodeVisitor { |
void Scheduler::ScheduleEarly() { |
Trace("------------------- SCHEDULE EARLY ----------------\n"); |
- int fixpoint_count = 0; |
+ // Compute the minimum RPO for each node thereby determining the earliest |
+ // position each node could be placed within a valid schedule. |
ScheduleEarlyNodeVisitor visitor(this); |
- while (visitor.has_changed_rpo_constraints_) { |
- visitor.has_changed_rpo_constraints_ = false; |
- graph_->VisitNodeInputsFromEnd(&visitor); |
- fixpoint_count++; |
- } |
- |
- Trace("It took %d iterations to determine fixpoint\n", fixpoint_count); |
+ graph_->VisitNodeInputsFromEnd(&visitor); |
} |
@@ -469,6 +476,7 @@ class PrepareUsesVisitor : public NullNodeVisitor { |
void Scheduler::PrepareUses() { |
Trace("------------------- PREPARE USES ------------------\n"); |
+ |
// Count the uses of every node, it will be used to ensure that all of a |
// node's uses are scheduled before the node itself. |
PrepareUsesVisitor prepare_uses(this); |