Index: src/compiler/scheduler.cc |
diff --git a/src/compiler/scheduler.cc b/src/compiler/scheduler.cc |
index 5252d42dadb0680e5f1e8152ee1f4a0dadbdca66..03c4c377f913ad1e432f495ffaa45124fb4ce77c 100644 |
--- a/src/compiler/scheduler.cc |
+++ b/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" |
@@ -58,7 +59,7 @@ Schedule* Scheduler::ComputeSchedule(Zone* zone, Graph* graph) { |
Scheduler::SchedulerData Scheduler::DefaultSchedulerData() { |
- SchedulerData def = {schedule_->start(), 0, false, false, kUnknown}; |
+ SchedulerData def = {schedule_->start(), 0, false, kUnknown}; |
return def; |
} |
@@ -85,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: |
@@ -125,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(); |
@@ -241,7 +237,7 @@ class CFGBuilder : public ZoneObject { |
schedule_(scheduler->schedule_), |
queue_(zone), |
control_(zone), |
- component_head_(NULL), |
+ component_entry_(NULL), |
component_start_(NULL), |
component_end_(NULL) {} |
@@ -267,31 +263,37 @@ class CFGBuilder : public ZoneObject { |
} |
// 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) { |
+ void Run(BasicBlock* block, Node* exit) { |
ResetDataStructures(); |
- Queue(node); |
+ 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. |
} |
} |
@@ -316,7 +318,6 @@ class CFGBuilder : public ZoneObject { |
} |
} |
- |
void BuildBlocks(Node* node) { |
switch (node->opcode()) { |
case IrOpcode::kEnd: |
@@ -390,14 +391,14 @@ class CFGBuilder : public ZoneObject { |
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]); |
@@ -430,7 +431,7 @@ class CFGBuilder : public ZoneObject { |
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, |
@@ -455,8 +456,8 @@ class CFGBuilder : public ZoneObject { |
DCHECK(block != NULL); |
// For all of the merge's control inputs, add a goto at the end to the |
// merge's basic block. |
- for (Node* const j : merge->inputs()) { |
- 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); |
} |
@@ -485,6 +486,12 @@ class CFGBuilder : public ZoneObject { |
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()); |
@@ -495,7 +502,7 @@ class CFGBuilder : public ZoneObject { |
Schedule* schedule_; |
ZoneQueue<Node*> queue_; |
NodeVector control_; |
- Node* component_head_; |
+ Node* component_entry_; |
BasicBlock* component_start_; |
BasicBlock* component_end_; |
}; |
@@ -504,6 +511,9 @@ class CFGBuilder : public ZoneObject { |
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. |
control_flow_builder_ = new (zone_) CFGBuilder(zone_, this); |
@@ -1363,7 +1373,6 @@ class ScheduleLateNodeVisitor { |
} |
void ScheduleFloatingControl(BasicBlock* block, Node* node) { |
- DCHECK(scheduler_->GetData(node)->is_floating_control_); |
scheduler_->FuseFloatingControl(block, node); |
} |