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 10 #include "llvm/ADT/SCCIterator.h" 11 #include "gtest/gtest.h" 12 #include "TestGraph.h" 13 #include <limits.h> 14 15 using namespace llvm; 16 17 namespace llvm { 18 19 TEST(SCCIteratorTest, AllSmallGraphs) { 20 // Test SCC computation against every graph with NUM_NODES nodes or less. 21 // Since SCC considers every node to have an implicit self-edge, we only 22 // create graphs for which every node has a self-edge. 23 #define NUM_NODES 4 24 #define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1)) 25 typedef Graph<NUM_NODES> GT; 26 27 /// Enumerate all graphs using NUM_GRAPHS bits. 28 static_assert(NUM_GRAPHS < sizeof(unsigned) * CHAR_BIT, "Too many graphs!"); 29 for (unsigned GraphDescriptor = 0; GraphDescriptor < (1U << NUM_GRAPHS); 30 ++GraphDescriptor) { 31 GT G; 32 33 // Add edges as specified by the descriptor. 34 unsigned DescriptorCopy = GraphDescriptor; 35 for (unsigned i = 0; i != NUM_NODES; ++i) 36 for (unsigned j = 0; j != NUM_NODES; ++j) { 37 // Always add a self-edge. 38 if (i == j) { 39 G.AddEdge(i, j); 40 continue; 41 } 42 if (DescriptorCopy & 1) 43 G.AddEdge(i, j); 44 DescriptorCopy >>= 1; 45 } 46 47 // Test the SCC logic on this graph. 48 49 /// NodesInSomeSCC - Those nodes which are in some SCC. 50 GT::NodeSubset NodesInSomeSCC; 51 52 for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) { 53 const std::vector<GT::NodeType *> &SCC = *I; 54 55 // Get the nodes in this SCC as a NodeSubset rather than a vector. 56 GT::NodeSubset NodesInThisSCC; 57 for (unsigned i = 0, e = SCC.size(); i != e; ++i) 58 NodesInThisSCC.AddNode(SCC[i]->first); 59 60 // There should be at least one node in every SCC. 61 EXPECT_FALSE(NodesInThisSCC.isEmpty()); 62 63 // Check that every node in the SCC is reachable from every other node in 64 // the SCC. 65 for (unsigned i = 0; i != NUM_NODES; ++i) 66 if (NodesInThisSCC.count(i)) 67 EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i))); 68 69 // OK, now that we now that every node in the SCC is reachable from every 70 // other, this means that the set of nodes reachable from any node in the 71 // SCC is the same as the set of nodes reachable from every node in the 72 // SCC. Check that for every node N not in the SCC but reachable from the 73 // SCC, no element of the SCC is reachable from N. 74 for (unsigned i = 0; i != NUM_NODES; ++i) 75 if (NodesInThisSCC.count(i)) { 76 GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i); 77 GT::NodeSubset ReachableButNotInSCC = 78 NodesReachableFromSCC.Meet(NodesInThisSCC.Complement()); 79 80 for (unsigned j = 0; j != NUM_NODES; ++j) 81 if (ReachableButNotInSCC.count(j)) 82 EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty()); 83 84 // The result must be the same for all other nodes in this SCC, so 85 // there is no point in checking them. 86 break; 87 } 88 89 // This is indeed a SCC: a maximal set of nodes for which each node is 90 // reachable from every other. 91 92 // Check that we didn't already see this SCC. 93 EXPECT_TRUE(NodesInSomeSCC.Meet(NodesInThisSCC).isEmpty()); 94 95 NodesInSomeSCC = NodesInSomeSCC.Join(NodesInThisSCC); 96 97 // Check a property that is specific to the LLVM SCC iterator and 98 // guaranteed by it: if a node in SCC S1 has an edge to a node in 99 // SCC S2, then S1 is visited *after* S2. This means that the set 100 // of nodes reachable from this SCC must be contained either in the 101 // union of this SCC and all previously visited SCC's. 102 103 for (unsigned i = 0; i != NUM_NODES; ++i) 104 if (NodesInThisSCC.count(i)) { 105 GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i); 106 EXPECT_TRUE(NodesReachableFromSCC.isSubsetOf(NodesInSomeSCC)); 107 // The result must be the same for all other nodes in this SCC, so 108 // there is no point in checking them. 109 break; 110 } 111 } 112 113 // Finally, check that the nodes in some SCC are exactly those that are 114 // reachable from the initial node. 115 EXPECT_EQ(NodesInSomeSCC, G.NodesReachableFrom(0)); 116 } 117 } 118 119 } 120