Switch schedule early phase to use forward propagation.

R=jarin@chromium.org

Review URL: https://codereview.chromium.org/655833005

Cr-Commit-Position: refs/heads/master@{#24923}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24923 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2b26c7a1
...@@ -64,7 +64,7 @@ Schedule* Scheduler::ComputeSchedule(ZonePool* zone_pool, Graph* graph) { ...@@ -64,7 +64,7 @@ Schedule* Scheduler::ComputeSchedule(ZonePool* zone_pool, Graph* graph) {
Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { Scheduler::SchedulerData Scheduler::DefaultSchedulerData() {
SchedulerData def = {NULL, 0, false, false, kUnknown}; SchedulerData def = {schedule_->start(), 0, false, false, kUnknown};
return def; return def;
} }
...@@ -952,76 +952,86 @@ void Scheduler::PrepareUses() { ...@@ -952,76 +952,86 @@ void Scheduler::PrepareUses() {
// Phase 4: Schedule nodes early. // Phase 4: Schedule nodes early.
class ScheduleEarlyNodeVisitor : public NullNodeVisitor { class ScheduleEarlyNodeVisitor {
public: public:
explicit ScheduleEarlyNodeVisitor(Scheduler* scheduler) ScheduleEarlyNodeVisitor(Zone* zone, Scheduler* scheduler)
: scheduler_(scheduler), schedule_(scheduler->schedule_) {} : scheduler_(scheduler), schedule_(scheduler->schedule_), queue_(zone) {}
GenericGraphVisit::Control Pre(Node* node) { // Run the schedule early algorithm on a set of fixed root nodes.
Scheduler::SchedulerData* data = scheduler_->GetData(node); void Run(NodeVector* roots) {
if (scheduler_->GetPlacement(node) == Scheduler::kFixed) { for (NodeVectorIter i = roots->begin(); i != roots->end(); ++i) {
// Fixed nodes already know their schedule early position. queue_.push(*i);
if (data->minimum_block_ == NULL) { while (!queue_.empty()) {
data->minimum_block_ = schedule_->block(node); VisitNode(queue_.front());
Trace("Preschedule #%d:%s minimum_rpo = %d (fixed)\n", node->id(), queue_.pop();
node->op()->mnemonic(), data->minimum_block_->rpo_number());
}
} else {
// For unfixed nodes the minimum RPO is the max of all of the inputs.
if (data->minimum_block_ == NULL) {
data->minimum_block_ = ComputeMaximumInputRPO(node);
if (data->minimum_block_ == NULL) return GenericGraphVisit::REENTER;
Trace("Preschedule #%d:%s minimum_rpo = %d\n", node->id(),
node->op()->mnemonic(), data->minimum_block_->rpo_number());
} }
} }
DCHECK_NE(data->minimum_block_, NULL);
return GenericGraphVisit::CONTINUE;
} }
GenericGraphVisit::Control Post(Node* node) { private:
// Visits one node from the queue and propagates its current schedule early
// position to all uses. This in turn might push more nodes onto the queue.
void VisitNode(Node* node) {
Scheduler::SchedulerData* data = scheduler_->GetData(node); Scheduler::SchedulerData* data = scheduler_->GetData(node);
if (scheduler_->GetPlacement(node) != Scheduler::kFixed) {
// For unfixed nodes the minimum RPO is the max of all of the inputs. // Fixed nodes already know their schedule early position.
if (data->minimum_block_ == NULL) { if (scheduler_->GetPlacement(node) == Scheduler::kFixed) {
data->minimum_block_ = ComputeMaximumInputRPO(node); DCHECK_EQ(schedule_->start(), data->minimum_block_);
Trace("Postschedule #%d:%s minimum_rpo = %d\n", node->id(), data->minimum_block_ = schedule_->block(node);
node->op()->mnemonic(), data->minimum_block_->rpo_number()); Trace("Fixing #%d:%s minimum_rpo = %d\n", node->id(),
} node->op()->mnemonic(), data->minimum_block_->rpo_number());
}
// No need to propagate unconstrained schedule early positions.
if (data->minimum_block_ == schedule_->start()) return;
// Propagate schedule early position.
DCHECK(data->minimum_block_ != NULL);
Node::Uses uses = node->uses();
for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) {
PropagateMinimumRPOToNode(data->minimum_block_, *i);
} }
DCHECK_NE(data->minimum_block_, NULL);
return GenericGraphVisit::CONTINUE;
} }
// Computes the maximum of the minimum RPOs for all inputs. If the maximum // Propagates {block} as another minimum RPO placement into the given {node}.
// cannot be determined (i.e. minimum RPO for at least one input is {NULL}), // This has the net effect of computing the maximum of the minimum RPOs for
// then {NULL} is returned. // all inputs to {node} when the queue has been fully processed.
BasicBlock* ComputeMaximumInputRPO(Node* node) { void PropagateMinimumRPOToNode(BasicBlock* block, Node* node) {
BasicBlock* max_block = schedule_->start(); Scheduler::SchedulerData* data = scheduler_->GetData(node);
for (InputIter i = node->inputs().begin(); i != node->inputs().end(); ++i) {
DCHECK_NE(node, *i); // Loops only exist for fixed nodes. // No need to propagate to fixed node, it's guaranteed to be a root.
BasicBlock* block = scheduler_->GetData(*i)->minimum_block_; if (scheduler_->GetPlacement(node) == Scheduler::kFixed) return;
if (block == NULL) return NULL;
if (block->rpo_number() > max_block->rpo_number()) { // Propagate new position if it is larger than the current.
max_block = block; if (block->rpo_number() > data->minimum_block_->rpo_number()) {
} data->minimum_block_ = block;
queue_.push(node);
Trace("Propagating #%d:%s minimum_rpo = %d\n", node->id(),
node->op()->mnemonic(), data->minimum_block_->rpo_number());
} }
return max_block;
} }
private:
Scheduler* scheduler_; Scheduler* scheduler_;
Schedule* schedule_; Schedule* schedule_;
ZoneQueue<Node*> queue_;
}; };
void Scheduler::ScheduleEarly() { void Scheduler::ScheduleEarly() {
Trace("--- SCHEDULE EARLY -----------------------------------------\n"); Trace("--- SCHEDULE EARLY -----------------------------------------\n");
if (FLAG_trace_turbo_scheduler) {
Trace("roots: ");
for (NodeVectorIter i = schedule_root_nodes_.begin();
i != schedule_root_nodes_.end(); ++i) {
Trace("#%d:%s ", (*i)->id(), (*i)->op()->mnemonic());
}
Trace("\n");
}
// Compute the minimum RPO for each node thereby determining the earliest // Compute the minimum RPO for each node thereby determining the earliest
// position each node could be placed within a valid schedule. // position each node could be placed within a valid schedule.
ScheduleEarlyNodeVisitor visitor(this); ScheduleEarlyNodeVisitor schedule_early_visitor(zone_, this);
graph_->VisitNodeInputsFromEnd(&visitor); schedule_early_visitor.Run(&schedule_root_nodes_);
} }
...@@ -1098,7 +1108,6 @@ class ScheduleLateNodeVisitor { ...@@ -1098,7 +1108,6 @@ class ScheduleLateNodeVisitor {
ScheduleNode(block, node); ScheduleNode(block, node);
} }
private:
BasicBlock* GetPreHeader(BasicBlock* block) { BasicBlock* GetPreHeader(BasicBlock* block) {
if (block->IsLoopHeader()) { if (block->IsLoopHeader()) {
return block->dominator(); return block->dominator();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment