LLVM 22.0.0git
Graph.h
Go to the documentation of this file.
1//===-- Graph.h - XRay Graph Class ------------------------------*- 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// A Graph Datatype for XRay.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_XRAY_GRAPH_H
14#define LLVM_XRAY_GRAPH_H
15
16#include <initializer_list>
17#include <stdint.h>
18#include <type_traits>
19#include <utility>
20
21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/DenseSet.h"
23#include "llvm/ADT/iterator.h"
24#include "llvm/Support/Error.h"
25
26namespace llvm::xray {
27
28/// A Graph object represents a Directed Graph and is used in XRay to compute
29/// and store function call graphs and associated statistical information.
30///
31/// The graph takes in four template parameters, these are:
32/// - VertexAttribute, this is a structure which is stored for each vertex.
33/// Must be DefaultConstructible, CopyConstructible, CopyAssignable and
34/// Destructible.
35/// - EdgeAttribute, this is a structure which is stored for each edge
36/// Must be DefaultConstructible, CopyConstructible, CopyAssignable and
37/// Destructible.
38/// - EdgeAttribute, this is a structure which is stored for each variable
39/// - VI, this is a type over which DenseMapInfo is defined and is the type
40/// used look up strings, available as VertexIdentifier.
41/// - If the built in DenseMapInfo is not defined, provide a specialization
42/// class type here.
43///
44/// Graph is CopyConstructible, CopyAssignable, MoveConstructible and
45/// MoveAssignable but is not EqualityComparible or LessThanComparible.
46///
47/// Usage Example Graph with weighted edges and vertices:
48/// Graph<int, int, int> G;
49///
50/// G[1] = 0;
51/// G[2] = 2;
52/// G[{1,2}] = 1;
53/// G[{2,1}] = -1;
54/// for(const auto &v : G.vertices()){
55/// // Do something with the vertices in the graph;
56/// }
57/// for(const auto &e : G.edges()){
58/// // Do something with the edges in the graph;
59/// }
60///
61/// Usage Example with StrRef keys.
62/// Graph<int, double, StrRef> StrG;
63/// char va[] = "Vertex A";
64/// char vaa[] = "Vertex A";
65/// char vb[] = "Vertex B"; // Vertices are referenced by String Refs.
66/// G[va] = 0;
67/// G[vb] = 1;
68/// G[{va, vb}] = 1.0;
69/// cout() << G[vaa] << " " << G[{vaa, vb}]; //prints "0 1.0".
70///
71template <typename VertexAttribute, typename EdgeAttribute,
72 typename VI = int32_t>
73class Graph {
74public:
75 /// These objects are used to name edges and vertices in the graph.
76 typedef VI VertexIdentifier;
77 typedef std::pair<VI, VI> EdgeIdentifier;
78
79 /// This type is the value_type of all iterators which range over vertices,
80 /// Determined by the Vertices DenseMap
83
84 /// This type is the value_type of all iterators which range over edges,
85 /// Determined by the Edges DenseMap.
87
88 using size_type = std::size_t;
89
90private:
91 /// The type used for storing the EdgeAttribute for each edge in the graph
93
94 /// The type used for storing the VertexAttribute for each vertex in
95 /// the graph.
97
98 /// The type used for storing the edges entering a vertex. Indexed by
99 /// the VertexIdentifier of the start of the edge. Only used to determine
100 /// where the incoming edges are, the EdgeIdentifiers are stored in an
101 /// InnerEdgeMapT.
102 using NeighborSetT = DenseSet<VertexIdentifier>;
103
104 /// The type storing the InnerInvGraphT corresponding to each vertex in
105 /// the graph (When a vertex has an incoming edge incident to it)
106 using NeighborLookupT = DenseMap<VertexIdentifier, NeighborSetT>;
107
108private:
109 /// Stores the map from the start and end vertex of an edge to it's
110 /// EdgeAttribute
111 EdgeMapT Edges;
112
113 /// Stores the map from VertexIdentifier to VertexAttribute
114 VertexMapT Vertices;
115
116 /// Allows fast lookup for the incoming edge set of any given vertex.
117 NeighborLookupT InNeighbors;
118
119 /// Allows fast lookup for the outgoing edge set of any given vertex.
120 NeighborLookupT OutNeighbors;
121
122 /// An Iterator adapter using an InnerInvGraphT::iterator as a base iterator,
123 /// and storing the VertexIdentifier the iterator range comes from. The
124 /// dereference operator is then performed using a pointer to the graph's edge
125 /// set.
126 template <bool IsConst, bool IsOut,
127 typename BaseIt = typename NeighborSetT::const_iterator,
128 typename T =
129 std::conditional_t<IsConst, const EdgeValueType, EdgeValueType>>
130 class NeighborEdgeIteratorT
131 : public iterator_adaptor_base<
132 NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
133 typename std::iterator_traits<BaseIt>::iterator_category, T> {
134 using InternalEdgeMapT =
135 std::conditional_t<IsConst, const EdgeMapT, EdgeMapT>;
136
137 friend class NeighborEdgeIteratorT<false, IsOut, BaseIt, EdgeValueType>;
138 friend class NeighborEdgeIteratorT<true, IsOut, BaseIt,
140
141 InternalEdgeMapT *MP;
143
144 public:
145 template <bool IsConstDest,
146 typename = std::enable_if_t<IsConstDest && !IsConst>>
147 operator NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
148 const EdgeValueType>() const {
149 return NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
150 const EdgeValueType>(this->I, MP, SI);
151 }
152
153 NeighborEdgeIteratorT() = default;
154 NeighborEdgeIteratorT(BaseIt _I, InternalEdgeMapT *_MP,
157 NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
158 typename std::iterator_traits<BaseIt>::iterator_category, T>(_I),
159 MP(_MP), SI(_SI) {}
160
161 T &operator*() const {
162 if (!IsOut)
163 return *(MP->find({*(this->I), SI}));
164 else
165 return *(MP->find({SI, *(this->I)}));
166 }
167 };
168
169public:
170 /// A const iterator type for iterating through the set of edges entering a
171 /// vertex.
172 ///
173 /// Has a const EdgeValueType as its value_type
174 using ConstInEdgeIterator = NeighborEdgeIteratorT<true, false>;
175
176 /// An iterator type for iterating through the set of edges leaving a vertex.
177 ///
178 /// Has an EdgeValueType as its value_type
179 using InEdgeIterator = NeighborEdgeIteratorT<false, false>;
180
181 /// A const iterator type for iterating through the set of edges entering a
182 /// vertex.
183 ///
184 /// Has a const EdgeValueType as its value_type
185 using ConstOutEdgeIterator = NeighborEdgeIteratorT<true, true>;
186
187 /// An iterator type for iterating through the set of edges leaving a vertex.
188 ///
189 /// Has an EdgeValueType as its value_type
190 using OutEdgeIterator = NeighborEdgeIteratorT<false, true>;
191
192 /// A class for ranging over the incoming edges incident to a vertex.
193 ///
194 /// Like all views in this class it provides methods to get the beginning and
195 /// past the range iterators for the range, as well as methods to determine
196 /// the number of elements in the range and whether the range is empty.
197 template <bool isConst, bool isOut> class InOutEdgeView {
198 public:
199 using iterator = NeighborEdgeIteratorT<isConst, isOut>;
200 using const_iterator = NeighborEdgeIteratorT<true, isOut>;
201 using GraphT = std::conditional_t<isConst, const Graph, Graph>;
203 std::conditional_t<isConst, const EdgeMapT, EdgeMapT>;
204
205 private:
207 const VertexIdentifier A;
208 const NeighborLookupT &NL;
209
210 public:
212 auto It = NL.find(A);
213 if (It == NL.end())
214 return iterator();
215 return iterator(It->second.begin(), &M, A);
216 }
217
219 auto It = NL.find(A);
220 if (It == NL.end())
221 return const_iterator();
222 return const_iterator(It->second.begin(), &M, A);
223 }
224
225 const_iterator begin() const { return cbegin(); }
226
228 auto It = NL.find(A);
229 if (It == NL.end())
230 return iterator();
231 return iterator(It->second.end(), &M, A);
232 }
234 auto It = NL.find(A);
235 if (It == NL.end())
236 return const_iterator();
237 return const_iterator(It->second.end(), &M, A);
238 }
239
240 const_iterator end() const { return cend(); }
241
242 size_type size() const {
243 auto I = NL.find(A);
244 if (I == NL.end())
245 return 0;
246 else
247 return I->second.size();
248 }
249
250 bool empty() const { return NL.count(A) == 0; };
251
253 : M(G.Edges), A(A), NL(isOut ? G.OutNeighbors : G.InNeighbors) {}
254 };
255
256 /// A const iterator type for iterating through the whole vertex set of the
257 /// graph.
258 ///
259 /// Has a const VertexValueType as its value_type
261
262 /// An iterator type for iterating through the whole vertex set of the graph.
263 ///
264 /// Has a VertexValueType as its value_type
266
267 /// A class for ranging over the vertices in the graph.
268 ///
269 /// Like all views in this class it provides methods to get the beginning and
270 /// past the range iterators for the range, as well as methods to determine
271 /// the number of elements in the range and whether the range is empty.
272 template <bool isConst> class VertexView {
273 public:
274 using iterator =
275 std::conditional_t<isConst, ConstVertexIterator, VertexIterator>;
277 using GraphT = std::conditional_t<isConst, const Graph, Graph>;
278
279 private:
280 GraphT &G;
281
282 public:
283 iterator begin() { return G.Vertices.begin(); }
284 iterator end() { return G.Vertices.end(); }
285 const_iterator cbegin() const { return G.Vertices.cbegin(); }
286 const_iterator cend() const { return G.Vertices.cend(); }
287 const_iterator begin() const { return G.Vertices.begin(); }
288 const_iterator end() const { return G.Vertices.end(); }
289 size_type size() const { return G.Vertices.size(); }
290 bool empty() const { return G.Vertices.empty(); }
291 VertexView(GraphT &_G) : G(_G) {}
292 };
293
294 /// A const iterator for iterating through the entire edge set of the graph.
295 ///
296 /// Has a const EdgeValueType as its value_type
298
299 /// An iterator for iterating through the entire edge set of the graph.
300 ///
301 /// Has an EdgeValueType as its value_type
303
304 /// A class for ranging over all the edges in the graph.
305 ///
306 /// Like all views in this class it provides methods to get the beginning and
307 /// past the range iterators for the range, as well as methods to determine
308 /// the number of elements in the range and whether the range is empty.
309 template <bool isConst> class EdgeView {
310 public:
311 using iterator =
312 std::conditional_t<isConst, ConstEdgeIterator, EdgeIterator>;
314 using GraphT = std::conditional_t<isConst, const Graph, Graph>;
315
316 private:
317 GraphT &G;
318
319 public:
320 iterator begin() { return G.Edges.begin(); }
321 iterator end() { return G.Edges.end(); }
322 const_iterator cbegin() const { return G.Edges.cbegin(); }
323 const_iterator cend() const { return G.Edges.cend(); }
324 const_iterator begin() const { return G.Edges.begin(); }
325 const_iterator end() const { return G.Edges.end(); }
326 size_type size() const { return G.Edges.size(); }
327 bool empty() const { return G.Edges.empty(); }
328 EdgeView(GraphT &_G) : G(_G) {}
329 };
330
331public:
332 // TODO: implement constructor to enable Graph Initialisation.\
333 // Something like:
334 // Graph<int, int, int> G(
335 // {1, 2, 3, 4, 5},
336 // {{1, 2}, {2, 3}, {3, 4}});
337
338 /// Empty the Graph
339 void clear() {
340 Edges.clear();
341 Vertices.clear();
342 InNeighbors.clear();
343 OutNeighbors.clear();
344 }
345
346 /// Returns a view object allowing iteration over the vertices of the graph.
347 /// also allows access to the size of the vertex set.
349
350 VertexView<true> vertices() const { return VertexView<true>(*this); }
351
352 /// Returns a view object allowing iteration over the edges of the graph.
353 /// also allows access to the size of the edge set.
355
356 EdgeView<true> edges() const { return EdgeView<true>(*this); }
357
358 /// Returns a view object allowing iteration over the edges which start at
359 /// a vertex I.
363
367
368 /// Returns a view object allowing iteration over the edges which point to
369 /// a vertex I.
373
377
378 /// Looks up the vertex with identifier I, if it does not exist it default
379 /// constructs it.
380 VertexAttribute &operator[](const VertexIdentifier &I) { return Vertices[I]; }
381
382 /// Looks up the edge with identifier I, if it does not exist it default
383 /// constructs it, if it's endpoints do not exist it also default constructs
384 /// them.
385 EdgeAttribute &operator[](const EdgeIdentifier &I) {
386 Vertices.try_emplace(I.first);
387 Vertices.try_emplace(I.second);
388 InNeighbors[I.second].insert(I.first);
389 OutNeighbors[I.first].insert(I.second);
390 return Edges[I];
391 }
392
393 /// Looks up a vertex with Identifier I, or an error if it does not exist.
395 auto It = Vertices.find(I);
396 if (It == Vertices.end())
398 "Vertex Identifier Does Not Exist",
399 std::make_error_code(std::errc::invalid_argument));
400 return It->second;
401 }
402
404 auto It = Vertices.find(I);
405 if (It == Vertices.end())
407 "Vertex Identifier Does Not Exist",
408 std::make_error_code(std::errc::invalid_argument));
409 return It->second;
410 }
411
412 /// Looks up an edge with Identifier I, or an error if it does not exist.
414 auto It = Edges.find(I);
415 if (It == Edges.end())
417 "Edge Identifier Does Not Exist",
418 std::make_error_code(std::errc::invalid_argument));
419 return It->second;
420 }
421
423 auto It = Edges.find(I);
424 if (It == Edges.end())
426 "Edge Identifier Does Not Exist",
427 std::make_error_code(std::errc::invalid_argument));
428 return It->second;
429 }
430
431 /// Looks for a vertex with identifier I, returns 1 if one exists, and
432 /// 0 otherwise
434 return Vertices.count(I);
435 }
436
437 /// Looks for an edge with Identifier I, returns 1 if one exists and 0
438 /// otherwise
439 size_type count(const EdgeIdentifier &I) const { return Edges.count(I); }
440
441 /// Inserts a vertex into the graph with Identifier Val.first, and
442 /// Attribute Val.second.
443 std::pair<VertexIterator, bool>
444 insert(const std::pair<VertexIdentifier, VertexAttribute> &Val) {
445 return Vertices.insert(Val);
446 }
447
448 std::pair<VertexIterator, bool>
449 insert(std::pair<VertexIdentifier, VertexAttribute> &&Val) {
450 return Vertices.insert(std::move(Val));
451 }
452
453 /// Inserts an edge into the graph with Identifier Val.first, and
454 /// Attribute Val.second. If the key is already in the map, it returns false
455 /// and doesn't update the value.
456 std::pair<EdgeIterator, bool>
457 insert(const std::pair<EdgeIdentifier, EdgeAttribute> &Val) {
458 const auto &p = Edges.insert(Val);
459 if (p.second) {
460 const auto &EI = Val.first;
461 Vertices.FindAndConstruct(EI.first);
462 Vertices.FindAndConstruct(EI.second);
463 InNeighbors[EI.second].insert(EI.first);
464 OutNeighbors[EI.first].insert(EI.second);
465 };
466
467 return p;
468 }
469
470 /// Inserts an edge into the graph with Identifier Val.first, and
471 /// Attribute Val.second. If the key is already in the map, it returns false
472 /// and doesn't update the value.
473 std::pair<EdgeIterator, bool>
474 insert(std::pair<EdgeIdentifier, EdgeAttribute> &&Val) {
475 auto EI = Val.first;
476 const auto &p = Edges.insert(std::move(Val));
477 if (p.second) {
478 Vertices.try_emplace(EI.first);
479 Vertices.try_emplace(EI.second);
480 InNeighbors[EI.second].insert(EI.first);
481 OutNeighbors[EI.first].insert(EI.second);
482 };
483
484 return p;
485 }
486};
487} // namespace llvm::xray
488
489#endif
aarch64 promote const
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
#define I(x, y, z)
Definition MD5.cpp:58
#define G(x, y, z)
Definition MD5.cpp:56
#define T
StandardInstrumentations SI(Mod->getContext(), Debug, VerifyEach)
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT > iterator
Definition DenseMap.h:74
DenseMapIterator< KeyT, ValueT, KeyInfoT, BucketT, true > const_iterator
Definition DenseMap.h:75
Implements a dense probed hash-table based set.
Definition DenseSet.h:279
Tagged union holding either a T or a Error.
Definition Error.h:485
CRTP base class for adapting an iterator to a different type.
Definition iterator.h:237
ReferenceT operator*() const
Definition iterator.h:305
A class for ranging over all the edges in the graph.
Definition Graph.h:309
const_iterator cend() const
Definition Graph.h:323
const_iterator end() const
Definition Graph.h:325
size_type size() const
Definition Graph.h:326
ConstEdgeIterator const_iterator
Definition Graph.h:313
std::conditional_t< isConst, const Graph, Graph > GraphT
Definition Graph.h:314
const_iterator cbegin() const
Definition Graph.h:322
std::conditional_t< isConst, ConstEdgeIterator, EdgeIterator > iterator
Definition Graph.h:311
const_iterator begin() const
Definition Graph.h:324
A class for ranging over the incoming edges incident to a vertex.
Definition Graph.h:197
NeighborEdgeIteratorT< isConst, isOut > iterator
Definition Graph.h:199
const_iterator end() const
Definition Graph.h:240
const_iterator cbegin() const
Definition Graph.h:218
std::conditional_t< isConst, const EdgeMapT, EdgeMapT > InternalEdgeMapT
Definition Graph.h:202
std::conditional_t< isConst, const Graph, Graph > GraphT
Definition Graph.h:201
const_iterator begin() const
Definition Graph.h:225
NeighborEdgeIteratorT< true, isOut > const_iterator
Definition Graph.h:200
size_type size() const
Definition Graph.h:242
const_iterator cend() const
Definition Graph.h:233
InOutEdgeView(GraphT &G, VertexIdentifier A)
Definition Graph.h:252
A class for ranging over the vertices in the graph.
Definition Graph.h:272
std::conditional_t< isConst, ConstVertexIterator, VertexIterator > iterator
Definition Graph.h:274
ConstVertexIterator const_iterator
Definition Graph.h:276
const_iterator end() const
Definition Graph.h:288
const_iterator begin() const
Definition Graph.h:287
const_iterator cend() const
Definition Graph.h:286
std::conditional_t< isConst, const Graph, Graph > GraphT
Definition Graph.h:277
size_type size() const
Definition Graph.h:289
const_iterator cbegin() const
Definition Graph.h:285
A Graph object represents a Directed Graph and is used in XRay to compute and store function call gra...
Definition Graph.h:73
std::pair< EdgeIterator, bool > insert(std::pair< EdgeIdentifier, EdgeAttribute > &&Val)
Inserts an edge into the graph with Identifier Val.first, and Attribute Val.second.
Definition Graph.h:474
std::pair< EdgeIterator, bool > insert(const std::pair< EdgeIdentifier, EdgeAttribute > &Val)
Inserts an edge into the graph with Identifier Val.first, and Attribute Val.second.
Definition Graph.h:457
EdgeAttribute & operator[](const EdgeIdentifier &I)
Looks up the edge with identifier I, if it does not exist it default constructs it,...
Definition Graph.h:385
std::pair< VertexIterator, bool > insert(std::pair< VertexIdentifier, VertexAttribute > &&Val)
Definition Graph.h:449
VertexView< false > vertices()
Returns a view object allowing iteration over the vertices of the graph.
Definition Graph.h:348
NeighborEdgeIteratorT< false, true > OutEdgeIterator
An iterator type for iterating through the set of edges leaving a vertex.
Definition Graph.h:190
InOutEdgeView< true, true > outEdges(const VertexIdentifier I) const
Definition Graph.h:364
size_type count(const EdgeIdentifier &I) const
Looks for an edge with Identifier I, returns 1 if one exists and 0 otherwise.
Definition Graph.h:439
void clear()
Empty the Graph.
Definition Graph.h:339
EdgeView< true > edges() const
Definition Graph.h:356
size_type count(const VertexIdentifier &I) const
Looks for a vertex with identifier I, returns 1 if one exists, and 0 otherwise.
Definition Graph.h:433
NeighborEdgeIteratorT< true, false > ConstInEdgeIterator
A const iterator type for iterating through the set of edges entering a vertex.
Definition Graph.h:174
std::size_t size_type
Definition Graph.h:88
EdgeView< false > edges()
Returns a view object allowing iteration over the edges of the graph.
Definition Graph.h:354
NeighborEdgeIteratorT< true, true > ConstOutEdgeIterator
A const iterator type for iterating through the set of edges entering a vertex.
Definition Graph.h:185
NeighborEdgeIteratorT< false, false > InEdgeIterator
An iterator type for iterating through the set of edges leaving a vertex.
Definition Graph.h:179
typename VertexMapT::iterator VertexIterator
An iterator type for iterating through the whole vertex set of the graph.
Definition Graph.h:265
InOutEdgeView< false, false > inEdges(const VertexIdentifier I)
Returns a view object allowing iteration over the edges which point to a vertex I.
Definition Graph.h:370
typename EdgeMapT::const_iterator ConstEdgeIterator
A const iterator for iterating through the entire edge set of the graph.
Definition Graph.h:297
std::pair< VertexIterator, bool > insert(const std::pair< VertexIdentifier, VertexAttribute > &Val)
Inserts a vertex into the graph with Identifier Val.first, and Attribute Val.second.
Definition Graph.h:444
detail::DenseMapPair< VertexIdentifier, VertexAttribute > VertexValueType
This type is the value_type of all iterators which range over vertices, Determined by the Vertices De...
Definition Graph.h:81
Expected< const VertexAttribute & > at(const VertexIdentifier &I) const
Definition Graph.h:403
VI VertexIdentifier
These objects are used to name edges and vertices in the graph.
Definition Graph.h:76
Expected< VertexAttribute & > at(const VertexIdentifier &I)
Looks up a vertex with Identifier I, or an error if it does not exist.
Definition Graph.h:394
VertexAttribute & operator[](const VertexIdentifier &I)
Looks up the vertex with identifier I, if it does not exist it default constructs it.
Definition Graph.h:380
VertexView< true > vertices() const
Definition Graph.h:350
InOutEdgeView< true, false > inEdges(const VertexIdentifier I) const
Definition Graph.h:374
typename VertexMapT::const_iterator ConstVertexIterator
A const iterator type for iterating through the whole vertex set of the graph.
Definition Graph.h:260
typename EdgeMapT::iterator EdgeIterator
An iterator for iterating through the entire edge set of the graph.
Definition Graph.h:302
std::pair< VI, VI > EdgeIdentifier
Definition Graph.h:77
detail::DenseMapPair< EdgeIdentifier, EdgeAttribute > EdgeValueType
This type is the value_type of all iterators which range over edges, Determined by the Edges DenseMap...
Definition Graph.h:86
Expected< const EdgeAttribute & > at(const EdgeIdentifier &I) const
Definition Graph.h:422
Expected< EdgeAttribute & > at(const EdgeIdentifier &I)
Looks up an edge with Identifier I, or an error if it does not exist.
Definition Graph.h:413
InOutEdgeView< false, true > outEdges(const VertexIdentifier I)
Returns a view object allowing iteration over the edges which start at a vertex I.
Definition Graph.h:360
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
Definition Error.h:340