Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

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