123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|