summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/scheduler.cc
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2015-01-07 18:38:38 +0100
committerBen Noordhuis <info@bnoordhuis.nl>2015-01-07 22:11:18 +0100
commitdad73f645cde6920e79db956e7ef82ed640d7615 (patch)
tree7ba3f3fc7e0722c5f130065461b7c56f571af383 /deps/v8/src/compiler/scheduler.cc
parent53ba494537259b18b346dc6150d6a100c557e08f (diff)
downloadnode-new-dad73f645cde6920e79db956e7ef82ed640d7615.tar.gz
deps: upgrade v8 to 3.31.74.1
PR-URL: https://github.com/iojs/io.js/pull/243 Reviewed-By: Fedor Indutny <fedor@indutny.com> Reviewed-By: Trevor Norris <trev.norris@gmail.com>
Diffstat (limited to 'deps/v8/src/compiler/scheduler.cc')
-rw-r--r--deps/v8/src/compiler/scheduler.cc364
1 files changed, 182 insertions, 182 deletions
diff --git a/deps/v8/src/compiler/scheduler.cc b/deps/v8/src/compiler/scheduler.cc
index 36ed08823d..f12c6318d3 100644
--- a/deps/v8/src/compiler/scheduler.cc
+++ b/deps/v8/src/compiler/scheduler.cc
@@ -8,6 +8,7 @@
#include "src/compiler/scheduler.h"
#include "src/bit-vector.h"
+#include "src/compiler/control-equivalence.h"
#include "src/compiler/graph.h"
#include "src/compiler/graph-inl.h"
#include "src/compiler/node.h"
@@ -38,11 +39,10 @@ Scheduler::Scheduler(Zone* zone, Graph* graph, Schedule* schedule)
node_data_(graph_->NodeCount(), DefaultSchedulerData(), zone) {}
-Schedule* Scheduler::ComputeSchedule(ZonePool* zone_pool, Graph* graph) {
- ZonePool::Scope zone_scope(zone_pool);
+Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph) {
Schedule* schedule = new (graph->zone())
Schedule(graph->zone(), static_cast<size_t>(graph->NodeCount()));
- Scheduler scheduler(zone_scope.zone(), graph, schedule);
+ Scheduler scheduler(zone, graph, schedule);
scheduler.BuildCFG();
scheduler.ComputeSpecialRPONumbering();
@@ -59,7 +59,7 @@ Schedule* Scheduler::ComputeSchedule(ZonePool* zone_pool, Graph* graph) {
Scheduler::SchedulerData Scheduler::DefaultSchedulerData() {
- SchedulerData def = {schedule_->start(), 0, false, false, kUnknown};
+ SchedulerData def = {schedule_->start(), 0, kUnknown};
return def;
}
@@ -86,17 +86,12 @@ Scheduler::Placement Scheduler::GetPlacement(Node* node) {
data->placement_ = (p == kFixed ? kFixed : kCoupled);
break;
}
-#define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V:
- CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE)
-#undef DEFINE_FLOATING_CONTROL_CASE
+#define DEFINE_CONTROL_CASE(V) case IrOpcode::k##V:
+ CONTROL_OP_LIST(DEFINE_CONTROL_CASE)
+#undef DEFINE_CONTROL_CASE
{
// Control nodes that were not control-reachable from end may float.
data->placement_ = kSchedulable;
- if (!data->is_connected_control_) {
- data->is_floating_control_ = true;
- Trace("Floating control found: #%d:%s\n", node->id(),
- node->op()->mnemonic());
- }
break;
}
default:
@@ -126,9 +121,9 @@ void Scheduler::UpdatePlacement(Node* node, Placement placement) {
schedule_->AddNode(block, node);
break;
}
-#define DEFINE_FLOATING_CONTROL_CASE(V) case IrOpcode::k##V:
- CONTROL_OP_LIST(DEFINE_FLOATING_CONTROL_CASE)
-#undef DEFINE_FLOATING_CONTROL_CASE
+#define DEFINE_CONTROL_CASE(V) case IrOpcode::k##V:
+ CONTROL_OP_LIST(DEFINE_CONTROL_CASE)
+#undef DEFINE_CONTROL_CASE
{
// Control nodes force coupled uses to be placed.
Node::Uses uses = node->uses();
@@ -148,8 +143,8 @@ void Scheduler::UpdatePlacement(Node* node, Placement placement) {
// Reduce the use count of the node's inputs to potentially make them
// 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) {
- DecrementUnscheduledUseCount(*i, i.index(), i.edge().from());
+ for (Edge const edge : node->input_edges()) {
+ DecrementUnscheduledUseCount(edge.to(), edge.index(), edge.from());
}
}
data->placement_ = placement;
@@ -235,14 +230,15 @@ BasicBlock* Scheduler::GetCommonDominator(BasicBlock* b1, BasicBlock* b2) {
// between them within a Schedule) from the node graph. Visits control edges of
// the graph backwards from an end node in order to find the connected control
// subgraph, needed for scheduling.
-class CFGBuilder {
+class CFGBuilder : public ZoneObject {
public:
CFGBuilder(Zone* zone, Scheduler* scheduler)
: scheduler_(scheduler),
schedule_(scheduler->schedule_),
+ queued_(scheduler->graph_, 2),
queue_(zone),
control_(zone),
- component_head_(NULL),
+ component_entry_(NULL),
component_start_(NULL),
component_end_(NULL) {}
@@ -250,6 +246,7 @@ class CFGBuilder {
// backwards from end through control edges, building and connecting the
// basic blocks for control nodes.
void Run() {
+ ResetDataStructures();
Queue(scheduler_->graph_->end());
while (!queue_.empty()) { // Breadth-first backwards traversal.
@@ -267,35 +264,45 @@ class CFGBuilder {
}
// Run the control flow graph construction for a minimal control-connected
- // component ending in {node} and merge that component into an existing
+ // component ending in {exit} and merge that component into an existing
// control flow graph at the bottom of {block}.
- void Run(BasicBlock* block, Node* node) {
- Queue(node);
+ void Run(BasicBlock* block, Node* exit) {
+ ResetDataStructures();
+ Queue(exit);
+ component_entry_ = NULL;
component_start_ = block;
- component_end_ = schedule_->block(node);
+ component_end_ = schedule_->block(exit);
+ scheduler_->equivalence_->Run(exit);
while (!queue_.empty()) { // Breadth-first backwards traversal.
Node* node = queue_.front();
queue_.pop();
- bool is_dom = true;
+
+ // Use control dependence equivalence to find a canonical single-entry
+ // single-exit region that makes up a minimal component to be scheduled.
+ if (IsSingleEntrySingleExitRegion(node, exit)) {
+ Trace("Found SESE at #%d:%s\n", node->id(), node->op()->mnemonic());
+ DCHECK_EQ(NULL, component_entry_);
+ component_entry_ = node;
+ continue;
+ }
+
int max = NodeProperties::PastControlIndex(node);
for (int i = NodeProperties::FirstControlIndex(node); i < max; i++) {
- is_dom = is_dom &&
- !scheduler_->GetData(node->InputAt(i))->is_floating_control_;
Queue(node->InputAt(i));
}
- // TODO(mstarzinger): This is a hacky way to find component dominator.
- if (is_dom) component_head_ = node;
}
- DCHECK_NOT_NULL(component_head_);
+ DCHECK_NE(NULL, component_entry_);
for (NodeVector::iterator i = control_.begin(); i != control_.end(); ++i) {
- scheduler_->GetData(*i)->is_floating_control_ = false;
ConnectBlocks(*i); // Connect block to its predecessor/successors.
}
}
private:
+ // TODO(mstarzinger): Only for Scheduler::FuseFloatingControl.
+ friend class Scheduler;
+
void FixNode(BasicBlock* block, Node* node) {
schedule_->AddNode(block, node);
scheduler_->UpdatePlacement(node, Scheduler::kFixed);
@@ -303,16 +310,14 @@ class CFGBuilder {
void Queue(Node* node) {
// Mark the connected control nodes as they are queued.
- Scheduler::SchedulerData* data = scheduler_->GetData(node);
- if (!data->is_connected_control_) {
- data->is_connected_control_ = true;
+ if (!queued_.Get(node)) {
BuildBlocks(node);
queue_.push(node);
+ queued_.Set(node, true);
control_.push_back(node);
}
}
-
void BuildBlocks(Node* node) {
switch (node->opcode()) {
case IrOpcode::kEnd:
@@ -386,14 +391,14 @@ class CFGBuilder {
IrOpcode::Value false_opcode) {
buffer[0] = NULL;
buffer[1] = NULL;
- for (UseIter i = node->uses().begin(); i != node->uses().end(); ++i) {
- if ((*i)->opcode() == true_opcode) {
+ for (Node* use : node->uses()) {
+ if (use->opcode() == true_opcode) {
DCHECK_EQ(NULL, buffer[0]);
- buffer[0] = *i;
+ buffer[0] = use;
}
- if ((*i)->opcode() == false_opcode) {
+ if (use->opcode() == false_opcode) {
DCHECK_EQ(NULL, buffer[1]);
- buffer[1] = *i;
+ buffer[1] = use;
}
}
DCHECK_NE(NULL, buffer[0]);
@@ -426,7 +431,7 @@ class CFGBuilder {
break;
}
- if (branch == component_head_) {
+ if (branch == component_entry_) {
TraceConnect(branch, component_start_, successor_blocks[0]);
TraceConnect(branch, component_start_, successor_blocks[1]);
schedule_->InsertBranch(component_start_, component_end_, branch,
@@ -451,9 +456,8 @@ class CFGBuilder {
DCHECK(block != NULL);
// For all of the merge's control inputs, add a goto at the end to the
// merge's basic block.
- for (InputIter j = merge->inputs().begin(); j != merge->inputs().end();
- ++j) {
- BasicBlock* predecessor_block = schedule_->block(*j);
+ for (Node* const input : merge->inputs()) {
+ BasicBlock* predecessor_block = schedule_->block(input);
TraceConnect(merge, predecessor_block, block);
schedule_->AddGoto(predecessor_block, block);
}
@@ -482,23 +486,39 @@ class CFGBuilder {
node == scheduler_->graph_->end()->InputAt(0));
}
+ bool IsSingleEntrySingleExitRegion(Node* entry, Node* exit) const {
+ size_t entry_class = scheduler_->equivalence_->ClassOf(entry);
+ size_t exit_class = scheduler_->equivalence_->ClassOf(exit);
+ return entry != exit && entry_class == exit_class;
+ }
+
+ void ResetDataStructures() {
+ control_.clear();
+ DCHECK(queue_.empty());
+ DCHECK(control_.empty());
+ }
+
Scheduler* scheduler_;
Schedule* schedule_;
- ZoneQueue<Node*> queue_;
- NodeVector control_;
- Node* component_head_;
- BasicBlock* component_start_;
- BasicBlock* component_end_;
+ NodeMarker<bool> queued_; // Mark indicating whether node is queued.
+ ZoneQueue<Node*> queue_; // Queue used for breadth-first traversal.
+ NodeVector control_; // List of encountered control nodes.
+ Node* component_entry_; // Component single-entry node.
+ BasicBlock* component_start_; // Component single-entry block.
+ BasicBlock* component_end_; // Component single-exit block.
};
void Scheduler::BuildCFG() {
Trace("--- CREATING CFG -------------------------------------------\n");
+ // Instantiate a new control equivalence algorithm for the graph.
+ equivalence_ = new (zone_) ControlEquivalence(zone_, graph_);
+
// Build a control-flow graph for the main control-connected component that
// is being spanned by the graph's start and end nodes.
- CFGBuilder cfg_builder(zone_, this);
- cfg_builder.Run();
+ control_flow_builder_ = new (zone_) CFGBuilder(zone_, this);
+ control_flow_builder_->Run();
// Initialize per-block data.
scheduled_nodes_.resize(schedule_->BasicBlockCount(), NodeVector(zone_));
@@ -526,18 +546,18 @@ class SpecialRPONumberer : public ZoneObject {
: zone_(zone),
schedule_(schedule),
order_(NULL),
- loops_(zone),
beyond_end_(NULL),
- backedges_(1, zone),
+ loops_(zone),
+ backedges_(zone),
stack_(zone),
previous_block_count_(0) {}
// Computes the special reverse-post-order for the main control flow graph,
// that is for the graph spanned between the schedule's start and end blocks.
void ComputeSpecialRPO() {
+ DCHECK(schedule_->end()->SuccessorCount() == 0);
DCHECK_EQ(NULL, order_); // Main order does not exist yet.
- // TODO(mstarzinger): Should use Schedule::end() after tests are fixed.
- ComputeAndInsertSpecialRPO(schedule_->start(), NULL);
+ ComputeAndInsertSpecialRPO(schedule_->start(), schedule_->end());
}
// Computes the special reverse-post-order for a partial control flow graph,
@@ -548,27 +568,13 @@ class SpecialRPONumberer : public ZoneObject {
ComputeAndInsertSpecialRPO(entry, end);
}
- // Serialize the previously computed order as an assembly order (non-deferred
- // code first, deferred code afterwards) into the final schedule.
- void SerializeAOIntoSchedule() {
- int32_t number = 0;
- for (BlockList* l = order_; l != NULL; l = l->next) {
- if (l->block->deferred()) continue;
- l->block->set_ao_number(number++);
- }
- for (BlockList* l = order_; l != NULL; l = l->next) {
- if (!l->block->deferred()) continue;
- l->block->set_ao_number(number++);
- }
- }
-
// Serialize the previously computed order as a special reverse-post-order
// numbering for basic blocks into the final schedule.
void SerializeRPOIntoSchedule() {
int32_t number = 0;
- for (BlockList* l = order_; l != NULL; l = l->next) {
- l->block->set_rpo_number(number++);
- schedule_->rpo_order()->push_back(l->block);
+ for (BasicBlock* b = order_; b != NULL; b = b->rpo_next()) {
+ b->set_rpo_number(number++);
+ schedule_->rpo_order()->push_back(b);
}
BeyondEndSentinel()->set_rpo_number(number);
}
@@ -584,9 +590,6 @@ class SpecialRPONumberer : public ZoneObject {
private:
typedef std::pair<BasicBlock*, size_t> Backedge;
- // TODO(mstarzinger): Only for Scheduler::GenerateImmediateDominatorTree.
- friend class Scheduler;
-
// Numbering for BasicBlock::rpo_number for this block traversal:
static const int kBlockOnStack = -2;
static const int kBlockVisited1 = -3;
@@ -599,32 +602,13 @@ class SpecialRPONumberer : public ZoneObject {
size_t index;
};
- struct BlockList {
- BasicBlock* block;
- BlockList* next;
-
- BlockList* Add(Zone* zone, BasicBlock* b) {
- BlockList* list = static_cast<BlockList*>(zone->New(sizeof(BlockList)));
- list->block = b;
- list->next = this;
- return list;
- }
-
- BlockList* FindForBlock(BasicBlock* b) {
- for (BlockList* l = this; l != NULL; l = l->next) {
- if (l->block == b) return l;
- }
- return NULL;
- }
- };
-
struct LoopInfo {
BasicBlock* header;
ZoneList<BasicBlock*>* outgoing;
BitVector* members;
LoopInfo* prev;
- BlockList* end;
- BlockList* start;
+ BasicBlock* end;
+ BasicBlock* start;
void AddOutgoing(Zone* zone, BasicBlock* block) {
if (outgoing == NULL) {
@@ -645,14 +629,17 @@ class SpecialRPONumberer : public ZoneObject {
return depth;
}
- // We are hijacking the {ao_number} to enumerate loops temporarily. Note that
- // these numbers are only valid within this class.
- static int GetLoopNumber(BasicBlock* block) { return block->ao_number(); }
+ BasicBlock* PushFront(BasicBlock* head, BasicBlock* block) {
+ block->set_rpo_next(head);
+ return block;
+ }
+
+ static int GetLoopNumber(BasicBlock* block) { return block->loop_number(); }
static void SetLoopNumber(BasicBlock* block, int loop_number) {
- return block->set_ao_number(loop_number);
+ return block->set_loop_number(loop_number);
}
static bool HasLoopNumber(BasicBlock* block) {
- return block->ao_number() >= 0;
+ return block->loop_number() >= 0;
}
// TODO(mstarzinger): We only need this special sentinel because some tests
@@ -670,14 +657,13 @@ class SpecialRPONumberer : public ZoneObject {
// mutating any existing order so that the result is still valid.
void ComputeAndInsertSpecialRPO(BasicBlock* entry, BasicBlock* end) {
// RPO should not have been serialized for this schedule yet.
- CHECK_EQ(kBlockUnvisited1, schedule_->start()->ao_number());
+ CHECK_EQ(kBlockUnvisited1, schedule_->start()->loop_number());
CHECK_EQ(kBlockUnvisited1, schedule_->start()->rpo_number());
CHECK_EQ(0, static_cast<int>(schedule_->rpo_order()->size()));
// Find correct insertion point within existing order.
- BlockList* insert_before = order_->FindForBlock(entry);
- BlockList* insert_after = insert_before ? insert_before->next : NULL;
- BlockList* order = insert_after;
+ BasicBlock* insertion_point = entry->rpo_next();
+ BasicBlock* order = insertion_point;
// Perform an iterative RPO traversal using an explicit stack,
// recording backedges that form cycles. O(|B|).
@@ -685,7 +671,7 @@ class SpecialRPONumberer : public ZoneObject {
stack_.resize(schedule_->BasicBlockCount() - previous_block_count_);
previous_block_count_ = schedule_->BasicBlockCount();
int stack_depth = Push(stack_, 0, entry, kBlockUnvisited1);
- int num_loops = 0;
+ int num_loops = static_cast<int>(loops_.size());
while (stack_depth > 0) {
int current = stack_depth - 1;
@@ -698,7 +684,7 @@ class SpecialRPONumberer : public ZoneObject {
if (succ->rpo_number() == kBlockVisited1) continue;
if (succ->rpo_number() == kBlockOnStack) {
// The successor is on the stack, so this is a backedge (cycle).
- backedges_.Add(Backedge(frame->block, frame->index - 1), zone_);
+ backedges_.push_back(Backedge(frame->block, frame->index - 1));
if (!HasLoopNumber(succ)) {
// Assign a new loop number to the header if it doesn't have one.
SetLoopNumber(succ, num_loops++);
@@ -710,14 +696,14 @@ class SpecialRPONumberer : public ZoneObject {
}
} else {
// Finished with all successors; pop the stack and add the block.
- order = order->Add(zone_, frame->block);
+ order = PushFront(order, frame->block);
frame->block->set_rpo_number(kBlockVisited1);
stack_depth--;
}
}
// If no loops were encountered, then the order we computed was correct.
- if (num_loops != 0) {
+ if (num_loops > static_cast<int>(loops_.size())) {
// Otherwise, compute the loop information from the backedges in order
// to perform a traversal that groups loop bodies together.
ComputeLoopInfo(stack_, num_loops, &backedges_);
@@ -725,7 +711,7 @@ class SpecialRPONumberer : public ZoneObject {
// Initialize the "loop stack". Note the entry could be a loop header.
LoopInfo* loop =
HasLoopNumber(entry) ? &loops_[GetLoopNumber(entry)] : NULL;
- order = NULL;
+ order = insertion_point;
// Perform an iterative post-order traversal, visiting loop bodies before
// edges that lead out of loops. Visits each block once, but linking loop
@@ -737,7 +723,7 @@ class SpecialRPONumberer : public ZoneObject {
BasicBlock* block = frame->block;
BasicBlock* succ = NULL;
- if (frame->index < block->SuccessorCount()) {
+ if (block != end && frame->index < block->SuccessorCount()) {
// Process the next normal successor.
succ = block->SuccessorAt(frame->index++);
} else if (HasLoopNumber(block)) {
@@ -746,7 +732,7 @@ class SpecialRPONumberer : public ZoneObject {
// Finish the loop body the first time the header is left on the
// stack.
DCHECK(loop != NULL && loop->header == block);
- loop->start = order->Add(zone_, block);
+ loop->start = PushFront(order, block);
order = loop->end;
block->set_rpo_number(kBlockVisited2);
// Pop the loop stack and continue visiting outgoing edges within
@@ -761,7 +747,7 @@ class SpecialRPONumberer : public ZoneObject {
static_cast<int>(frame->index - block->SuccessorCount());
LoopInfo* info = &loops_[GetLoopNumber(block)];
DCHECK(loop != info);
- if (info->outgoing != NULL &&
+ if (block != entry && info->outgoing != NULL &&
outgoing_index < info->outgoing->length()) {
succ = info->outgoing->at(outgoing_index);
frame->index++;
@@ -794,9 +780,9 @@ class SpecialRPONumberer : public ZoneObject {
if (HasLoopNumber(block)) {
// If we are going to pop a loop header, then add its entire body.
LoopInfo* info = &loops_[GetLoopNumber(block)];
- for (BlockList* l = info->start; true; l = l->next) {
- if (l->next == info->end) {
- l->next = order;
+ for (BasicBlock* b = info->start; true; b = b->rpo_next()) {
+ if (b->rpo_next() == info->end) {
+ b->set_rpo_next(order);
info->end = order;
break;
}
@@ -804,7 +790,7 @@ class SpecialRPONumberer : public ZoneObject {
order = info->start;
} else {
// Pop a single node off the stack and add it to the order.
- order = order->Add(zone_, block);
+ order = PushFront(order, block);
block->set_rpo_number(kBlockVisited2);
}
stack_depth--;
@@ -812,23 +798,16 @@ class SpecialRPONumberer : public ZoneObject {
}
}
- // Insert result into existing order.
- if (insert_before == NULL) {
- order_ = order;
- } else {
- // There already is a list element for the entry block in the list, hence
- // we skip the first element of the sub-list to compensate duplication.
- DCHECK_EQ(insert_before->block, order->block);
- insert_before->next = order->next;
- }
+ // Publish new order the first time.
+ if (order_ == NULL) order_ = order;
// Compute the correct loop headers and set the correct loop ends.
LoopInfo* current_loop = NULL;
BasicBlock* current_header = entry->loop_header();
int32_t loop_depth = entry->loop_depth();
if (entry->IsLoopHeader()) --loop_depth; // Entry might be a loop header.
- for (BlockList* l = order; l != insert_after; l = l->next) {
- BasicBlock* current = l->block;
+ for (BasicBlock* b = order; b != insertion_point; b = b->rpo_next()) {
+ BasicBlock* current = b;
// Reset BasicBlock::rpo_number again.
current->set_rpo_number(kBlockUnvisited1);
@@ -847,8 +826,8 @@ class SpecialRPONumberer : public ZoneObject {
if (HasLoopNumber(current)) {
++loop_depth;
current_loop = &loops_[GetLoopNumber(current)];
- BlockList* end = current_loop->end;
- current->set_loop_end(end == NULL ? BeyondEndSentinel() : end->block);
+ BasicBlock* end = current_loop->end;
+ current->set_loop_end(end == NULL ? BeyondEndSentinel() : end);
current_header = current_loop->header;
Trace("B%d is a loop header, increment loop depth to %d\n",
current->id().ToInt(), loop_depth);
@@ -868,12 +847,21 @@ class SpecialRPONumberer : public ZoneObject {
// Computes loop membership from the backedges of the control flow graph.
void ComputeLoopInfo(ZoneVector<SpecialRPOStackFrame>& queue,
- size_t num_loops, ZoneList<Backedge>* backedges) {
+ size_t num_loops, ZoneVector<Backedge>* backedges) {
+ // Extend existing loop membership vectors.
+ for (LoopInfo& loop : loops_) {
+ BitVector* new_members = new (zone_)
+ BitVector(static_cast<int>(schedule_->BasicBlockCount()), zone_);
+ new_members->CopyFrom(*loop.members);
+ loop.members = new_members;
+ }
+
+ // Extend loop information vector.
loops_.resize(num_loops, LoopInfo());
// Compute loop membership starting from backedges.
// O(max(loop_depth) * max(|loop|)
- for (int i = 0; i < backedges->length(); i++) {
+ for (size_t i = 0; i < backedges->size(); i++) {
BasicBlock* member = backedges->at(i).first;
BasicBlock* header = member->SuccessorAt(backedges->at(i).second);
size_t loop_num = GetLoopNumber(header);
@@ -924,8 +912,7 @@ class SpecialRPONumberer : public ZoneObject {
}
os << ":\n";
- for (BlockList* l = order_; l != NULL; l = l->next) {
- BasicBlock* block = l->block;
+ for (BasicBlock* block = order_; block != NULL; block = block->rpo_next()) {
BasicBlock::Id bid = block->id();
// TODO(jarin,svenpanne): Add formatting here once we have support for
// that in streams (we want an equivalent of PrintF("%5d:", x) here).
@@ -971,18 +958,18 @@ class SpecialRPONumberer : public ZoneObject {
// Verify the start ... end list relationship.
int links = 0;
- BlockList* l = loop->start;
- DCHECK(l != NULL && l->block == header);
+ BasicBlock* block = loop->start;
+ DCHECK_EQ(header, block);
bool end_found;
while (true) {
- if (l == NULL || l == loop->end) {
- end_found = (loop->end == l);
+ if (block == NULL || block == loop->end) {
+ end_found = (loop->end == block);
break;
}
// The list should be in same order as the final result.
- DCHECK(l->block->rpo_number() == links + header->rpo_number());
+ DCHECK(block->rpo_number() == links + header->rpo_number());
links++;
- l = l->next;
+ block = block->rpo_next();
DCHECK(links < static_cast<int>(2 * order->size())); // cycle?
}
DCHECK(links > 0);
@@ -1016,23 +1003,18 @@ class SpecialRPONumberer : public ZoneObject {
Zone* zone_;
Schedule* schedule_;
- BlockList* order_;
- ZoneVector<LoopInfo> loops_;
+ BasicBlock* order_;
BasicBlock* beyond_end_;
- ZoneList<Backedge> backedges_;
+ ZoneVector<LoopInfo> loops_;
+ ZoneVector<Backedge> backedges_;
ZoneVector<SpecialRPOStackFrame> stack_;
size_t previous_block_count_;
};
-BasicBlockVector* Scheduler::ComputeSpecialRPO(ZonePool* zone_pool,
- Schedule* schedule) {
- ZonePool::Scope zone_scope(zone_pool);
- Zone* zone = zone_scope.zone();
-
+BasicBlockVector* Scheduler::ComputeSpecialRPO(Zone* zone, Schedule* schedule) {
SpecialRPONumberer numberer(zone, schedule);
numberer.ComputeSpecialRPO();
- numberer.SerializeAOIntoSchedule();
numberer.SerializeRPOIntoSchedule();
numberer.PrintAndVerifySpecialRPO();
return schedule->rpo_order();
@@ -1048,19 +1030,10 @@ void Scheduler::ComputeSpecialRPONumbering() {
}
-void Scheduler::GenerateImmediateDominatorTree() {
- Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n");
-
- // TODO(danno): Consider using Lengauer & Tarjan's if this becomes too slow.
-
- // Build the block dominator tree.
- schedule_->start()->set_dominator_depth(0);
- typedef SpecialRPONumberer::BlockList BlockList;
- for (BlockList* l = special_rpo_->order_; l != NULL; l = l->next) {
- BasicBlock* current = l->block;
- if (current == schedule_->start()) continue;
- BasicBlock::Predecessors::iterator pred = current->predecessors_begin();
- BasicBlock::Predecessors::iterator end = current->predecessors_end();
+void Scheduler::PropagateImmediateDominators(BasicBlock* block) {
+ for (/*nop*/; block != NULL; block = block->rpo_next()) {
+ BasicBlock::Predecessors::iterator pred = block->predecessors_begin();
+ BasicBlock::Predecessors::iterator end = block->predecessors_end();
DCHECK(pred != end); // All blocks except start have predecessors.
BasicBlock* dominator = *pred;
// For multiple predecessors, walk up the dominator tree until a common
@@ -1071,16 +1044,27 @@ void Scheduler::GenerateImmediateDominatorTree() {
if ((*pred)->dominator_depth() < 0) continue;
dominator = GetCommonDominator(dominator, *pred);
}
- current->set_dominator(dominator);
- current->set_dominator_depth(dominator->dominator_depth() + 1);
+ block->set_dominator(dominator);
+ block->set_dominator_depth(dominator->dominator_depth() + 1);
// Propagate "deferredness" of the dominator.
- if (dominator->deferred()) current->set_deferred(true);
- Trace("Block B%d's idom is B%d, depth = %d\n", current->id().ToInt(),
- dominator->id().ToInt(), current->dominator_depth());
+ if (dominator->deferred()) block->set_deferred(true);
+ Trace("Block B%d's idom is B%d, depth = %d\n", block->id().ToInt(),
+ dominator->id().ToInt(), block->dominator_depth());
}
}
+void Scheduler::GenerateImmediateDominatorTree() {
+ Trace("--- IMMEDIATE BLOCK DOMINATORS -----------------------------\n");
+
+ // Seed start block to be the first dominator.
+ schedule_->start()->set_dominator_depth(0);
+
+ // Build the block dominator tree resulting from the above seed.
+ PropagateImmediateDominators(schedule_->start()->rpo_next());
+}
+
+
// -----------------------------------------------------------------------------
// Phase 3: Prepare use counts for nodes.
@@ -1163,7 +1147,6 @@ class ScheduleEarlyNodeVisitor {
// Fixed nodes already know their schedule early position.
if (scheduler_->GetPlacement(node) == Scheduler::kFixed) {
- DCHECK_EQ(schedule_->start(), data->minimum_block_);
data->minimum_block_ = schedule_->block(node);
Trace("Fixing #%d:%s minimum_block = B%d, dominator_depth = %d\n",
node->id(), node->op()->mnemonic(),
@@ -1260,9 +1243,7 @@ class ScheduleLateNodeVisitor {
private:
void ProcessQueue(Node* root) {
ZoneQueue<Node*>* queue = &(scheduler_->schedule_queue_);
- for (InputIter i = root->inputs().begin(); i != root->inputs().end(); ++i) {
- Node* node = *i;
-
+ for (Node* node : root->inputs()) {
// Don't schedule coupled nodes on their own.
if (scheduler_->GetPlacement(node) == Scheduler::kCoupled) {
node = NodeProperties::GetControlInput(node);
@@ -1335,9 +1316,8 @@ class ScheduleLateNodeVisitor {
BasicBlock* GetCommonDominatorOfUses(Node* node) {
BasicBlock* block = NULL;
- Node::Uses uses = node->uses();
- for (Node::Uses::iterator i = uses.begin(); i != uses.end(); ++i) {
- BasicBlock* use_block = GetBlockForUse(i.edge());
+ for (Edge edge : node->use_edges()) {
+ BasicBlock* use_block = GetBlockForUse(edge);
block = block == NULL ? use_block : use_block == NULL
? block
: scheduler_->GetCommonDominator(
@@ -1346,7 +1326,7 @@ class ScheduleLateNodeVisitor {
return block;
}
- BasicBlock* GetBlockForUse(Node::Edge edge) {
+ BasicBlock* GetBlockForUse(Edge edge) {
Node* use = edge.from();
IrOpcode::Value opcode = use->opcode();
if (opcode == IrOpcode::kPhi || opcode == IrOpcode::kEffectPhi) {
@@ -1377,7 +1357,6 @@ class ScheduleLateNodeVisitor {
}
void ScheduleFloatingControl(BasicBlock* block, Node* node) {
- DCHECK(scheduler_->GetData(node)->is_floating_control_);
scheduler_->FuseFloatingControl(block, node);
}
@@ -1416,7 +1395,6 @@ void Scheduler::SealFinalSchedule() {
Trace("--- SEAL FINAL SCHEDULE ------------------------------------\n");
// Serialize the assembly order and reverse-post-order numbering.
- special_rpo_->SerializeAOIntoSchedule();
special_rpo_->SerializeRPOIntoSchedule();
special_rpo_->PrintAndVerifySpecialRPO();
@@ -1443,17 +1421,39 @@ void Scheduler::FuseFloatingControl(BasicBlock* block, Node* node) {
}
// Iterate on phase 1: Build control-flow graph.
- CFGBuilder cfg_builder(zone_, this);
- cfg_builder.Run(block, node);
+ control_flow_builder_->Run(block, node);
// Iterate on phase 2: Compute special RPO and dominator tree.
special_rpo_->UpdateSpecialRPO(block, schedule_->block(node));
// TODO(mstarzinger): Currently "iterate on" means "re-run". Fix that.
- for (BasicBlock* block : schedule_->all_blocks_) {
- block->set_dominator_depth(-1);
- block->set_dominator(NULL);
+ for (BasicBlock* b = block->rpo_next(); b != NULL; b = b->rpo_next()) {
+ b->set_dominator_depth(-1);
+ b->set_dominator(NULL);
+ }
+ PropagateImmediateDominators(block->rpo_next());
+
+ // Iterate on phase 4: Schedule nodes early.
+ // TODO(mstarzinger): The following loop gathering the propagation roots is a
+ // temporary solution and should be merged into the rest of the scheduler as
+ // soon as the approach settled for all floating loops.
+ NodeVector propagation_roots(control_flow_builder_->control_);
+ for (Node* node : control_flow_builder_->control_) {
+ for (Node* use : node->uses()) {
+ if (use->opcode() == IrOpcode::kPhi ||
+ use->opcode() == IrOpcode::kEffectPhi) {
+ propagation_roots.push_back(use);
+ }
+ }
+ }
+ if (FLAG_trace_turbo_scheduler) {
+ Trace("propagation roots: ");
+ for (Node* node : propagation_roots) {
+ Trace("#%d:%s ", node->id(), node->op()->mnemonic());
+ }
+ Trace("\n");
}
- GenerateImmediateDominatorTree();
+ ScheduleEarlyNodeVisitor schedule_early_visitor(zone_, this);
+ schedule_early_visitor.Run(&propagation_roots);
// Move previously planned nodes.
// TODO(mstarzinger): Improve that by supporting bulk moves.