| //===- llvm/ADT/DirectedGraph.h - Directed Graph ----------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// This file defines the interface and a base class implementation for a |
| /// directed graph. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_ADT_DIRECTEDGRAPH_H |
| #define LLVM_ADT_DIRECTEDGRAPH_H |
| |
| #include "llvm/ADT/GraphTraits.h" |
| #include "llvm/ADT/SetVector.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/Support/Debug.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| namespace llvm { |
| |
| /// Represent an edge in the directed graph. |
| /// The edge contains the target node it connects to. |
| template <class NodeType, class EdgeType> class DGEdge { |
| public: |
| DGEdge() = delete; |
| /// Create an edge pointing to the given node \p N. |
| explicit DGEdge(NodeType &N) : TargetNode(N) {} |
| explicit DGEdge(const DGEdge<NodeType, EdgeType> &E) |
| : TargetNode(E.TargetNode) {} |
| DGEdge<NodeType, EdgeType> &operator=(const DGEdge<NodeType, EdgeType> &E) { |
| TargetNode = E.TargetNode; |
| return *this; |
| } |
| |
| /// Static polymorphism: delegate implementation (via isEqualTo) to the |
| /// derived class. |
| bool operator==(const DGEdge &E) const { |
| return getDerived().isEqualTo(E.getDerived()); |
| } |
| bool operator!=(const DGEdge &E) const { return !operator==(E); } |
| |
| /// Retrieve the target node this edge connects to. |
| const NodeType &getTargetNode() const { return TargetNode; } |
| NodeType &getTargetNode() { |
| return const_cast<NodeType &>( |
| static_cast<const DGEdge<NodeType, EdgeType> &>(*this).getTargetNode()); |
| } |
| |
| /// Set the target node this edge connects to. |
| void setTargetNode(const NodeType &N) { TargetNode = N; } |
| |
| protected: |
| // As the default implementation use address comparison for equality. |
| bool isEqualTo(const EdgeType &E) const { return this == &E; } |
| |
| // Cast the 'this' pointer to the derived type and return a reference. |
| EdgeType &getDerived() { return *static_cast<EdgeType *>(this); } |
| const EdgeType &getDerived() const { |
| return *static_cast<const EdgeType *>(this); |
| } |
| |
| // The target node this edge connects to. |
| NodeType &TargetNode; |
| }; |
| |
| /// Represent a node in the directed graph. |
| /// The node has a (possibly empty) list of outgoing edges. |
| template <class NodeType, class EdgeType> class DGNode { |
| public: |
| using EdgeListTy = SetVector<EdgeType *>; |
| using iterator = typename EdgeListTy::iterator; |
| using const_iterator = typename EdgeListTy::const_iterator; |
| |
| /// Create a node with a single outgoing edge \p E. |
| explicit DGNode(EdgeType &E) : Edges() { Edges.insert(&E); } |
| DGNode() = default; |
| |
| explicit DGNode(const DGNode<NodeType, EdgeType> &N) : Edges(N.Edges) {} |
| DGNode(DGNode<NodeType, EdgeType> &&N) : Edges(std::move(N.Edges)) {} |
| |
| DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &N) { |
| Edges = N.Edges; |
| return *this; |
| } |
| DGNode<NodeType, EdgeType> &operator=(const DGNode<NodeType, EdgeType> &&N) { |
| Edges = std::move(N.Edges); |
| return *this; |
| } |
| |
| /// Static polymorphism: delegate implementation (via isEqualTo) to the |
| /// derived class. |
| friend bool operator==(const NodeType &M, const NodeType &N) { |
| return M.isEqualTo(N); |
| } |
| friend bool operator!=(const NodeType &M, const NodeType &N) { |
| return !(M == N); |
| } |
| |
| const_iterator begin() const { return Edges.begin(); } |
| const_iterator end() const { return Edges.end(); } |
| iterator begin() { return Edges.begin(); } |
| iterator end() { return Edges.end(); } |
| const EdgeType &front() const { return *Edges.front(); } |
| EdgeType &front() { return *Edges.front(); } |
| const EdgeType &back() const { return *Edges.back(); } |
| EdgeType &back() { return *Edges.back(); } |
| |
| /// Collect in \p EL, all the edges from this node to \p N. |
| /// Return true if at least one edge was found, and false otherwise. |
| /// Note that this implementation allows more than one edge to connect |
| /// a given pair of nodes. |
| bool findEdgesTo(const NodeType &N, SmallVectorImpl<EdgeType *> &EL) const { |
| assert(EL.empty() && "Expected the list of edges to be empty."); |
| for (auto *E : Edges) |
| if (E->getTargetNode() == N) |
| EL.push_back(E); |
| return !EL.empty(); |
| } |
| |
| /// Add the given edge \p E to this node, if it doesn't exist already. Returns |
| /// true if the edge is added and false otherwise. |
| bool addEdge(EdgeType &E) { return Edges.insert(&E); } |
| |
| /// Remove the given edge \p E from this node, if it exists. |
| void removeEdge(EdgeType &E) { Edges.remove(&E); } |
| |
| /// Test whether there is an edge that goes from this node to \p N. |
| bool hasEdgeTo(const NodeType &N) const { |
| return (findEdgeTo(N) != Edges.end()); |
| } |
| |
| /// Retrieve the outgoing edges for the node. |
| const EdgeListTy &getEdges() const { return Edges; } |
| EdgeListTy &getEdges() { |
| return const_cast<EdgeListTy &>( |
| static_cast<const DGNode<NodeType, EdgeType> &>(*this).Edges); |
| } |
| |
| /// Clear the outgoing edges. |
| void clear() { Edges.clear(); } |
| |
| protected: |
| // As the default implementation use address comparison for equality. |
| bool isEqualTo(const NodeType &N) const { return this == &N; } |
| |
| // Cast the 'this' pointer to the derived type and return a reference. |
| NodeType &getDerived() { return *static_cast<NodeType *>(this); } |
| const NodeType &getDerived() const { |
| return *static_cast<const NodeType *>(this); |
| } |
| |
| /// Find an edge to \p N. If more than one edge exists, this will return |
| /// the first one in the list of edges. |
| const_iterator findEdgeTo(const NodeType &N) const { |
| return llvm::find_if( |
| Edges, [&N](const EdgeType *E) { return E->getTargetNode() == N; }); |
| } |
| |
| // The list of outgoing edges. |
| EdgeListTy Edges; |
| }; |
| |
| /// Directed graph |
| /// |
| /// The graph is represented by a table of nodes. |
| /// Each node contains a (possibly empty) list of outgoing edges. |
| /// Each edge contains the target node it connects to. |
| template <class NodeType, class EdgeType> class DirectedGraph { |
| protected: |
| using NodeListTy = SmallVector<NodeType *, 10>; |
| using EdgeListTy = SmallVector<EdgeType *, 10>; |
| public: |
| using iterator = typename NodeListTy::iterator; |
| using const_iterator = typename NodeListTy::const_iterator; |
| using DGraphType = DirectedGraph<NodeType, EdgeType>; |
| |
| DirectedGraph() = default; |
| explicit DirectedGraph(NodeType &N) : Nodes() { addNode(N); } |
| DirectedGraph(const DGraphType &G) : Nodes(G.Nodes) {} |
| DirectedGraph(DGraphType &&RHS) : Nodes(std::move(RHS.Nodes)) {} |
| DGraphType &operator=(const DGraphType &G) { |
| Nodes = G.Nodes; |
| return *this; |
| } |
| DGraphType &operator=(const DGraphType &&G) { |
| Nodes = std::move(G.Nodes); |
| return *this; |
| } |
| |
| const_iterator begin() const { return Nodes.begin(); } |
| const_iterator end() const { return Nodes.end(); } |
| iterator begin() { return Nodes.begin(); } |
| iterator end() { return Nodes.end(); } |
| const NodeType &front() const { return *Nodes.front(); } |
| NodeType &front() { return *Nodes.front(); } |
| const NodeType &back() const { return *Nodes.back(); } |
| NodeType &back() { return *Nodes.back(); } |
| |
| size_t size() const { return Nodes.size(); } |
| |
| /// Find the given node \p N in the table. |
| const_iterator findNode(const NodeType &N) const { |
| return llvm::find_if(Nodes, |
| [&N](const NodeType *Node) { return *Node == N; }); |
| } |
| iterator findNode(const NodeType &N) { |
| return const_cast<iterator>( |
| static_cast<const DGraphType &>(*this).findNode(N)); |
| } |
| |
| /// Add the given node \p N to the graph if it is not already present. |
| bool addNode(NodeType &N) { |
| if (findNode(N) != Nodes.end()) |
| return false; |
| Nodes.push_back(&N); |
| return true; |
| } |
| |
| /// Collect in \p EL all edges that are coming into node \p N. Return true |
| /// if at least one edge was found, and false otherwise. |
| bool findIncomingEdgesToNode(const NodeType &N, SmallVectorImpl<EdgeType*> &EL) const { |
| assert(EL.empty() && "Expected the list of edges to be empty."); |
| EdgeListTy TempList; |
| for (auto *Node : Nodes) { |
| if (*Node == N) |
| continue; |
| Node->findEdgesTo(N, TempList); |
| llvm::append_range(EL, TempList); |
| TempList.clear(); |
| } |
| return !EL.empty(); |
| } |
| |
| /// Remove the given node \p N from the graph. If the node has incoming or |
| /// outgoing edges, they are also removed. Return true if the node was found |
| /// and then removed, and false if the node was not found in the graph to |
| /// begin with. |
| bool removeNode(NodeType &N) { |
| iterator IT = findNode(N); |
| if (IT == Nodes.end()) |
| return false; |
| // Remove incoming edges. |
| EdgeListTy EL; |
| for (auto *Node : Nodes) { |
| if (*Node == N) |
| continue; |
| Node->findEdgesTo(N, EL); |
| for (auto *E : EL) |
| Node->removeEdge(*E); |
| EL.clear(); |
| } |
| N.clear(); |
| Nodes.erase(IT); |
| return true; |
| } |
| |
| /// Assuming nodes \p Src and \p Dst are already in the graph, connect node \p |
| /// Src to node \p Dst using the provided edge \p E. Return true if \p Src is |
| /// not already connected to \p Dst via \p E, and false otherwise. |
| bool connect(NodeType &Src, NodeType &Dst, EdgeType &E) { |
| assert(findNode(Src) != Nodes.end() && "Src node should be present."); |
| assert(findNode(Dst) != Nodes.end() && "Dst node should be present."); |
| assert((E.getTargetNode() == Dst) && |
| "Target of the given edge does not match Dst."); |
| return Src.addEdge(E); |
| } |
| |
| protected: |
| // The list of nodes in the graph. |
| NodeListTy Nodes; |
| }; |
| |
| } // namespace llvm |
| |
| #endif // LLVM_ADT_DIRECTEDGRAPH_H |