From: titzer@chromium.org Date: Thu, 6 Nov 2014 13:27:24 +0000 (+0000) Subject: Fix O(n^2) successor traversal in ControlReducer. X-Git-Tag: upstream/4.7.83~5835 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fb0a5a61bccf293a9b2ac18935b3c7f26d1073c0;p=platform%2Fupstream%2Fv8.git 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 --- diff --git a/src/compiler/control-reducer.cc b/src/compiler/control-reducer.cc index 89b05d0..1d83103 100644 --- a/src/compiler/control-reducer.cc +++ b/src/compiler/control-reducer.cc @@ -80,33 +80,41 @@ class ControlReducerImpl { Node* start = graph()->start(); ZoneVector fw_reachability(graph()->NodeCount(), 0, zone_); fw_reachability[start->id()] = kFromStart | kOnStack; - stack_.push_back(start); - while (!stack_.empty()) { - Node* node = stack_.back(); + // We use a stack of (Node, UseIter) pairs to avoid O(n^2) traversal. + typedef std::pair FwIter; + ZoneDeque 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())); 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()]; if ((reach & kOnStack) != 0 && state_[succ->id()] != kVisited) { // {succ} is on stack and not reachable from end. ConnectNTL(nodes, succ); 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; } if ((reach & kFromStart) == 0 && IrOpcode::IsControlOpcode(succ->opcode())) { // {succ} is a control node and not yet reached from start. 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. break; } + ++fw_stack.back().second; } if (pop) { fw_reachability[node->id()] &= ~kOnStack; - stack_.pop_back(); + fw_stack.pop_back(); } }