| 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);
|
| }
|
|
|
|
|