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