From e4fe4e2c5f5c598cddd7d9fe4644d802ec030fbe Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Wed, 22 Oct 2014 11:31:12 +0000 Subject: [PATCH] Switch ScheduleLateNodeVisitor to use explicit queue. R=jarin@chromium.org Review URL: https://codereview.chromium.org/672583002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24803 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/compiler/scheduler.cc | 76 +++++++++++++++++++++++++++-------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc index eb18b39..3ab96ab 100644 --- a/src/compiler/scheduler.cc +++ b/src/compiler/scheduler.cc @@ -535,27 +535,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; @@ -600,11 +615,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(); @@ -633,7 +645,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); @@ -642,10 +655,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); } } @@ -663,10 +676,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); } } } @@ -675,6 +689,7 @@ class ScheduleLateNodeVisitor : public NullNodeVisitor { Scheduler* scheduler_; Schedule* schedule_; + ZoneQueue queue_; }; @@ -690,15 +705,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 >( - 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. -- 2.7.4