xref: /llvm-project/llvm/unittests/ADT/TestGraph.h (revision 5272d2a3a43b21dadb61a8320c14df94db89acc1)
1608ca250STim Shen //===- llvm/unittest/ADT/TestGraph.h - Graph for testing ------------------===//
2608ca250STim Shen //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6608ca250STim Shen //
7608ca250STim Shen //===----------------------------------------------------------------------===//
8608ca250STim Shen //
9608ca250STim Shen // Common graph data structure for testing.
10608ca250STim Shen //
11608ca250STim Shen //===----------------------------------------------------------------------===//
12608ca250STim Shen 
13c30340b2SArgyrios Kyrtzidis #ifndef LLVM_UNITTESTS_ADT_TEST_GRAPH_H
14c30340b2SArgyrios Kyrtzidis #define LLVM_UNITTESTS_ADT_TEST_GRAPH_H
15c30340b2SArgyrios Kyrtzidis 
16608ca250STim Shen #include "llvm/ADT/GraphTraits.h"
17608ca250STim Shen #include <cassert>
18608ca250STim Shen #include <climits>
19608ca250STim Shen #include <utility>
20608ca250STim Shen 
21608ca250STim Shen namespace llvm {
22608ca250STim Shen 
23608ca250STim Shen /// Graph<N> - A graph with N nodes.  Note that N can be at most 8.
24608ca250STim Shen template <unsigned N>
25608ca250STim Shen class Graph {
26608ca250STim Shen private:
27608ca250STim Shen   // Disable copying.
28608ca250STim Shen   Graph(const Graph&);
29608ca250STim Shen   Graph& operator=(const Graph&);
30608ca250STim Shen 
ValidateIndex(unsigned Idx)31608ca250STim Shen   static void ValidateIndex(unsigned Idx) {
32608ca250STim Shen     assert(Idx < N && "Invalid node index!");
33608ca250STim Shen   }
34608ca250STim Shen public:
35608ca250STim Shen 
36608ca250STim Shen   /// NodeSubset - A subset of the graph's nodes.
37608ca250STim Shen   class NodeSubset {
38608ca250STim Shen     typedef unsigned char BitVector; // Where the limitation N <= 8 comes from.
39608ca250STim Shen     BitVector Elements;
NodeSubset(BitVector e)40608ca250STim Shen     NodeSubset(BitVector e) : Elements(e) {}
41608ca250STim Shen   public:
42608ca250STim Shen     /// NodeSubset - Default constructor, creates an empty subset.
NodeSubset()43608ca250STim Shen     NodeSubset() : Elements(0) {
44608ca250STim Shen       assert(N <= sizeof(BitVector)*CHAR_BIT && "Graph too big!");
45608ca250STim Shen     }
46608ca250STim Shen 
47608ca250STim Shen     /// Comparison operators.
48608ca250STim Shen     bool operator==(const NodeSubset &other) const {
49608ca250STim Shen       return other.Elements == this->Elements;
50608ca250STim Shen     }
51608ca250STim Shen     bool operator!=(const NodeSubset &other) const {
52608ca250STim Shen       return !(*this == other);
53608ca250STim Shen     }
54608ca250STim Shen 
55608ca250STim Shen     /// AddNode - Add the node with the given index to the subset.
AddNode(unsigned Idx)56608ca250STim Shen     void AddNode(unsigned Idx) {
57608ca250STim Shen       ValidateIndex(Idx);
58608ca250STim Shen       Elements |= 1U << Idx;
59608ca250STim Shen     }
60608ca250STim Shen 
61608ca250STim Shen     /// DeleteNode - Remove the node with the given index from the subset.
DeleteNode(unsigned Idx)62608ca250STim Shen     void DeleteNode(unsigned Idx) {
63608ca250STim Shen       ValidateIndex(Idx);
64608ca250STim Shen       Elements &= ~(1U << Idx);
65608ca250STim Shen     }
66608ca250STim Shen 
67608ca250STim Shen     /// count - Return true if the node with the given index is in the subset.
count(unsigned Idx)68608ca250STim Shen     bool count(unsigned Idx) {
69608ca250STim Shen       ValidateIndex(Idx);
70608ca250STim Shen       return (Elements & (1U << Idx)) != 0;
71608ca250STim Shen     }
72608ca250STim Shen 
73608ca250STim Shen     /// isEmpty - Return true if this is the empty set.
isEmpty()74608ca250STim Shen     bool isEmpty() const {
75608ca250STim Shen       return Elements == 0;
76608ca250STim Shen     }
77608ca250STim Shen 
78608ca250STim Shen     /// isSubsetOf - Return true if this set is a subset of the given one.
isSubsetOf(const NodeSubset & other)79608ca250STim Shen     bool isSubsetOf(const NodeSubset &other) const {
80608ca250STim Shen       return (this->Elements | other.Elements) == other.Elements;
81608ca250STim Shen     }
82608ca250STim Shen 
83608ca250STim Shen     /// Complement - Return the complement of this subset.
Complement()84608ca250STim Shen     NodeSubset Complement() const {
85608ca250STim Shen       return ~(unsigned)this->Elements & ((1U << N) - 1);
86608ca250STim Shen     }
87608ca250STim Shen 
88608ca250STim Shen     /// Join - Return the union of this subset and the given one.
Join(const NodeSubset & other)89608ca250STim Shen     NodeSubset Join(const NodeSubset &other) const {
90608ca250STim Shen       return this->Elements | other.Elements;
91608ca250STim Shen     }
92608ca250STim Shen 
93608ca250STim Shen     /// Meet - Return the intersection of this subset and the given one.
Meet(const NodeSubset & other)94608ca250STim Shen     NodeSubset Meet(const NodeSubset &other) const {
95608ca250STim Shen       return this->Elements & other.Elements;
96608ca250STim Shen     }
97608ca250STim Shen   };
98608ca250STim Shen 
99608ca250STim Shen   /// NodeType - Node index and set of children of the node.
100608ca250STim Shen   typedef std::pair<unsigned, NodeSubset> NodeType;
101608ca250STim Shen 
102608ca250STim Shen private:
103608ca250STim Shen   /// Nodes - The list of nodes for this graph.
104608ca250STim Shen   NodeType Nodes[N];
105608ca250STim Shen public:
106608ca250STim Shen 
107608ca250STim Shen   /// Graph - Default constructor.  Creates an empty graph.
Graph()108608ca250STim Shen   Graph() {
109608ca250STim Shen     // Let each node know which node it is.  This allows us to find the start of
110608ca250STim Shen     // the Nodes array given a pointer to any element of it.
111608ca250STim Shen     for (unsigned i = 0; i != N; ++i)
112608ca250STim Shen       Nodes[i].first = i;
113608ca250STim Shen   }
114608ca250STim Shen 
115608ca250STim Shen   /// AddEdge - Add an edge from the node with index FromIdx to the node with
116608ca250STim Shen   /// index ToIdx.
AddEdge(unsigned FromIdx,unsigned ToIdx)117608ca250STim Shen   void AddEdge(unsigned FromIdx, unsigned ToIdx) {
118608ca250STim Shen     ValidateIndex(FromIdx);
119608ca250STim Shen     Nodes[FromIdx].second.AddNode(ToIdx);
120608ca250STim Shen   }
121608ca250STim Shen 
122608ca250STim Shen   /// DeleteEdge - Remove the edge (if any) from the node with index FromIdx to
123608ca250STim Shen   /// the node with index ToIdx.
DeleteEdge(unsigned FromIdx,unsigned ToIdx)124608ca250STim Shen   void DeleteEdge(unsigned FromIdx, unsigned ToIdx) {
125608ca250STim Shen     ValidateIndex(FromIdx);
126608ca250STim Shen     Nodes[FromIdx].second.DeleteNode(ToIdx);
127608ca250STim Shen   }
128608ca250STim Shen 
129608ca250STim Shen   /// AccessNode - Get a pointer to the node with the given index.
AccessNode(unsigned Idx)130608ca250STim Shen   NodeType *AccessNode(unsigned Idx) const {
131608ca250STim Shen     ValidateIndex(Idx);
132608ca250STim Shen     // The constant cast is needed when working with GraphTraits, which insists
133608ca250STim Shen     // on taking a constant Graph.
134608ca250STim Shen     return const_cast<NodeType *>(&Nodes[Idx]);
135608ca250STim Shen   }
136608ca250STim Shen 
137608ca250STim Shen   /// NodesReachableFrom - Return the set of all nodes reachable from the given
138608ca250STim Shen   /// node.
NodesReachableFrom(unsigned Idx)139608ca250STim Shen   NodeSubset NodesReachableFrom(unsigned Idx) const {
140608ca250STim Shen     // This algorithm doesn't scale, but that doesn't matter given the small
141608ca250STim Shen     // size of our graphs.
142608ca250STim Shen     NodeSubset Reachable;
143608ca250STim Shen 
144608ca250STim Shen     // The initial node is reachable.
145608ca250STim Shen     Reachable.AddNode(Idx);
146608ca250STim Shen     do {
147608ca250STim Shen       NodeSubset Previous(Reachable);
148608ca250STim Shen 
149608ca250STim Shen       // Add in all nodes which are children of a reachable node.
150608ca250STim Shen       for (unsigned i = 0; i != N; ++i)
151608ca250STim Shen         if (Previous.count(i))
152608ca250STim Shen           Reachable = Reachable.Join(Nodes[i].second);
153608ca250STim Shen 
154608ca250STim Shen       // If nothing changed then we have found all reachable nodes.
155608ca250STim Shen       if (Reachable == Previous)
156608ca250STim Shen         return Reachable;
157608ca250STim Shen 
158608ca250STim Shen       // Rinse and repeat.
159608ca250STim Shen     } while (1);
160608ca250STim Shen   }
161608ca250STim Shen 
162608ca250STim Shen   /// ChildIterator - Visit all children of a node.
163608ca250STim Shen   class ChildIterator {
164608ca250STim Shen     friend class Graph;
165608ca250STim Shen 
166608ca250STim Shen     /// FirstNode - Pointer to first node in the graph's Nodes array.
167608ca250STim Shen     NodeType *FirstNode;
168608ca250STim Shen     /// Children - Set of nodes which are children of this one and that haven't
169608ca250STim Shen     /// yet been visited.
170608ca250STim Shen     NodeSubset Children;
171608ca250STim Shen 
172608ca250STim Shen     ChildIterator(); // Disable default constructor.
173608ca250STim Shen   protected:
ChildIterator(NodeType * F,NodeSubset C)174608ca250STim Shen     ChildIterator(NodeType *F, NodeSubset C) : FirstNode(F), Children(C) {}
175608ca250STim Shen 
176608ca250STim Shen   public:
177608ca250STim Shen     /// ChildIterator - Copy constructor.
178*5272d2a3SDávid Bolvanský     ChildIterator(const ChildIterator &other) = default;
179*5272d2a3SDávid Bolvanský     ChildIterator &operator=(const ChildIterator &other) = default;
180608ca250STim Shen 
181608ca250STim Shen     /// Comparison operators.
182608ca250STim Shen     bool operator==(const ChildIterator &other) const {
183608ca250STim Shen       return other.FirstNode == this->FirstNode &&
184608ca250STim Shen         other.Children == this->Children;
185608ca250STim Shen     }
186608ca250STim Shen     bool operator!=(const ChildIterator &other) const {
187608ca250STim Shen       return !(*this == other);
188608ca250STim Shen     }
189608ca250STim Shen 
190608ca250STim Shen     /// Prefix increment operator.
191608ca250STim Shen     ChildIterator& operator++() {
192608ca250STim Shen       // Find the next unvisited child node.
193608ca250STim Shen       for (unsigned i = 0; i != N; ++i)
194608ca250STim Shen         if (Children.count(i)) {
195608ca250STim Shen           // Remove that child - it has been visited.  This is the increment!
196608ca250STim Shen           Children.DeleteNode(i);
197608ca250STim Shen           return *this;
198608ca250STim Shen         }
199608ca250STim Shen       assert(false && "Incrementing end iterator!");
200608ca250STim Shen       return *this; // Avoid compiler warnings.
201608ca250STim Shen     }
202608ca250STim Shen 
203608ca250STim Shen     /// Postfix increment operator.
204608ca250STim Shen     ChildIterator operator++(int) {
205608ca250STim Shen       ChildIterator Result(*this);
206608ca250STim Shen       ++(*this);
207608ca250STim Shen       return Result;
208608ca250STim Shen     }
209608ca250STim Shen 
210608ca250STim Shen     /// Dereference operator.
211608ca250STim Shen     NodeType *operator*() {
212608ca250STim Shen       // Find the next unvisited child node.
213608ca250STim Shen       for (unsigned i = 0; i != N; ++i)
214608ca250STim Shen         if (Children.count(i))
215608ca250STim Shen           // Return a pointer to it.
216608ca250STim Shen           return FirstNode + i;
217608ca250STim Shen       assert(false && "Dereferencing end iterator!");
218608ca250STim Shen       return nullptr; // Avoid compiler warning.
219608ca250STim Shen     }
220608ca250STim Shen   };
221608ca250STim Shen 
222608ca250STim Shen   /// child_begin - Return an iterator pointing to the first child of the given
223608ca250STim Shen   /// node.
child_begin(NodeType * Parent)224608ca250STim Shen   static ChildIterator child_begin(NodeType *Parent) {
225608ca250STim Shen     return ChildIterator(Parent - Parent->first, Parent->second);
226608ca250STim Shen   }
227608ca250STim Shen 
228608ca250STim Shen   /// child_end - Return the end iterator for children of the given node.
child_end(NodeType * Parent)229608ca250STim Shen   static ChildIterator child_end(NodeType *Parent) {
230608ca250STim Shen     return ChildIterator(Parent - Parent->first, NodeSubset());
231608ca250STim Shen   }
232608ca250STim Shen };
233608ca250STim Shen 
234608ca250STim Shen template <unsigned N>
235608ca250STim Shen struct GraphTraits<Graph<N> > {
236608ca250STim Shen   typedef typename Graph<N>::NodeType *NodeRef;
237608ca250STim Shen   typedef typename Graph<N>::ChildIterator ChildIteratorType;
238608ca250STim Shen 
23948f814e8STim Shen   static NodeRef getEntryNode(const Graph<N> &G) { return G.AccessNode(0); }
24048f814e8STim Shen   static ChildIteratorType child_begin(NodeRef Node) {
241608ca250STim Shen     return Graph<N>::child_begin(Node);
242608ca250STim Shen   }
24348f814e8STim Shen   static ChildIteratorType child_end(NodeRef Node) {
244608ca250STim Shen     return Graph<N>::child_end(Node);
245608ca250STim Shen   }
246608ca250STim Shen };
247608ca250STim Shen 
248608ca250STim Shen } // End namespace llvm
249608ca250STim Shen 
250608ca250STim Shen #endif
251