22#ifndef LLVM_ADT_SCCITERATOR_H
23#define LLVM_ADT_SCCITERATOR_H
45template <
class GraphT,
class GT = GraphTraits<GraphT>>
47 scc_iterator<GraphT, GT>, std::forward_iterator_tag,
48 const std::vector<typename GT::NodeRef>, ptrdiff_t> {
49 using NodeRef =
typename GT::NodeRef;
50 using ChildItTy =
typename GT::ChildIteratorType;
51 using SccTy = std::vector<NodeRef>;
52 using reference =
typename scc_iterator::reference;
60 StackElement(NodeRef
Node,
const ChildItTy &Child,
unsigned Min)
61 :
Node(
Node), NextChild(Child), MinVisited(Min) {}
65 NextChild ==
Other.NextChild &&
66 MinVisited ==
Other.MinVisited;
78 std::vector<NodeRef> SCCNodeStack;
85 std::vector<StackElement> VisitStack;
88 void DFSVisitOne(NodeRef
N);
91 void DFSVisitChildren();
96 scc_iterator(NodeRef entryN) : visitNum(0) {
102 scc_iterator() =
default;
105 static scc_iterator
begin(
const GraphT &
G) {
106 return scc_iterator(GT::getEntryNode(
G));
108 static scc_iterator
end(
const GraphT &) {
return scc_iterator(); }
113 assert(!CurrentSCC.empty() || VisitStack.empty());
114 return CurrentSCC.empty();
118 return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
127 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
140 assert(nodeVisitNumbers.count(Old) &&
"Old not in scc_iterator?");
143 auto tempVal = nodeVisitNumbers[Old];
144 nodeVisitNumbers[New] = tempVal;
145 nodeVisitNumbers.erase(Old);
149template <
class GraphT,
class GT>
150void scc_iterator<GraphT, GT>::DFSVisitOne(NodeRef
N) {
152 nodeVisitNumbers[
N] = visitNum;
153 SCCNodeStack.push_back(
N);
154 VisitStack.push_back(StackElement(
N, GT::child_begin(
N), visitNum));
156 dbgs() <<
"TarjanSCC: Node " <<
N <<
157 " : visitNum = " << visitNum <<
"\n";
161template <
class GraphT,
class GT>
162void scc_iterator<GraphT, GT>::DFSVisitChildren() {
163 assert(!VisitStack.empty());
164 while (VisitStack.back().NextChild != GT::child_end(VisitStack.back().Node)) {
166 NodeRef childN = *VisitStack.back().NextChild++;
167 auto Visited = nodeVisitNumbers.find(childN);
168 if (Visited == nodeVisitNumbers.end()) {
174 unsigned childNum = Visited->second;
175 if (VisitStack.back().MinVisited > childNum)
176 VisitStack.back().MinVisited = childNum;
180template <
class GraphT,
class GT>
void scc_iterator<GraphT, GT>::GetNextSCC() {
182 while (!VisitStack.empty()) {
186 NodeRef visitingN = VisitStack.back().Node;
187 unsigned minVisitNum = VisitStack.back().MinVisited;
188 assert(VisitStack.back().NextChild == GT::child_end(visitingN));
189 VisitStack.pop_back();
192 if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
193 VisitStack.back().MinVisited = minVisitNum;
196 dbgs() <<
"TarjanSCC: Popped node " << visitingN <<
197 " : minVisitNum = " << minVisitNum <<
"; Node visit num = " <<
198 nodeVisitNumbers[visitingN] <<
"\n";
201 if (minVisitNum != nodeVisitNumbers[visitingN])
209 CurrentSCC.push_back(SCCNodeStack.back());
210 SCCNodeStack.pop_back();
211 nodeVisitNumbers[CurrentSCC.back()] = ~0
U;
212 }
while (CurrentSCC.back() != visitingN);
217template <
class GraphT,
class GT>
219 assert(!CurrentSCC.empty() &&
"Dereferencing END SCC iterator!");
220 if (CurrentSCC.size() > 1)
222 NodeRef
N = CurrentSCC.front();
223 for (ChildItTy CI = GT::child_begin(
N), CE = GT::child_end(
N); CI != CE;
250template <
class GraphT,
class GT = GraphTraits<GraphT>>
252 using NodeType =
typename GT::NodeType;
253 using EdgeType =
typename GT::EdgeType;
254 using NodesType = std::vector<NodeType *>;
258 NodeInfo *Group =
this;
260 bool Visited =
false;
266 NodeInfo *find(NodeInfo *
Node) {
274 bool unionGroups(
const EdgeType *Edge) {
275 NodeInfo *G1 = find(&NodeInfoMap[Edge->Source]);
276 NodeInfo *G2 = find(&NodeInfoMap[Edge->Target]);
283 if (G1->Rank < G2->Rank)
288 if (G1->Rank == G2->Rank)
303template <
class GraphT,
class GT>
305 const NodesType &InputNodes) {
306 if (InputNodes.size() <= 1) {
313 NodeInfoMap.reserve(InputNodes.size());
314 for (
auto *
Node : InputNodes) {
318 NodeInfoMap.try_emplace(
Node);
322 struct EdgeComparer {
323 bool operator()(
const EdgeType *L,
const EdgeType *R)
const {
324 return L->Weight > R->Weight;
328 std::multiset<const EdgeType *, EdgeComparer> SortedEdges;
329 for (
auto *
Node : InputNodes) {
330 for (
auto &Edge :
Node->Edges) {
331 if (NodeInfoMap.count(Edge.Target))
332 SortedEdges.insert(&Edge);
339 for (
auto *Edge : SortedEdges) {
340 if (unionGroups(Edge))
349 std::queue<NodeType *> Queue;
350 for (
const auto *Edge : MSTEdges)
351 NodeInfoMap[Edge->Target].IncomingMSTEdges.insert(Edge);
355 for (
auto *Edge : SortedEdges) {
356 auto &Info = NodeInfoMap[Edge->Source];
357 if (!Info.Visited && Info.IncomingMSTEdges.empty()) {
358 Queue.push(Edge->Source);
363 while (!Queue.empty()) {
364 auto *
Node = Queue.front();
366 Nodes.push_back(
Node);
367 for (
auto &Edge :
Node->Edges) {
370 auto It = NodeInfoMap.find(Edge.Target);
371 if (It == NodeInfoMap.end())
373 NodeInfo &Info = It->second;
374 Info.IncomingMSTEdges.erase(&Edge);
375 if (MSTEdges.
count(&Edge) && Info.IncomingMSTEdges.empty()) {
376 Queue.push(Edge.Target);
381 assert(InputNodes.size() == Nodes.size() &&
"missing nodes in MST");
382 std::reverse(Nodes.begin(), Nodes.end());
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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...
This file defines the SmallPtrSet class.
Implements a dense probed hash-table based set.
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
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
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.
LLVM_ABI 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.