LLVM: include/llvm/ADT/SCCIterator.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22#ifndef LLVM_ADT_SCCITERATOR_H
23#define LLVM_ADT_SCCITERATOR_H
24
29#include
30#include
31#include
32#include
33#include
34#include <unordered_map>
35#include <unordered_set>
36#include
37
38namespace llvm {
39
40
41
42
43
44
45
46template <class GraphT, class GT = GraphTraits>
48 scc_iterator<GraphT, GT>, std::forward_iterator_tag,
49 const std::vector, ptrdiff_t> {
50 using NodeRef = typename GT::NodeRef;
51 using ChildItTy = typename GT::ChildIteratorType;
52 using SccTy = std::vector;
53 using reference = typename scc_iterator::reference;
54
55
56 struct StackElement {
57 NodeRef Node;
58 ChildItTy NextChild;
59 unsigned MinVisited;
60
61 StackElement(NodeRef Node, const ChildItTy &Child, unsigned Min)
62 : Node(Node), NextChild(Child), MinVisited(Min) {}
63
66 NextChild == Other.NextChild &&
67 MinVisited == Other.MinVisited;
68 }
69 };
70
71
72
73
74
75 unsigned visitNum;
77
78
79 std::vector SCCNodeStack;
80
81
82 SccTy CurrentSCC;
83
84
85
86 std::vector VisitStack;
87
88
89 void DFSVisitOne(NodeRef N);
90
91
92 void DFSVisitChildren();
93
94
95 void GetNextSCC();
96
97 scc_iterator(NodeRef entryN) : visitNum(0) {
98 DFSVisitOne(entryN);
99 GetNextSCC();
100 }
101
102
103 scc_iterator() = default;
104
105public:
106 static scc_iterator begin(const GraphT &G) {
107 return scc_iterator(GT::getEntryNode(G));
108 }
109 static scc_iterator end(const GraphT &) { return scc_iterator(); }
110
111
112
114 assert(!CurrentSCC.empty() || VisitStack.empty());
115 return CurrentSCC.empty();
116 }
117
119 return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC;
120 }
121
123 GetNextSCC();
124 return *this;
125 }
126
128 assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
129 return CurrentSCC;
130 }
131
132
133
134
135
137
138
139
141 assert(nodeVisitNumbers.count(Old) && "Old not in scc_iterator?");
142
143
144 auto tempVal = nodeVisitNumbers[Old];
145 nodeVisitNumbers[New] = tempVal;
146 nodeVisitNumbers.erase(Old);
147 }
148};
149
150template <class GraphT, class GT>
151void scc_iterator<GraphT, GT>::DFSVisitOne(NodeRef N) {
152 ++visitNum;
153 nodeVisitNumbers[N] = visitNum;
154 SCCNodeStack.push_back(N);
155 VisitStack.push_back(StackElement(N, GT::child_begin(N), visitNum));
156#if 0
157 dbgs() << "TarjanSCC: Node " << N <<
158 " : visitNum = " << visitNum << "\n";
159#endif
160}
161
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)) {
166
167 NodeRef childN = *VisitStack.back().NextChild++;
169 nodeVisitNumbers.find(childN);
170 if (Visited == nodeVisitNumbers.end()) {
171
172 DFSVisitOne(childN);
173 continue;
174 }
175
176 unsigned childNum = Visited->second;
177 if (VisitStack.back().MinVisited > childNum)
178 VisitStack.back().MinVisited = childNum;
179 }
180}
181
182template <class GraphT, class GT> void scc_iterator<GraphT, GT>::GetNextSCC() {
183 CurrentSCC.clear();
184 while (!VisitStack.empty()) {
185 DFSVisitChildren();
186
187
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();
192
193
194 if (!VisitStack.empty() && VisitStack.back().MinVisited > minVisitNum)
195 VisitStack.back().MinVisited = minVisitNum;
196
197#if 0
198 dbgs() << "TarjanSCC: Popped node " << visitingN <<
199 " : minVisitNum = " << minVisitNum << "; Node visit num = " <<
200 nodeVisitNumbers[visitingN] << "\n";
201#endif
202
203 if (minVisitNum != nodeVisitNumbers[visitingN])
204 continue;
205
206
207
208
209
210 do {
211 CurrentSCC.push_back(SCCNodeStack.back());
212 SCCNodeStack.pop_back();
213 nodeVisitNumbers[CurrentSCC.back()] = ~0U;
214 } while (CurrentSCC.back() != visitingN);
215 return;
216 }
217}
218
219template <class GraphT, class GT>
221 assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!");
222 if (CurrentSCC.size() > 1)
223 return true;
224 NodeRef N = CurrentSCC.front();
225 for (ChildItTy CI = GT::child_begin(N), CE = GT::child_end(N); CI != CE;
226 ++CI)
227 if (*CI == N)
228 return true;
229 return false;
230 }
231
232
236
237
241
242
243
244
245
246
247
248
249
250
251
252template <class GraphT, class GT = GraphTraits>
254 using NodeType = typename GT::NodeType;
255 using EdgeType = typename GT::EdgeType;
256 using NodesType = std::vector<NodeType *>;
257
258
259 struct NodeInfo {
260 NodeInfo *Group = this;
262 bool Visited = false;
264 };
265
266
267
268 NodeInfo *find(NodeInfo *Node) {
270 Node->Group = find(Node->Group);
271 return Node->Group;
272 }
273
274
275
276 bool unionGroups(const EdgeType *Edge) {
277 NodeInfo *G1 = find(&NodeInfoMap[Edge->Source]);
278 NodeInfo *G2 = find(&NodeInfoMap[Edge->Target]);
279
280
281 if (G1 == G2)
282 return false;
283
284
285 if (G1->Rank < G2->Rank)
286 G1->Group = G2;
287 else {
288 G2->Group = G1;
289
290 if (G1->Rank == G2->Rank)
291 G1->Rank++;
292 }
293 return true;
294 }
295
296 std::unordered_map<NodeType *, NodeInfo> NodeInfoMap;
297 NodesType Nodes;
298
299public:
301
303};
304
305template <class GraphT, class GT>
307 const NodesType &InputNodes) {
308 if (InputNodes.size() <= 1) {
309 Nodes = InputNodes;
310 return;
311 }
312
313
314 NodeInfoMap.clear();
315 for (auto *Node : InputNodes) {
316
317
318
319 NodeInfoMap.try_emplace(Node);
320 }
321
322
323 struct EdgeComparer {
324 bool operator()(const EdgeType *L, const EdgeType *R) const {
325 return L->Weight > R->Weight;
326 }
327 };
328
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);
334 }
335 }
336
337
338
339 std::unordered_set<const EdgeType *> MSTEdges;
340 for (auto *Edge : SortedEdges) {
341 if (unionGroups(Edge))
342 MSTEdges.insert(Edge);
343 }
344
345
346
347
348
349
350 std::queue<NodeType *> Queue;
351 for (const auto *Edge : MSTEdges)
352 NodeInfoMap[Edge->Target].IncomingMSTEdges.insert(Edge);
353
354
355
356 for (auto *Edge : SortedEdges) {
357 auto &Info = NodeInfoMap[Edge->Source];
358 if (.Visited && Info.IncomingMSTEdges.empty()) {
359 Queue.push(Edge->Source);
360 Info.Visited = true;
361 }
362 }
363
364 while (!Queue.empty()) {
365 auto *Node = Queue.front();
366 Queue.pop();
367 Nodes.push_back(Node);
368 for (auto &Edge : Node->Edges) {
369 NodeInfo &Info = NodeInfoMap[Edge.Target];
370 Info.IncomingMSTEdges.erase(&Edge);
371 if (MSTEdges.count(&Edge) && Info.IncomingMSTEdges.empty()) {
372 Queue.push(Edge.Target);
373 }
374 }
375 }
376
377 assert(InputNodes.size() == Nodes.size() && "missing nodes in MST");
378 std::reverse(Nodes.begin(), Nodes.end());
379}
380}
381
382#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
This file defines the little GraphTraits template class that should be specialized by classes that...
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
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.
Definition SCCIterator.h:49
scc_iterator & operator++()
Definition SCCIterator.h:122
static scc_iterator begin(const GraphT &G)
Definition SCCIterator.h:106
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
Definition SCCIterator.h:113
static scc_iterator end(const GraphT &)
Definition SCCIterator.h:109
bool operator==(const scc_iterator &x) const
Definition SCCIterator.h:118
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 ...
Definition SCCIterator.h:140
bool hasCycle() const
Test if the current SCC has a cycle.
Definition SCCIterator.h:220
reference operator*() const
Definition SCCIterator.h:127
scc_member_iterator(const NodesType &InputNodes)
Definition SCCIterator.h:306
NodesType & operator*()
Definition SCCIterator.h:302
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.
Definition SCCIterator.h:233
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.
Definition SCCIterator.h:238