Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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
  281.