| 207 | } |
| 208 | |
| 209 | bool PruneForReverseReachability(Graph* g, |
| 210 | std::unordered_set<const Node*> start) { |
| 211 | // Compute set of nodes that we need to traverse in order to reach |
| 212 | // the nodes in "start" by performing a breadth-first search from those |
| 213 | // nodes, and accumulating the visited nodes. |
| 214 | std::vector<bool> visited(g->num_node_ids()); |
| 215 | for (auto node : start) { |
| 216 | visited[node->id()] = true; |
| 217 | } |
| 218 | std::deque<const Node*> queue(start.begin(), start.end()); |
| 219 | while (!queue.empty()) { |
| 220 | const Node* n = queue.front(); |
| 221 | queue.pop_front(); |
| 222 | for (const Node* in : n->in_nodes()) { |
| 223 | if (!visited[in->id()]) { |
| 224 | visited[in->id()] = true; |
| 225 | queue.push_back(in); |
| 226 | VLOG(2) << "Reverse reach : " << n->name() << " from " << in->name(); |
| 227 | } |
| 228 | } |
| 229 | } |
| 230 | |
| 231 | // Make a pass over the graph to remove nodes not in "visited". |
| 232 | bool any_removed = false; |
| 233 | for (int i = 0; i < visited.size(); ++i) { |
| 234 | if (!visited[i]) { |
| 235 | Node* n = g->FindNodeId(i); |
| 236 | if (n != nullptr && !n->IsSource() && !n->IsSink()) { |
| 237 | g->RemoveNode(n); |
| 238 | any_removed = true; |
| 239 | } |
| 240 | } |
| 241 | } |
| 242 | return any_removed; |
| 243 | } |
| 244 | |
| 245 | bool FixupSourceAndSinkEdges(Graph* g) { |
| 246 | // Connect all nodes with no incoming edges to source. |