22#ifndef LLVM_ADT_SCCITERATOR_H
23#define LLVM_ADT_SCCITERATOR_H
34#include <unordered_map>
35#include <unordered_set>
46template <
class GraphT,
class GT = GraphTraits<GraphT>>
48 scc_iterator<GraphT, GT>, std::forward_iterator_tag,
49 const std::vector<typename GT::NodeRef>, ptrdiff_t> {
50 using NodeRef =
typename GT::NodeRef;
51 using ChildItTy =
typename GT::ChildIteratorType;
52 using SccTy = std::vector<NodeRef>;
53 using reference =
typename scc_iterator::reference;
61 StackElement(NodeRef
Node,
const ChildItTy &Child,
unsigned Min)
62 :
Node(
Node), NextChild(Child), MinVisited(Min) {}
66 NextChild ==
Other.NextChild &&
67 MinVisited ==
Other.MinVisited;
79 std::vector<NodeRef> SCCNodeStack;
86 std::vector<StackElement> VisitStack;
89 void DFSVisitOne(NodeRef
N);
92 void DFSVisitChildren();
114 assert(!CurrentSCC.empty() || VisitStack.empty());
115 return CurrentSCC.empty();
119 return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
128 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
141 assert(nodeVisitNumbers.
count(Old) &&
"Old not in scc_iterator?");
144 auto tempVal = nodeVisitNumbers[Old];
145 nodeVisitNumbers[New] = tempVal;
146 nodeVisitNumbers.
erase(Old);
150template <
class GraphT,
class GT>
151void scc_iterator<GraphT, GT>::DFSVisitOne(NodeRef
N) {
153 nodeVisitNumbers[
N] = visitNum;
154 SCCNodeStack.push_back(
N);
155 VisitStack.push_back(StackElement(
N, GT::child_begin(
N), visitNum));
157 dbgs() <<
"TarjanSCC: Node " <<
N <<
158 " : visitNum = " << visitNum <<
"\n";
162template <
class GraphT,
class GT>
163void scc_iterator<GraphT, GT>::DFSVisitChildren() {
164 assert(!VisitStack.empty());
165 while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
167 NodeRef childN = *VisitStack.back().NextChild++;
168 typename DenseMap<NodeRef, unsigned>::iterator Visited =
169 nodeVisitNumbers.find(childN);
170 if (Visited == nodeVisitNumbers.end()) {
176 unsigned childNum = Visited->second;
177 if (VisitStack.back().MinVisited > childNum)
178 VisitStack.back().MinVisited = childNum;
182template <
class GraphT,
class GT>
void scc_iterator<GraphT, GT>::GetNextSCC() {
184 while (!VisitStack.empty()) {
188 NodeRef visitingN = VisitStack.back().Node;
189 unsigned minVisitNum = VisitStack.back().MinVisited;
190 assert(VisitStack.back().NextChild == GT::child_end(visitingN));
191 VisitStack.pop_back();
194 if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
195 VisitStack.back().MinVisited = minVisitNum;
198 dbgs() <<
"TarjanSCC: Popped node " << visitingN <<
199 " : minVisitNum = " << minVisitNum <<
"; Node visit num = " <<
200 nodeVisitNumbers[visitingN] <<
"\n";
203 if (minVisitNum != nodeVisitNumbers[visitingN])
211 CurrentSCC.push_back(SCCNodeStack.back());
212 SCCNodeStack.pop_back();
213 nodeVisitNumbers[CurrentSCC.back()] = ~0
U;
214 }
while (CurrentSCC.back() != visitingN);
219template <
class GraphT,
class GT>
221 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
222 if (CurrentSCC.size() > 1)
224 NodeRef
N = CurrentSCC.front();
225 for (ChildItTy CI = GT::child_begin(
N), CE = GT::child_end(
N); CI != CE;
252template <
class GraphT,
class GT = GraphTraits<GraphT>>
254 using NodeType =
typename GT::NodeType;
255 using EdgeType =
typename GT::EdgeType;
256 using NodesType = std::vector<NodeType *>;
260 NodeInfo *Group =
this;
262 bool Visited =
false;
268 NodeInfo *find(NodeInfo *
Node) {
276 bool unionGroups(
const EdgeType *Edge) {
277 NodeInfo *G1 = find(&NodeInfoMap[Edge->Source]);
278 NodeInfo *G2 = find(&NodeInfoMap[Edge->Target]);
285 if (G1->Rank < G2->Rank)
290 if (G1->Rank == G2->Rank)
296 std::unordered_map<NodeType *, NodeInfo> NodeInfoMap;
305template <
class GraphT,
class GT>
307 const NodesType &InputNodes) {
308 if (InputNodes.size() <= 1) {
315 for (
auto *
Node : InputNodes) {
319 (void)NodeInfoMap[
Node].Group;
323 struct EdgeComparer {
324 bool operator()(
const EdgeType *L,
const EdgeType *R)
const {
325 return L->Weight > R->Weight;
329 std::multiset<const EdgeType *, EdgeComparer> SortedEdges;
330 for (
auto *
Node : InputNodes) {
331 for (
auto &Edge :
Node->Edges) {
332 if (NodeInfoMap.count(Edge.Target))
333 SortedEdges.insert(&Edge);
339 std::unordered_set<const EdgeType *> MSTEdges;
340 for (
auto *Edge : SortedEdges) {
341 if (unionGroups(Edge))
342 MSTEdges.insert(Edge);
350 std::queue<NodeType *> Queue;
351 for (
const auto *Edge : MSTEdges)
352 NodeInfoMap[Edge->Target].IncomingMSTEdges.insert(Edge);
356 for (
auto *Edge : SortedEdges) {
357 if (!NodeInfoMap[Edge->Source].Visited &&
358 NodeInfoMap[Edge->Source].IncomingMSTEdges.empty()) {
359 Queue.push(Edge->Source);
360 NodeInfoMap[Edge->Source].Visited =
true;
364 while (!Queue.empty()) {
365 auto *
Node = Queue.front();
367 Nodes.push_back(
Node);
368 for (
auto &Edge :
Node->Edges) {
369 NodeInfoMap[Edge.Target].IncomingMSTEdges.erase(&Edge);
370 if (MSTEdges.count(&Edge) &&
371 NodeInfoMap[Edge.Target].IncomingMSTEdges.empty()) {
372 Queue.push(Edge.Target);
377 assert(InputNodes.size() == Nodes.size() &&
"missing nodes in MST");
378 std::reverse(Nodes.begin(), Nodes.end());
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file defines the little GraphTraits<X> template class that should be specialized by classes that...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool erase(const KeyT &Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Implements a dense probed hash-table based set.
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
Enumerate the SCCs of a directed graph in reverse topological order of the SCC DAG.
scc_iterator & operator++()
static scc_iterator begin(const GraphT &G)
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
static scc_iterator end(const GraphT &)
bool operator==(const scc_iterator &x) const
void ReplaceNode(NodeRef Old, NodeRef New)
This informs the scc_iterator that the specified Old node has been deleted, and New is to be used in ...
bool hasCycle() const
Test if the current SCC has a cycle.
reference operator*() const
Sort the nodes of a directed SCC in the decreasing order of the edge weights.
scc_member_iterator(const NodesType &InputNodes)
std::pair< NodeId, LaneBitmask > NodeRef
This is an optimization pass for GlobalISel generic memory operations.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
bool operator==(const AddressRangeValuePair &LHS, const AddressRangeValuePair &RHS)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
scc_iterator< T > scc_end(const T &G)
Construct the end iterator for a deduced graph type T.