Index: src/compiler/scheduler.cc |
diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc |
index 42ee0c4fb44ea8eb4f240877533197136e09b9ca..7a64f3ac8680440c06a39eca16e36573286655e9 100644 |
--- a/src/compiler/scheduler.cc |
+++ b/src/compiler/scheduler.cc |
@@ -521,27 +521,42 @@ void Scheduler::ScheduleEarly() { |
// Phase 4: Schedule nodes late. |
-class ScheduleLateNodeVisitor : public NullNodeVisitor { |
+class ScheduleLateNodeVisitor { |
public: |
- explicit ScheduleLateNodeVisitor(Scheduler* scheduler) |
- : scheduler_(scheduler), schedule_(scheduler_->schedule_) {} |
+ ScheduleLateNodeVisitor(Zone* zone, Scheduler* scheduler) |
+ : scheduler_(scheduler), schedule_(scheduler_->schedule_), queue_(zone) {} |
- GenericGraphVisit::Control Pre(Node* node) { |
- // Don't schedule nodes that are already scheduled. |
- if (schedule_->IsScheduled(node)) { |
- return GenericGraphVisit::CONTINUE; |
+ // Run the schedule late algorithm on a set of fixed root nodes. |
+ void Run(NodeVector* roots) { |
+ for (NodeVectorIter i = roots->begin(); i != roots->end(); ++i) { |
+ ProcessQueue(*i); |
} |
+ } |
+ |
+ private: |
+ void ProcessQueue(Node* root) { |
+ for (InputIter i = root->inputs().begin(); i != root->inputs().end(); ++i) { |
+ if (scheduler_->GetData(*i)->unscheduled_count_ != 0) continue; |
+ queue_.push(*i); |
+ while (!queue_.empty()) { |
+ VisitNode(queue_.front()); |
+ queue_.pop(); |
+ } |
+ } |
+ } |
+ |
+ // Visits one node from the queue of schedulable nodes and determines its |
+ // schedule late position. Also hoists nodes out of loops to find a more |
+ // optimal scheduling position. |
+ void VisitNode(Node* node) { |
+ DCHECK(scheduler_->GetData(node)->unscheduled_count_ == 0); |
+ |
+ // Don't schedule nodes that are already scheduled. |
+ if (schedule_->IsScheduled(node)) return; |
Scheduler::SchedulerData* data = scheduler_->GetData(node); |
DCHECK_EQ(Scheduler::kSchedulable, data->placement_); |
- // If all the uses of a node have been scheduled, then the node itself can |
- // be scheduled. |
- bool eligible = data->unscheduled_count_ == 0; |
- Trace("Testing for schedule eligibility for #%d:%s = %s\n", node->id(), |
- node->op()->mnemonic(), eligible ? "true" : "false"); |
- if (!eligible) return GenericGraphVisit::DEFER; |
- |
// Determine the dominating block for all of the uses of this node. It is |
// the latest block that this node can be scheduled in. |
BasicBlock* block = NULL; |
@@ -586,11 +601,8 @@ class ScheduleLateNodeVisitor : public NullNodeVisitor { |
} |
ScheduleNode(block, node); |
- |
- return GenericGraphVisit::CONTINUE; |
} |
- private: |
BasicBlock* GetBlockForUse(Node::Edge edge) { |
Node* use = edge.from(); |
IrOpcode::Value opcode = use->opcode(); |
@@ -619,7 +631,8 @@ class ScheduleLateNodeVisitor : public NullNodeVisitor { |
scheduler_->scheduled_nodes_[block->id().ToSize()].push_back(node); |
// Reduce the use count of the node's inputs to potentially make them |
- // schedulable. |
+ // schedulable. If all the uses of a node have been scheduled, then the node |
+ // itself can be scheduled. |
for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) { |
Scheduler::SchedulerData* data = scheduler_->GetData(*i); |
DCHECK(data->unscheduled_count_ > 0); |
@@ -628,10 +641,10 @@ class ScheduleLateNodeVisitor : public NullNodeVisitor { |
Trace(" Use count for #%d:%s (used by #%d:%s)-- = %d\n", (*i)->id(), |
(*i)->op()->mnemonic(), i.edge().from()->id(), |
i.edge().from()->op()->mnemonic(), data->unscheduled_count_); |
- if (data->unscheduled_count_ == 0) { |
- Trace(" newly eligible #%d:%s\n", (*i)->id(), |
- (*i)->op()->mnemonic()); |
- } |
+ } |
+ if (data->unscheduled_count_ == 0) { |
+ Trace(" newly eligible #%d:%s\n", (*i)->id(), (*i)->op()->mnemonic()); |
+ queue_.push(*i); |
} |
} |
@@ -649,10 +662,11 @@ class ScheduleLateNodeVisitor : public NullNodeVisitor { |
"%d\n", |
(*i)->id(), (*i)->op()->mnemonic(), node->id(), |
node->op()->mnemonic(), data->unscheduled_count_); |
- if (data->unscheduled_count_ == 0) { |
- Trace(" newly eligible #%d:%s\n", (*i)->id(), |
- (*i)->op()->mnemonic()); |
- } |
+ } |
+ if (data->unscheduled_count_ == 0) { |
+ Trace(" newly eligible #%d:%s\n", (*i)->id(), |
+ (*i)->op()->mnemonic()); |
+ queue_.push(*i); |
} |
} |
} |
@@ -661,6 +675,7 @@ class ScheduleLateNodeVisitor : public NullNodeVisitor { |
Scheduler* scheduler_; |
Schedule* schedule_; |
+ ZoneQueue<Node*> queue_; |
}; |
@@ -676,15 +691,10 @@ void Scheduler::ScheduleLate() { |
} |
// Schedule: Places nodes in dominator block of all their uses. |
- ScheduleLateNodeVisitor schedule_late_visitor(this); |
- |
{ |
ZonePool::Scope zone_scope(zone_pool_); |
- Zone* zone = zone_scope.zone(); |
- GenericGraphVisit::Visit<ScheduleLateNodeVisitor, |
- NodeInputIterationTraits<Node> >( |
- graph_, zone, schedule_root_nodes_.begin(), schedule_root_nodes_.end(), |
- &schedule_late_visitor); |
+ ScheduleLateNodeVisitor schedule_late_visitor(zone_scope.zone(), this); |
+ schedule_late_visitor.Run(&schedule_root_nodes_); |
} |
// Add collected nodes for basic blocks to their blocks in the right order. |