SCCIteratorTest.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. //===----- llvm/unittest/ADT/SCCIteratorTest.cpp - SCCIterator tests ------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "llvm/ADT/SCCIterator.h"
  10. #include "llvm/ADT/GraphTraits.h"
  11. #include "gtest/gtest.h"
  12. #include <limits.h>
  13. using namespace llvm;
  14. namespace llvm {
  15. /// Graph<N> - A graph with N nodes. Note that N can be at most 8.
  16. template <unsigned N>
  17. class Graph {
  18. private:
  19. // Disable copying.
  20. Graph(const Graph&);
  21. Graph& operator=(const Graph&);
  22. static void ValidateIndex(unsigned Idx) {
  23. assert(Idx < N && "Invalid node index!");
  24. }
  25. public:
  26. /// NodeSubset - A subset of the graph's nodes.
  27. class NodeSubset {
  28. typedef unsigned char BitVector; // Where the limitation N <= 8 comes from.
  29. BitVector Elements;
  30. NodeSubset(BitVector e) : Elements(e) {}
  31. public:
  32. /// NodeSubset - Default constructor, creates an empty subset.
  33. NodeSubset() : Elements(0) {
  34. assert(N <= sizeof(BitVector)*CHAR_BIT && "Graph too big!");
  35. }
  36. /// NodeSubset - Copy constructor.
  37. NodeSubset(const NodeSubset &other) : Elements(other.Elements) {}
  38. /// Comparison operators.
  39. bool operator==(const NodeSubset &other) const {
  40. return other.Elements == this->Elements;
  41. }
  42. bool operator!=(const NodeSubset &other) const {
  43. return !(*this == other);
  44. }
  45. /// AddNode - Add the node with the given index to the subset.
  46. void AddNode(unsigned Idx) {
  47. ValidateIndex(Idx);
  48. Elements |= 1U << Idx;
  49. }
  50. /// DeleteNode - Remove the node with the given index from the subset.
  51. void DeleteNode(unsigned Idx) {
  52. ValidateIndex(Idx);
  53. Elements &= ~(1U << Idx);
  54. }
  55. /// count - Return true if the node with the given index is in the subset.
  56. bool count(unsigned Idx) {
  57. ValidateIndex(Idx);
  58. return (Elements & (1U << Idx)) != 0;
  59. }
  60. /// isEmpty - Return true if this is the empty set.
  61. bool isEmpty() const {
  62. return Elements == 0;
  63. }
  64. /// isSubsetOf - Return true if this set is a subset of the given one.
  65. bool isSubsetOf(const NodeSubset &other) const {
  66. return (this->Elements | other.Elements) == other.Elements;
  67. }
  68. /// Complement - Return the complement of this subset.
  69. NodeSubset Complement() const {
  70. return ~(unsigned)this->Elements & ((1U << N) - 1);
  71. }
  72. /// Join - Return the union of this subset and the given one.
  73. NodeSubset Join(const NodeSubset &other) const {
  74. return this->Elements | other.Elements;
  75. }
  76. /// Meet - Return the intersection of this subset and the given one.
  77. NodeSubset Meet(const NodeSubset &other) const {
  78. return this->Elements & other.Elements;
  79. }
  80. };
  81. /// NodeType - Node index and set of children of the node.
  82. typedef std::pair<unsigned, NodeSubset> NodeType;
  83. private:
  84. /// Nodes - The list of nodes for this graph.
  85. NodeType Nodes[N];
  86. public:
  87. /// Graph - Default constructor. Creates an empty graph.
  88. Graph() {
  89. // Let each node know which node it is. This allows us to find the start of
  90. // the Nodes array given a pointer to any element of it.
  91. for (unsigned i = 0; i != N; ++i)
  92. Nodes[i].first = i;
  93. }
  94. /// AddEdge - Add an edge from the node with index FromIdx to the node with
  95. /// index ToIdx.
  96. void AddEdge(unsigned FromIdx, unsigned ToIdx) {
  97. ValidateIndex(FromIdx);
  98. Nodes[FromIdx].second.AddNode(ToIdx);
  99. }
  100. /// DeleteEdge - Remove the edge (if any) from the node with index FromIdx to
  101. /// the node with index ToIdx.
  102. void DeleteEdge(unsigned FromIdx, unsigned ToIdx) {
  103. ValidateIndex(FromIdx);
  104. Nodes[FromIdx].second.DeleteNode(ToIdx);
  105. }
  106. /// AccessNode - Get a pointer to the node with the given index.
  107. NodeType *AccessNode(unsigned Idx) const {
  108. ValidateIndex(Idx);
  109. // The constant cast is needed when working with GraphTraits, which insists
  110. // on taking a constant Graph.
  111. return const_cast<NodeType *>(&Nodes[Idx]);
  112. }
  113. /// NodesReachableFrom - Return the set of all nodes reachable from the given
  114. /// node.
  115. NodeSubset NodesReachableFrom(unsigned Idx) const {
  116. // This algorithm doesn't scale, but that doesn't matter given the small
  117. // size of our graphs.
  118. NodeSubset Reachable;
  119. // The initial node is reachable.
  120. Reachable.AddNode(Idx);
  121. do {
  122. NodeSubset Previous(Reachable);
  123. // Add in all nodes which are children of a reachable node.
  124. for (unsigned i = 0; i != N; ++i)
  125. if (Previous.count(i))
  126. Reachable = Reachable.Join(Nodes[i].second);
  127. // If nothing changed then we have found all reachable nodes.
  128. if (Reachable == Previous)
  129. return Reachable;
  130. // Rinse and repeat.
  131. } while (1);
  132. }
  133. /// ChildIterator - Visit all children of a node.
  134. class ChildIterator {
  135. friend class Graph;
  136. /// FirstNode - Pointer to first node in the graph's Nodes array.
  137. NodeType *FirstNode;
  138. /// Children - Set of nodes which are children of this one and that haven't
  139. /// yet been visited.
  140. NodeSubset Children;
  141. ChildIterator(); // Disable default constructor.
  142. protected:
  143. ChildIterator(NodeType *F, NodeSubset C) : FirstNode(F), Children(C) {}
  144. public:
  145. /// ChildIterator - Copy constructor.
  146. ChildIterator(const ChildIterator& other) : FirstNode(other.FirstNode),
  147. Children(other.Children) {}
  148. /// Comparison operators.
  149. bool operator==(const ChildIterator &other) const {
  150. return other.FirstNode == this->FirstNode &&
  151. other.Children == this->Children;
  152. }
  153. bool operator!=(const ChildIterator &other) const {
  154. return !(*this == other);
  155. }
  156. /// Prefix increment operator.
  157. ChildIterator& operator++() {
  158. // Find the next unvisited child node.
  159. for (unsigned i = 0; i != N; ++i)
  160. if (Children.count(i)) {
  161. // Remove that child - it has been visited. This is the increment!
  162. Children.DeleteNode(i);
  163. return *this;
  164. }
  165. assert(false && "Incrementing end iterator!");
  166. return *this; // Avoid compiler warnings.
  167. }
  168. /// Postfix increment operator.
  169. ChildIterator operator++(int) {
  170. ChildIterator Result(*this);
  171. ++(*this);
  172. return Result;
  173. }
  174. /// Dereference operator.
  175. NodeType *operator*() {
  176. // Find the next unvisited child node.
  177. for (unsigned i = 0; i != N; ++i)
  178. if (Children.count(i))
  179. // Return a pointer to it.
  180. return FirstNode + i;
  181. assert(false && "Dereferencing end iterator!");
  182. return 0; // Avoid compiler warning.
  183. }
  184. };
  185. /// child_begin - Return an iterator pointing to the first child of the given
  186. /// node.
  187. static ChildIterator child_begin(NodeType *Parent) {
  188. return ChildIterator(Parent - Parent->first, Parent->second);
  189. }
  190. /// child_end - Return the end iterator for children of the given node.
  191. static ChildIterator child_end(NodeType *Parent) {
  192. return ChildIterator(Parent - Parent->first, NodeSubset());
  193. }
  194. };
  195. template <unsigned N>
  196. struct GraphTraits<Graph<N> > {
  197. typedef typename Graph<N>::NodeType NodeType;
  198. typedef typename Graph<N>::ChildIterator ChildIteratorType;
  199. static inline NodeType *getEntryNode(const Graph<N> &G) { return G.AccessNode(0); }
  200. static inline ChildIteratorType child_begin(NodeType *Node) {
  201. return Graph<N>::child_begin(Node);
  202. }
  203. static inline ChildIteratorType child_end(NodeType *Node) {
  204. return Graph<N>::child_end(Node);
  205. }
  206. };
  207. TEST(SCCIteratorTest, AllSmallGraphs) {
  208. // Test SCC computation against every graph with NUM_NODES nodes or less.
  209. // Since SCC considers every node to have an implicit self-edge, we only
  210. // create graphs for which every node has a self-edge.
  211. #define NUM_NODES 4
  212. #define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1))
  213. typedef Graph<NUM_NODES> GT;
  214. /// Enumerate all graphs using NUM_GRAPHS bits.
  215. assert(NUM_GRAPHS < sizeof(unsigned) * CHAR_BIT && "Too many graphs!");
  216. for (unsigned GraphDescriptor = 0; GraphDescriptor < (1U << NUM_GRAPHS);
  217. ++GraphDescriptor) {
  218. GT G;
  219. // Add edges as specified by the descriptor.
  220. unsigned DescriptorCopy = GraphDescriptor;
  221. for (unsigned i = 0; i != NUM_NODES; ++i)
  222. for (unsigned j = 0; j != NUM_NODES; ++j) {
  223. // Always add a self-edge.
  224. if (i == j) {
  225. G.AddEdge(i, j);
  226. continue;
  227. }
  228. if (DescriptorCopy & 1)
  229. G.AddEdge(i, j);
  230. DescriptorCopy >>= 1;
  231. }
  232. // Test the SCC logic on this graph.
  233. /// NodesInSomeSCC - Those nodes which are in some SCC.
  234. GT::NodeSubset NodesInSomeSCC;
  235. for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) {
  236. std::vector<GT::NodeType*> &SCC = *I;
  237. // Get the nodes in this SCC as a NodeSubset rather than a vector.
  238. GT::NodeSubset NodesInThisSCC;
  239. for (unsigned i = 0, e = SCC.size(); i != e; ++i)
  240. NodesInThisSCC.AddNode(SCC[i]->first);
  241. // There should be at least one node in every SCC.
  242. EXPECT_FALSE(NodesInThisSCC.isEmpty());
  243. // Check that every node in the SCC is reachable from every other node in
  244. // the SCC.
  245. for (unsigned i = 0; i != NUM_NODES; ++i)
  246. if (NodesInThisSCC.count(i))
  247. EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i)));
  248. // OK, now that we now that every node in the SCC is reachable from every
  249. // other, this means that the set of nodes reachable from any node in the
  250. // SCC is the same as the set of nodes reachable from every node in the
  251. // SCC. Check that for every node N not in the SCC but reachable from the
  252. // SCC, no element of the SCC is reachable from N.
  253. for (unsigned i = 0; i != NUM_NODES; ++i)
  254. if (NodesInThisSCC.count(i)) {
  255. GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
  256. GT::NodeSubset ReachableButNotInSCC =
  257. NodesReachableFromSCC.Meet(NodesInThisSCC.Complement());
  258. for (unsigned j = 0; j != NUM_NODES; ++j)
  259. if (ReachableButNotInSCC.count(j))
  260. EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty());
  261. // The result must be the same for all other nodes in this SCC, so
  262. // there is no point in checking them.
  263. break;
  264. }
  265. // This is indeed a SCC: a maximal set of nodes for which each node is
  266. // reachable from every other.
  267. // Check that we didn't already see this SCC.
  268. EXPECT_TRUE(NodesInSomeSCC.Meet(NodesInThisSCC).isEmpty());
  269. NodesInSomeSCC = NodesInSomeSCC.Join(NodesInThisSCC);
  270. // Check a property that is specific to the LLVM SCC iterator and
  271. // guaranteed by it: if a node in SCC S1 has an edge to a node in
  272. // SCC S2, then S1 is visited *after* S2. This means that the set
  273. // of nodes reachable from this SCC must be contained either in the
  274. // union of this SCC and all previously visited SCC's.
  275. for (unsigned i = 0; i != NUM_NODES; ++i)
  276. if (NodesInThisSCC.count(i)) {
  277. GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i);
  278. EXPECT_TRUE(NodesReachableFromSCC.isSubsetOf(NodesInSomeSCC));
  279. // The result must be the same for all other nodes in this SCC, so
  280. // there is no point in checking them.
  281. break;
  282. }
  283. }
  284. // Finally, check that the nodes in some SCC are exactly those that are
  285. // reachable from the initial node.
  286. EXPECT_EQ(NodesInSomeSCC, G.NodesReachableFrom(0));
  287. }
  288. }
  289. }