1 //===- llvm/ADT/DirectedGraph.h - Directed Graph ----------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the interface and a base class implementation for a
12 //===----------------------------------------------------------------------===//
14 #ifndef LLVM_ADT_DIRECTEDGRAPH_H
15 #define LLVM_ADT_DIRECTEDGRAPH_H
17 #include "llvm/ADT/GraphTraits.h"
18 #include "llvm/ADT/SetVector.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
25 /// Represent an edge in the directed graph.
26 /// The edge contains the target node it connects to.
27 template <class NodeType
, class EdgeType
> class DGEdge
{
30 /// Create an edge pointing to the given node \p N.
31 explicit DGEdge(NodeType
&N
) : TargetNode(N
) {}
32 explicit DGEdge(const DGEdge
<NodeType
, EdgeType
> &E
)
33 : TargetNode(E
.TargetNode
) {}
34 DGEdge
<NodeType
, EdgeType
> &operator=(const DGEdge
<NodeType
, EdgeType
> &E
) {
35 TargetNode
= E
.TargetNode
;
39 /// Static polymorphism: delegate implementation (via isEqualTo) to the
41 bool operator==(const EdgeType
&E
) const { return getDerived().isEqualTo(E
); }
42 bool operator!=(const EdgeType
&E
) const { return !operator==(E
); }
44 /// Retrieve the target node this edge connects to.
45 const NodeType
&getTargetNode() const { return TargetNode
; }
46 NodeType
&getTargetNode() {
47 return const_cast<NodeType
&>(
48 static_cast<const DGEdge
<NodeType
, EdgeType
> &>(*this).getTargetNode());
52 // As the default implementation use address comparison for equality.
53 bool isEqualTo(const EdgeType
&E
) const { return this == &E
; }
55 // Cast the 'this' pointer to the derived type and return a reference.
56 EdgeType
&getDerived() { return *static_cast<EdgeType
*>(this); }
57 const EdgeType
&getDerived() const {
58 return *static_cast<const EdgeType
*>(this);
61 // The target node this edge connects to.
65 /// Represent a node in the directed graph.
66 /// The node has a (possibly empty) list of outgoing edges.
67 template <class NodeType
, class EdgeType
> class DGNode
{
69 using EdgeListTy
= SetVector
<EdgeType
*>;
70 using iterator
= typename
EdgeListTy::iterator
;
71 using const_iterator
= typename
EdgeListTy::const_iterator
;
73 /// Create a node with a single outgoing edge \p E.
74 explicit DGNode(EdgeType
&E
) : Edges() { Edges
.insert(&E
); }
77 explicit DGNode(const DGNode
<NodeType
, EdgeType
> &N
) : Edges(N
.Edges
) {}
78 DGNode(DGNode
<NodeType
, EdgeType
> &&N
) : Edges(std::move(N
.Edges
)) {}
80 DGNode
<NodeType
, EdgeType
> &operator=(const DGNode
<NodeType
, EdgeType
> &N
) {
84 DGNode
<NodeType
, EdgeType
> &operator=(const DGNode
<NodeType
, EdgeType
> &&N
) {
85 Edges
= std::move(N
.Edges
);
89 /// Static polymorphism: delegate implementation (via isEqualTo) to the
91 bool operator==(const NodeType
&N
) const { return getDerived().isEqualTo(N
); }
92 bool operator!=(const NodeType
&N
) const { return !operator==(N
); }
94 const_iterator
begin() const { return Edges
.begin(); }
95 const_iterator
end() const { return Edges
.end(); }
96 iterator
begin() { return Edges
.begin(); }
97 iterator
end() { return Edges
.end(); }
98 const EdgeType
&front() const { return *Edges
.front(); }
99 EdgeType
&front() { return *Edges
.front(); }
100 const EdgeType
&back() const { return *Edges
.back(); }
101 EdgeType
&back() { return *Edges
.back(); }
103 /// Collect in \p EL, all the edges from this node to \p N.
104 /// Return true if at least one edge was found, and false otherwise.
105 /// Note that this implementation allows more than one edge to connect
106 /// a given pair of nodes.
107 bool findEdgesTo(const NodeType
&N
, SmallVectorImpl
<EdgeType
*> &EL
) const {
108 assert(EL
.empty() && "Expected the list of edges to be empty.");
109 for (auto *E
: Edges
)
110 if (E
->getTargetNode() == N
)
115 /// Add the given edge \p E to this node, if it doesn't exist already. Returns
116 /// true if the edge is added and false otherwise.
117 bool addEdge(EdgeType
&E
) { return Edges
.insert(&E
); }
119 /// Remove the given edge \p E from this node, if it exists.
120 void removeEdge(EdgeType
&E
) { Edges
.remove(&E
); }
122 /// Test whether there is an edge that goes from this node to \p N.
123 bool hasEdgeTo(const NodeType
&N
) const {
124 return (findEdgeTo(N
) != Edges
.end());
127 /// Retrieve the outgoing edges for the node.
128 const EdgeListTy
&getEdges() const { return Edges
; }
129 EdgeListTy
&getEdges() {
130 return const_cast<EdgeListTy
&>(
131 static_cast<const DGNode
<NodeType
, EdgeType
> &>(*this).Edges
);
134 /// Clear the outgoing edges.
135 void clear() { Edges
.clear(); }
138 // As the default implementation use address comparison for equality.
139 bool isEqualTo(const NodeType
&N
) const { return this == &N
; }
141 // Cast the 'this' pointer to the derived type and return a reference.
142 NodeType
&getDerived() { return *static_cast<NodeType
*>(this); }
143 const NodeType
&getDerived() const {
144 return *static_cast<const NodeType
*>(this);
147 /// Find an edge to \p N. If more than one edge exists, this will return
148 /// the first one in the list of edges.
149 const_iterator
findEdgeTo(const NodeType
&N
) const {
150 return llvm::find_if(
151 Edges
, [&N
](const EdgeType
*E
) { return E
->getTargetNode() == N
; });
154 // The list of outgoing edges.
160 /// The graph is represented by a table of nodes.
161 /// Each node contains a (possibly empty) list of outgoing edges.
162 /// Each edge contains the target node it connects to.
163 template <class NodeType
, class EdgeType
> class DirectedGraph
{
165 using NodeListTy
= SmallVector
<NodeType
*, 10>;
166 using EdgeListTy
= SmallVector
<EdgeType
*, 10>;
168 using iterator
= typename
NodeListTy::iterator
;
169 using const_iterator
= typename
NodeListTy::const_iterator
;
170 using DGraphType
= DirectedGraph
<NodeType
, EdgeType
>;
172 DirectedGraph() = default;
173 explicit DirectedGraph(NodeType
&N
) : Nodes() { addNode(N
); }
174 DirectedGraph(const DGraphType
&G
) : Nodes(G
.Nodes
) {}
175 DirectedGraph(DGraphType
&&RHS
) : Nodes(std::move(RHS
.Nodes
)) {}
176 DGraphType
&operator=(const DGraphType
&G
) {
180 DGraphType
&operator=(const DGraphType
&&G
) {
181 Nodes
= std::move(G
.Nodes
);
185 const_iterator
begin() const { return Nodes
.begin(); }
186 const_iterator
end() const { return Nodes
.end(); }
187 iterator
begin() { return Nodes
.begin(); }
188 iterator
end() { return Nodes
.end(); }
189 const NodeType
&front() const { return *Nodes
.front(); }
190 NodeType
&front() { return *Nodes
.front(); }
191 const NodeType
&back() const { return *Nodes
.back(); }
192 NodeType
&back() { return *Nodes
.back(); }
194 size_t size() const { return Nodes
.size(); }
196 /// Find the given node \p N in the table.
197 const_iterator
findNode(const NodeType
&N
) const {
198 return llvm::find_if(Nodes
,
199 [&N
](const NodeType
*Node
) { return *Node
== N
; });
201 iterator
findNode(const NodeType
&N
) {
202 return const_cast<iterator
>(
203 static_cast<const DGraphType
&>(*this).findNode(N
));
206 /// Add the given node \p N to the graph if it is not already present.
207 bool addNode(NodeType
&N
) {
208 if (findNode(N
) != Nodes
.end())
214 /// Collect in \p EL all edges that are coming into node \p N. Return true
215 /// if at least one edge was found, and false otherwise.
216 bool findIncomingEdgesToNode(const NodeType
&N
, SmallVectorImpl
<EdgeType
*> &EL
) const {
217 assert(EL
.empty() && "Expected the list of edges to be empty.");
219 for (auto *Node
: Nodes
) {
222 Node
->findEdgesTo(N
, TempList
);
223 EL
.insert(EL
.end(), TempList
.begin(), TempList
.end());
229 /// Remove the given node \p N from the graph. If the node has incoming or
230 /// outgoing edges, they are also removed. Return true if the node was found
231 /// and then removed, and false if the node was not found in the graph to
233 bool removeNode(NodeType
&N
) {
234 iterator IT
= findNode(N
);
235 if (IT
== Nodes
.end())
237 // Remove incoming edges.
239 for (auto *Node
: Nodes
) {
242 Node
->findEdgesTo(N
, EL
);
244 Node
->removeEdge(*E
);
252 /// Assuming nodes \p Src and \p Dst are already in the graph, connect node \p
253 /// Src to node \p Dst using the provided edge \p E. Return true if \p Src is
254 /// not already connected to \p Dst via \p E, and false otherwise.
255 bool connect(NodeType
&Src
, NodeType
&Dst
, EdgeType
&E
) {
256 assert(findNode(Src
) != Nodes
.end() && "Src node should be present.");
257 assert(findNode(Dst
) != Nodes
.end() && "Dst node should be present.");
258 assert((E
.getTargetNode() == Dst
) &&
259 "Target of the given edge does not match Dst.");
260 return Src
.addEdge(E
);
264 // The list of nodes in the graph.
270 #endif // LLVM_ADT_DIRECTEDGRAPH_H