Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 14 | pmbaty | 1 | //===- llvm/ADT/DirectedGraph.h - Directed Graph ----------------*- C++ -*-===// |
| 2 | // |
||
| 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 |
||
| 6 | // |
||
| 7 | //===----------------------------------------------------------------------===// |
||
| 8 | /// |
||
| 9 | /// \file |
||
| 10 | /// This file defines the interface and a base class implementation for a |
||
| 11 | /// directed graph. |
||
| 12 | /// |
||
| 13 | //===----------------------------------------------------------------------===// |
||
| 14 | |||
| 15 | #ifndef LLVM_ADT_DIRECTEDGRAPH_H |
||
| 16 | #define LLVM_ADT_DIRECTEDGRAPH_H |
||
| 17 | |||
| 18 | #include "llvm/ADT/GraphTraits.h" |
||
| 19 | #include "llvm/ADT/SetVector.h" |
||
| 20 | #include "llvm/ADT/SmallVector.h" |
||
| 21 | #include "llvm/Support/Debug.h" |
||
| 22 | #include "llvm/Support/raw_ostream.h" |
||
| 23 | |||
| 24 | namespace llvm { |
||
| 25 | |||
| 26 | /// Represent an edge in the directed graph. |
||
| 27 | /// The edge contains the target node it connects to. |
||
| 28 | template <class NodeType, class EdgeType> class DGEdge { |
||
| 29 | public: |
||
| 30 | DGEdge() = delete; |
||
| 31 | /// Create an edge pointing to the given node \p N. |
||
| 32 | explicit DGEdge(NodeType &N) : TargetNode(N) {} |
||
| 33 | explicit DGEdge(const DGEdge<NodeType, EdgeType> &E) |
||
| 34 | : TargetNode(E.TargetNode) {} |
||
| 35 | DGEdge<NodeType, EdgeType> &operator=(const DGEdge<NodeType, EdgeType> &E) { |
||
| 36 | TargetNode = E.TargetNode; |
||
| 37 | return *this; |
||
| 38 | } |
||
| 39 | |||
| 40 | /// Static polymorphism: delegate implementation (via isEqualTo) to the |
||
| 41 | /// derived class. |
||
| 42 | bool operator==(const DGEdge &E) const { |
||
| 43 | return getDerived().isEqualTo(E.getDerived()); |
||
| 44 | } |
||
| 45 | bool operator!=(const DGEdge &E) const { return !operator==(E); } |
||
| 46 | |||
| 47 | /// Retrieve the target node this edge connects to. |
||
| 48 | const NodeType &getTargetNode() const { return TargetNode; } |
||
| 49 | NodeType &getTargetNode() { |
||
| 50 | return const_cast<NodeType &>( |
||
| 51 | static_cast<const DGEdge<NodeType, EdgeType> &>(*this).getTargetNode()); |
||
| 52 | } |
||
| 53 | |||
| 54 | /// Set the target node this edge connects to. |
||
| 55 | void setTargetNode(const NodeType &N) { TargetNode = N; } |
||
| 56 | |||
| 57 | protected: |
||
| 58 | // As the default implementation use address comparison for equality. |
||
| 59 | bool isEqualTo(const EdgeType &E) const { return this == &E; } |
||
| 60 | |||
| 61 | // Cast the 'this' pointer to the derived type and return a reference. |
||
| 62 | EdgeType &getDerived() { return *static_cast<EdgeType *>(this); } |
||
| 63 | const EdgeType &getDerived() const { |
||
| 64 | return *static_cast<const EdgeType *>(this); |
||
| 65 | } |
||
| 66 | |||
| 67 | // The target node this edge connects to. |
||
| 68 | NodeType &TargetNode; |
||
| 69 | }; |
||
| 70 | |||
| 71 | /// Represent a node in the directed graph. |
||
| 72 | /// The node has a (possibly empty) list of outgoing edges. |
||
| 73 | template <class NodeType, class EdgeType> class DGNode { |
||
| 74 | public: |
||
| 75 | using EdgeListTy = SetVector<EdgeType *>; |
||
| 76 | using iterator = typename EdgeListTy::iterator; |
||
| 77 | using const_iterator = typename EdgeListTy::const_iterator; |
||
| 78 | |||
| 79 | /// Create a node with a single outgoing edge \p E. |
||
| 80 | explicit DGNode(EdgeType &E) : Edges() { Edges.insert(&E); } |
||
| 81 | DGNode() = default; |
||
| 82 | |||
| 83 | explicit DGNode(const DGNode<NodeType, EdgeType> &N) : Edges(N.Edges) {} |
||
| 84 | DGNode(DGNode<NodeType, EdgeType> &&N) : Edges(std::move(N.Edges)) {} |
||
| 85 | |||
| 86 | DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &N) { |
||
| 87 | Edges = N.Edges; |
||
| 88 | return *this; |
||
| 89 | } |
||
| 90 | DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &&N) { |
||
| 91 | Edges = std::move(N.Edges); |
||
| 92 | return *this; |
||
| 93 | } |
||
| 94 | |||
| 95 | /// Static polymorphism: delegate implementation (via isEqualTo) to the |
||
| 96 | /// derived class. |
||
| 97 | friend bool operator==(const NodeType &M, const NodeType &N) { |
||
| 98 | return M.isEqualTo(N); |
||
| 99 | } |
||
| 100 | friend bool operator!=(const NodeType &M, const NodeType &N) { |
||
| 101 | return !(M == N); |
||
| 102 | } |
||
| 103 | |||
| 104 | const_iterator begin() const { return Edges.begin(); } |
||
| 105 | const_iterator end() const { return Edges.end(); } |
||
| 106 | iterator begin() { return Edges.begin(); } |
||
| 107 | iterator end() { return Edges.end(); } |
||
| 108 | const EdgeType &front() const { return *Edges.front(); } |
||
| 109 | EdgeType &front() { return *Edges.front(); } |
||
| 110 | const EdgeType &back() const { return *Edges.back(); } |
||
| 111 | EdgeType &back() { return *Edges.back(); } |
||
| 112 | |||
| 113 | /// Collect in \p EL, all the edges from this node to \p N. |
||
| 114 | /// Return true if at least one edge was found, and false otherwise. |
||
| 115 | /// Note that this implementation allows more than one edge to connect |
||
| 116 | /// a given pair of nodes. |
||
| 117 | bool findEdgesTo(const NodeType &N, SmallVectorImpl<EdgeType *> &EL) const { |
||
| 118 | assert(EL.empty() && "Expected the list of edges to be empty."); |
||
| 119 | for (auto *E : Edges) |
||
| 120 | if (E->getTargetNode() == N) |
||
| 121 | EL.push_back(E); |
||
| 122 | return !EL.empty(); |
||
| 123 | } |
||
| 124 | |||
| 125 | /// Add the given edge \p E to this node, if it doesn't exist already. Returns |
||
| 126 | /// true if the edge is added and false otherwise. |
||
| 127 | bool addEdge(EdgeType &E) { return Edges.insert(&E); } |
||
| 128 | |||
| 129 | /// Remove the given edge \p E from this node, if it exists. |
||
| 130 | void removeEdge(EdgeType &E) { Edges.remove(&E); } |
||
| 131 | |||
| 132 | /// Test whether there is an edge that goes from this node to \p N. |
||
| 133 | bool hasEdgeTo(const NodeType &N) const { |
||
| 134 | return (findEdgeTo(N) != Edges.end()); |
||
| 135 | } |
||
| 136 | |||
| 137 | /// Retrieve the outgoing edges for the node. |
||
| 138 | const EdgeListTy &getEdges() const { return Edges; } |
||
| 139 | EdgeListTy &getEdges() { |
||
| 140 | return const_cast<EdgeListTy &>( |
||
| 141 | static_cast<const DGNode<NodeType, EdgeType> &>(*this).Edges); |
||
| 142 | } |
||
| 143 | |||
| 144 | /// Clear the outgoing edges. |
||
| 145 | void clear() { Edges.clear(); } |
||
| 146 | |||
| 147 | protected: |
||
| 148 | // As the default implementation use address comparison for equality. |
||
| 149 | bool isEqualTo(const NodeType &N) const { return this == &N; } |
||
| 150 | |||
| 151 | // Cast the 'this' pointer to the derived type and return a reference. |
||
| 152 | NodeType &getDerived() { return *static_cast<NodeType *>(this); } |
||
| 153 | const NodeType &getDerived() const { |
||
| 154 | return *static_cast<const NodeType *>(this); |
||
| 155 | } |
||
| 156 | |||
| 157 | /// Find an edge to \p N. If more than one edge exists, this will return |
||
| 158 | /// the first one in the list of edges. |
||
| 159 | const_iterator findEdgeTo(const NodeType &N) const { |
||
| 160 | return llvm::find_if( |
||
| 161 | Edges, [&N](const EdgeType *E) { return E->getTargetNode() == N; }); |
||
| 162 | } |
||
| 163 | |||
| 164 | // The list of outgoing edges. |
||
| 165 | EdgeListTy Edges; |
||
| 166 | }; |
||
| 167 | |||
| 168 | /// Directed graph |
||
| 169 | /// |
||
| 170 | /// The graph is represented by a table of nodes. |
||
| 171 | /// Each node contains a (possibly empty) list of outgoing edges. |
||
| 172 | /// Each edge contains the target node it connects to. |
||
| 173 | template <class NodeType, class EdgeType> class DirectedGraph { |
||
| 174 | protected: |
||
| 175 | using NodeListTy = SmallVector<NodeType *, 10>; |
||
| 176 | using EdgeListTy = SmallVector<EdgeType *, 10>; |
||
| 177 | public: |
||
| 178 | using iterator = typename NodeListTy::iterator; |
||
| 179 | using const_iterator = typename NodeListTy::const_iterator; |
||
| 180 | using DGraphType = DirectedGraph<NodeType, EdgeType>; |
||
| 181 | |||
| 182 | DirectedGraph() = default; |
||
| 183 | explicit DirectedGraph(NodeType &N) : Nodes() { addNode(N); } |
||
| 184 | DirectedGraph(const DGraphType &G) : Nodes(G.Nodes) {} |
||
| 185 | DirectedGraph(DGraphType &&RHS) : Nodes(std::move(RHS.Nodes)) {} |
||
| 186 | DGraphType &operator=(const DGraphType &G) { |
||
| 187 | Nodes = G.Nodes; |
||
| 188 | return *this; |
||
| 189 | } |
||
| 190 | DGraphType &operator=(const DGraphType &&G) { |
||
| 191 | Nodes = std::move(G.Nodes); |
||
| 192 | return *this; |
||
| 193 | } |
||
| 194 | |||
| 195 | const_iterator begin() const { return Nodes.begin(); } |
||
| 196 | const_iterator end() const { return Nodes.end(); } |
||
| 197 | iterator begin() { return Nodes.begin(); } |
||
| 198 | iterator end() { return Nodes.end(); } |
||
| 199 | const NodeType &front() const { return *Nodes.front(); } |
||
| 200 | NodeType &front() { return *Nodes.front(); } |
||
| 201 | const NodeType &back() const { return *Nodes.back(); } |
||
| 202 | NodeType &back() { return *Nodes.back(); } |
||
| 203 | |||
| 204 | size_t size() const { return Nodes.size(); } |
||
| 205 | |||
| 206 | /// Find the given node \p N in the table. |
||
| 207 | const_iterator findNode(const NodeType &N) const { |
||
| 208 | return llvm::find_if(Nodes, |
||
| 209 | [&N](const NodeType *Node) { return *Node == N; }); |
||
| 210 | } |
||
| 211 | iterator findNode(const NodeType &N) { |
||
| 212 | return const_cast<iterator>( |
||
| 213 | static_cast<const DGraphType &>(*this).findNode(N)); |
||
| 214 | } |
||
| 215 | |||
| 216 | /// Add the given node \p N to the graph if it is not already present. |
||
| 217 | bool addNode(NodeType &N) { |
||
| 218 | if (findNode(N) != Nodes.end()) |
||
| 219 | return false; |
||
| 220 | Nodes.push_back(&N); |
||
| 221 | return true; |
||
| 222 | } |
||
| 223 | |||
| 224 | /// Collect in \p EL all edges that are coming into node \p N. Return true |
||
| 225 | /// if at least one edge was found, and false otherwise. |
||
| 226 | bool findIncomingEdgesToNode(const NodeType &N, SmallVectorImpl<EdgeType*> &EL) const { |
||
| 227 | assert(EL.empty() && "Expected the list of edges to be empty."); |
||
| 228 | EdgeListTy TempList; |
||
| 229 | for (auto *Node : Nodes) { |
||
| 230 | if (*Node == N) |
||
| 231 | continue; |
||
| 232 | Node->findEdgesTo(N, TempList); |
||
| 233 | llvm::append_range(EL, TempList); |
||
| 234 | TempList.clear(); |
||
| 235 | } |
||
| 236 | return !EL.empty(); |
||
| 237 | } |
||
| 238 | |||
| 239 | /// Remove the given node \p N from the graph. If the node has incoming or |
||
| 240 | /// outgoing edges, they are also removed. Return true if the node was found |
||
| 241 | /// and then removed, and false if the node was not found in the graph to |
||
| 242 | /// begin with. |
||
| 243 | bool removeNode(NodeType &N) { |
||
| 244 | iterator IT = findNode(N); |
||
| 245 | if (IT == Nodes.end()) |
||
| 246 | return false; |
||
| 247 | // Remove incoming edges. |
||
| 248 | EdgeListTy EL; |
||
| 249 | for (auto *Node : Nodes) { |
||
| 250 | if (*Node == N) |
||
| 251 | continue; |
||
| 252 | Node->findEdgesTo(N, EL); |
||
| 253 | for (auto *E : EL) |
||
| 254 | Node->removeEdge(*E); |
||
| 255 | EL.clear(); |
||
| 256 | } |
||
| 257 | N.clear(); |
||
| 258 | Nodes.erase(IT); |
||
| 259 | return true; |
||
| 260 | } |
||
| 261 | |||
| 262 | /// Assuming nodes \p Src and \p Dst are already in the graph, connect node \p |
||
| 263 | /// Src to node \p Dst using the provided edge \p E. Return true if \p Src is |
||
| 264 | /// not already connected to \p Dst via \p E, and false otherwise. |
||
| 265 | bool connect(NodeType &Src, NodeType &Dst, EdgeType &E) { |
||
| 266 | assert(findNode(Src) != Nodes.end() && "Src node should be present."); |
||
| 267 | assert(findNode(Dst) != Nodes.end() && "Dst node should be present."); |
||
| 268 | assert((E.getTargetNode() == Dst) && |
||
| 269 | "Target of the given edge does not match Dst."); |
||
| 270 | return Src.addEdge(E); |
||
| 271 | } |
||
| 272 | |||
| 273 | protected: |
||
| 274 | // The list of nodes in the graph. |
||
| 275 | NodeListTy Nodes; |
||
| 276 | }; |
||
| 277 | |||
| 278 | } // namespace llvm |
||
| 279 | |||
| 280 | #endif // LLVM_ADT_DIRECTEDGRAPH_H |