From 31c642771740329f54620683ed0077127150c42e Mon Sep 17 00:00:00 2001 From: titzer Date: Mon, 1 Dec 2014 03:50:37 -0800 Subject: [PATCH] [turbofan] NodeMarker in ControlReducer. R=mstarzinger@chromium.org BUG= Review URL: https://codereview.chromium.org/767743003 Cr-Commit-Position: refs/heads/master@{#25583} --- src/compiler/control-reducer.cc | 93 ++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 37 deletions(-) diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc index b5acbb23e7..5068385514 100644 --- a/src/compiler/control-reducer.cc +++ b/src/compiler/control-reducer.cc @@ -15,9 +15,32 @@ namespace internal { namespace compiler { enum VisitState { kUnvisited = 0, kOnStack = 1, kRevisit = 2, kVisited = 3 }; -enum Reachability { kFromStart = 8 }; enum Decision { kFalse, kUnknown, kTrue }; +class ReachabilityMarker : public NodeMarker { + public: + explicit ReachabilityMarker(Graph* graph) : NodeMarker(graph, 8) {} + bool SetReachableFromEnd(Node* node) { + uint8_t before = Get(node); + Set(node, before | kFromEnd); + return before & kFromEnd; + } + bool IsReachableFromEnd(Node* node) { return Get(node) & kFromEnd; } + bool SetReachableFromStart(Node* node) { + uint8_t before = Get(node); + Set(node, before | kFromStart); + return before & kFromStart; + } + bool IsReachableFromStart(Node* node) { return Get(node) & kFromStart; } + void Push(Node* node) { Set(node, Get(node) | kFwStack); } + void Pop(Node* node) { Set(node, Get(node) & ~kFwStack); } + bool IsOnStack(Node* node) { return Get(node) & kFwStack; } + + private: + enum Bit { kFromEnd = 1, kFromStart = 2, kFwStack = 4 }; +}; + + #define TRACE(x) \ if (FLAG_trace_turbo_reduction) PrintF x @@ -72,15 +95,15 @@ class ControlReducerImpl { // we have to be careful about proper loop detection during reduction. // Gather all nodes backwards-reachable from end (through inputs). - state_.assign(graph()->NodeCount(), kUnvisited); + ReachabilityMarker marked(graph()); NodeVector nodes(zone_); - AddNodesReachableFromEnd(nodes); + AddNodesReachableFromEnd(marked, nodes); // Walk forward through control nodes, looking for back edges to nodes // that are not connected to end. Those are non-terminating loops (NTLs). Node* start = graph()->start(); - ZoneVector fw_reachability(graph()->NodeCount(), 0, zone_); - fw_reachability[start->id()] = kFromStart | kOnStack; + marked.Push(start); + marked.SetReachableFromStart(start); // We use a stack of (Node, UseIter) pairs to avoid O(n^2) traversal. typedef std::pair FwIter; @@ -93,20 +116,23 @@ class ControlReducerImpl { bool pop = true; while (fw_stack.back().second != node->uses().end()) { Node* succ = *(fw_stack.back().second); - byte reach = fw_reachability[succ->id()]; - if ((reach & kOnStack) != 0 && state_[succ->id()] != kVisited) { + if (marked.IsOnStack(succ) && !marked.IsReachableFromEnd(succ)) { // {succ} is on stack and not reachable from end. - ConnectNTL(nodes, succ); - fw_reachability.resize(graph()->NodeCount(), 0); + Node* added = ConnectNTL(succ); + nodes.push_back(added); + marked.SetReachableFromEnd(added); + AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); + // The use list of {succ} might have changed. fw_stack[fw_stack.size() - 1] = FwIter(succ, succ->uses().begin()); pop = false; // restart traversing successors of this node. break; } - if ((reach & kFromStart) == 0 && - IrOpcode::IsControlOpcode(succ->opcode())) { + if (IrOpcode::IsControlOpcode(succ->opcode()) && + !marked.IsReachableFromStart(succ)) { // {succ} is a control node and not yet reached from start. - fw_reachability[succ->id()] |= kFromStart | kOnStack; + marked.Push(succ); + marked.SetReachableFromStart(succ); fw_stack.push_back(FwIter(succ, succ->uses().begin())); pop = false; // "recurse" into successor control node. break; @@ -114,21 +140,20 @@ class ControlReducerImpl { ++fw_stack.back().second; } if (pop) { - fw_reachability[node->id()] &= ~kOnStack; + marked.Pop(node); fw_stack.pop_back(); } } // Trim references from dead nodes to live nodes first. jsgraph_->GetCachedNodes(&nodes); - TrimNodes(nodes); + TrimNodes(marked, nodes); // Any control nodes not reachable from start are dead, even loops. for (size_t i = 0; i < nodes.size(); i++) { Node* node = nodes[i]; - byte reach = fw_reachability[node->id()]; - if ((reach & kFromStart) == 0 && - IrOpcode::IsControlOpcode(node->opcode())) { + if (IrOpcode::IsControlOpcode(node->opcode()) && + !marked.IsReachableFromStart(node)) { ReplaceNode(node, dead()); // uses will be added to revisit queue. } } @@ -136,7 +161,7 @@ class ControlReducerImpl { } // Connect {loop}, the header of a non-terminating loop, to the end node. - void ConnectNTL(NodeVector& nodes, Node* loop) { + Node* ConnectNTL(Node* loop) { TRACE(("ConnectNTL: #%d:%s\n", loop->id(), loop->op()->mnemonic())); if (loop->opcode() != IrOpcode::kTerminate) { @@ -173,27 +198,24 @@ class ControlReducerImpl { merge->AppendInput(graph()->zone(), loop); merge->set_op(common_->Merge(merge->InputCount())); } - nodes.push_back(to_add); - state_.resize(graph()->NodeCount(), kUnvisited); - state_[to_add->id()] = kVisited; - AddBackwardsReachableNodes(nodes, nodes.size() - 1); + return to_add; } - void AddNodesReachableFromEnd(NodeVector& nodes) { + void AddNodesReachableFromEnd(ReachabilityMarker& marked, NodeVector& nodes) { Node* end = graph()->end(); - state_[end->id()] = kVisited; + marked.SetReachableFromEnd(end); if (!end->IsDead()) { nodes.push_back(end); - AddBackwardsReachableNodes(nodes, nodes.size() - 1); + AddBackwardsReachableNodes(marked, nodes, nodes.size() - 1); } } - void AddBackwardsReachableNodes(NodeVector& nodes, size_t cursor) { + void AddBackwardsReachableNodes(ReachabilityMarker& marked, NodeVector& nodes, + size_t cursor) { while (cursor < nodes.size()) { Node* node = nodes[cursor++]; for (Node* const input : node->inputs()) { - if (state_[input->id()] != kVisited) { - state_[input->id()] = kVisited; + if (!marked.SetReachableFromEnd(input)) { nodes.push_back(input); } } @@ -202,22 +224,21 @@ class ControlReducerImpl { void Trim() { // Gather all nodes backwards-reachable from end through inputs. - state_.assign(graph()->NodeCount(), kUnvisited); + ReachabilityMarker marked(graph()); NodeVector nodes(zone_); - AddNodesReachableFromEnd(nodes); + AddNodesReachableFromEnd(marked, nodes); // Process cached nodes in the JSGraph too. jsgraph_->GetCachedNodes(&nodes); - TrimNodes(nodes); + TrimNodes(marked, nodes); } - void TrimNodes(NodeVector& nodes) { + void TrimNodes(ReachabilityMarker& marked, NodeVector& nodes) { // Remove dead->live edges. for (size_t j = 0; j < nodes.size(); j++) { Node* node = nodes[j]; for (UseIter i = node->uses().begin(); i != node->uses().end();) { - size_t id = static_cast((*i)->id()); - if (state_[id] != kVisited) { + if (!marked.IsReachableFromEnd(*i)) { TRACE(("DeadLink: #%d:%s(%d) -> #%d:%s\n", (*i)->id(), (*i)->op()->mnemonic(), i.index(), node->id(), node->op()->mnemonic())); @@ -235,8 +256,7 @@ class ControlReducerImpl { CHECK_NE(NULL, input); } for (Node* const use : node->uses()) { - size_t id = static_cast(use->id()); - CHECK_EQ(kVisited, state_[id]); + CHECK(marked.IsReachableFromEnd(use)); } } #endif @@ -519,7 +539,6 @@ void ControlReducer::ReduceGraph(Zone* zone, JSGraph* jsgraph, CommonOperatorBuilder* common) { ControlReducerImpl impl(zone, jsgraph, common); impl.Reduce(); - impl.Trim(); }