Commit fb0a5a61 authored by titzer@chromium.org's avatar titzer@chromium.org

Fix O(n^2) successor traversal in ControlReducer.

R=mstarzinger@chromium.org
BUG=

Review URL: https://codereview.chromium.org/703163002

Cr-Commit-Position: refs/heads/master@{#25197}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@25197 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 88efe28d
...@@ -80,33 +80,41 @@ class ControlReducerImpl { ...@@ -80,33 +80,41 @@ class ControlReducerImpl {
Node* start = graph()->start(); Node* start = graph()->start();
ZoneVector<byte> fw_reachability(graph()->NodeCount(), 0, zone_); ZoneVector<byte> fw_reachability(graph()->NodeCount(), 0, zone_);
fw_reachability[start->id()] = kFromStart | kOnStack; fw_reachability[start->id()] = kFromStart | kOnStack;
stack_.push_back(start);
while (!stack_.empty()) { // We use a stack of (Node, UseIter) pairs to avoid O(n^2) traversal.
Node* node = stack_.back(); typedef std::pair<Node*, UseIter> FwIter;
ZoneDeque<FwIter> fw_stack(zone_);
fw_stack.push_back(FwIter(start, start->uses().begin()));
while (!fw_stack.empty()) {
Node* node = fw_stack.back().first;
TRACE(("ControlFw: #%d:%s\n", node->id(), node->op()->mnemonic())); TRACE(("ControlFw: #%d:%s\n", node->id(), node->op()->mnemonic()));
bool pop = true; bool pop = true;
for (Node* const succ : node->uses()) { while (fw_stack.back().second != node->uses().end()) {
Node* succ = *(fw_stack.back().second);
byte reach = fw_reachability[succ->id()]; byte reach = fw_reachability[succ->id()];
if ((reach & kOnStack) != 0 && state_[succ->id()] != kVisited) { if ((reach & kOnStack) != 0 && state_[succ->id()] != kVisited) {
// {succ} is on stack and not reachable from end. // {succ} is on stack and not reachable from end.
ConnectNTL(nodes, succ); ConnectNTL(nodes, succ);
fw_reachability.resize(graph()->NodeCount(), 0); fw_reachability.resize(graph()->NodeCount(), 0);
pop = false; // continue traversing inputs to this node. // 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; break;
} }
if ((reach & kFromStart) == 0 && if ((reach & kFromStart) == 0 &&
IrOpcode::IsControlOpcode(succ->opcode())) { IrOpcode::IsControlOpcode(succ->opcode())) {
// {succ} is a control node and not yet reached from start. // {succ} is a control node and not yet reached from start.
fw_reachability[succ->id()] |= kFromStart | kOnStack; fw_reachability[succ->id()] |= kFromStart | kOnStack;
stack_.push_back(succ); fw_stack.push_back(FwIter(succ, succ->uses().begin()));
pop = false; // "recurse" into successor control node. pop = false; // "recurse" into successor control node.
break; break;
} }
++fw_stack.back().second;
} }
if (pop) { if (pop) {
fw_reachability[node->id()] &= ~kOnStack; fw_reachability[node->id()] &= ~kOnStack;
stack_.pop_back(); fw_stack.pop_back();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment