| //===----- llvm/unittest/ADT/SCCIteratorTest.cpp - SCCIterator tests ------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #include <limits.h> | 
 | #include "llvm/ADT/GraphTraits.h" | 
 | #include "llvm/ADT/SCCIterator.h" | 
 | #include "gtest/gtest.h" | 
 |  | 
 | using namespace llvm; | 
 |  | 
 | namespace llvm { | 
 |  | 
 | /// Graph<N> - A graph with N nodes.  Note that N can be at most 8. | 
 | template <unsigned N> | 
 | class Graph { | 
 | private: | 
 |   // Disable copying. | 
 |   Graph(const Graph&); | 
 |   Graph& operator=(const Graph&); | 
 |  | 
 |   static void ValidateIndex(unsigned Idx) { | 
 |     assert(Idx < N && "Invalid node index!"); | 
 |   } | 
 | public: | 
 |  | 
 |   /// NodeSubset - A subset of the graph's nodes. | 
 |   class NodeSubset { | 
 |     typedef unsigned char BitVector; // Where the limitation N <= 8 comes from. | 
 |     BitVector Elements; | 
 |     NodeSubset(BitVector e) : Elements(e) {} | 
 |   public: | 
 |     /// NodeSubset - Default constructor, creates an empty subset. | 
 |     NodeSubset() : Elements(0) { | 
 |       assert(N <= sizeof(BitVector)*CHAR_BIT && "Graph too big!"); | 
 |     } | 
 |     /// NodeSubset - Copy constructor. | 
 |     NodeSubset(const NodeSubset &other) : Elements(other.Elements) {} | 
 |  | 
 |     /// Comparison operators. | 
 |     bool operator==(const NodeSubset &other) const { | 
 |       return other.Elements == this->Elements; | 
 |     } | 
 |     bool operator!=(const NodeSubset &other) const { | 
 |       return !(*this == other); | 
 |     } | 
 |  | 
 |     /// AddNode - Add the node with the given index to the subset. | 
 |     void AddNode(unsigned Idx) { | 
 |       ValidateIndex(Idx); | 
 |       Elements |= 1U << Idx; | 
 |     } | 
 |  | 
 |     /// DeleteNode - Remove the node with the given index from the subset. | 
 |     void DeleteNode(unsigned Idx) { | 
 |       ValidateIndex(Idx); | 
 |       Elements &= ~(1U << Idx); | 
 |     } | 
 |  | 
 |     /// count - Return true if the node with the given index is in the subset. | 
 |     bool count(unsigned Idx) { | 
 |       ValidateIndex(Idx); | 
 |       return (Elements & (1U << Idx)) != 0; | 
 |     } | 
 |  | 
 |     /// isEmpty - Return true if this is the empty set. | 
 |     bool isEmpty() const { | 
 |       return Elements == 0; | 
 |     } | 
 |  | 
 |     /// isSubsetOf - Return true if this set is a subset of the given one. | 
 |     bool isSubsetOf(const NodeSubset &other) const { | 
 |       return (this->Elements | other.Elements) == other.Elements; | 
 |     } | 
 |  | 
 |     /// Complement - Return the complement of this subset. | 
 |     NodeSubset Complement() const { | 
 |       return ~(unsigned)this->Elements & ((1U << N) - 1); | 
 |     } | 
 |  | 
 |     /// Join - Return the union of this subset and the given one. | 
 |     NodeSubset Join(const NodeSubset &other) const { | 
 |       return this->Elements | other.Elements; | 
 |     } | 
 |  | 
 |     /// Meet - Return the intersection of this subset and the given one. | 
 |     NodeSubset Meet(const NodeSubset &other) const { | 
 |       return this->Elements & other.Elements; | 
 |     } | 
 |   }; | 
 |  | 
 |   /// NodeType - Node index and set of children of the node. | 
 |   typedef std::pair<unsigned, NodeSubset> NodeType; | 
 |  | 
 | private: | 
 |   /// Nodes - The list of nodes for this graph. | 
 |   NodeType Nodes[N]; | 
 | public: | 
 |  | 
 |   /// Graph - Default constructor.  Creates an empty graph. | 
 |   Graph() { | 
 |     // Let each node know which node it is.  This allows us to find the start of | 
 |     // the Nodes array given a pointer to any element of it. | 
 |     for (unsigned i = 0; i != N; ++i) | 
 |       Nodes[i].first = i; | 
 |   } | 
 |  | 
 |   /// AddEdge - Add an edge from the node with index FromIdx to the node with | 
 |   /// index ToIdx. | 
 |   void AddEdge(unsigned FromIdx, unsigned ToIdx) { | 
 |     ValidateIndex(FromIdx); | 
 |     Nodes[FromIdx].second.AddNode(ToIdx); | 
 |   } | 
 |  | 
 |   /// DeleteEdge - Remove the edge (if any) from the node with index FromIdx to | 
 |   /// the node with index ToIdx. | 
 |   void DeleteEdge(unsigned FromIdx, unsigned ToIdx) { | 
 |     ValidateIndex(FromIdx); | 
 |     Nodes[FromIdx].second.DeleteNode(ToIdx); | 
 |   } | 
 |  | 
 |   /// AccessNode - Get a pointer to the node with the given index. | 
 |   NodeType *AccessNode(unsigned Idx) const { | 
 |     ValidateIndex(Idx); | 
 |     // The constant cast is needed when working with GraphTraits, which insists | 
 |     // on taking a constant Graph. | 
 |     return const_cast<NodeType *>(&Nodes[Idx]); | 
 |   } | 
 |  | 
 |   /// NodesReachableFrom - Return the set of all nodes reachable from the given | 
 |   /// node. | 
 |   NodeSubset NodesReachableFrom(unsigned Idx) const { | 
 |     // This algorithm doesn't scale, but that doesn't matter given the small | 
 |     // size of our graphs. | 
 |     NodeSubset Reachable; | 
 |  | 
 |     // The initial node is reachable. | 
 |     Reachable.AddNode(Idx); | 
 |     do { | 
 |       NodeSubset Previous(Reachable); | 
 |  | 
 |       // Add in all nodes which are children of a reachable node. | 
 |       for (unsigned i = 0; i != N; ++i) | 
 |         if (Previous.count(i)) | 
 |           Reachable = Reachable.Join(Nodes[i].second); | 
 |  | 
 |       // If nothing changed then we have found all reachable nodes. | 
 |       if (Reachable == Previous) | 
 |         return Reachable; | 
 |  | 
 |       // Rinse and repeat. | 
 |     } while (1); | 
 |   } | 
 |  | 
 |   /// ChildIterator - Visit all children of a node. | 
 |   class ChildIterator { | 
 |     friend class Graph; | 
 |  | 
 |     /// FirstNode - Pointer to first node in the graph's Nodes array. | 
 |     NodeType *FirstNode; | 
 |     /// Children - Set of nodes which are children of this one and that haven't | 
 |     /// yet been visited. | 
 |     NodeSubset Children; | 
 |  | 
 |     ChildIterator(); // Disable default constructor. | 
 |   protected: | 
 |     ChildIterator(NodeType *F, NodeSubset C) : FirstNode(F), Children(C) {} | 
 |  | 
 |   public: | 
 |     /// ChildIterator - Copy constructor. | 
 |     ChildIterator(const ChildIterator& other) : FirstNode(other.FirstNode), | 
 |       Children(other.Children) {} | 
 |  | 
 |     /// Comparison operators. | 
 |     bool operator==(const ChildIterator &other) const { | 
 |       return other.FirstNode == this->FirstNode && | 
 |         other.Children == this->Children; | 
 |     } | 
 |     bool operator!=(const ChildIterator &other) const { | 
 |       return !(*this == other); | 
 |     } | 
 |  | 
 |     /// Prefix increment operator. | 
 |     ChildIterator& operator++() { | 
 |       // Find the next unvisited child node. | 
 |       for (unsigned i = 0; i != N; ++i) | 
 |         if (Children.count(i)) { | 
 |           // Remove that child - it has been visited.  This is the increment! | 
 |           Children.DeleteNode(i); | 
 |           return *this; | 
 |         } | 
 |       assert(false && "Incrementing end iterator!"); | 
 |       return *this; // Avoid compiler warnings. | 
 |     } | 
 |  | 
 |     /// Postfix increment operator. | 
 |     ChildIterator operator++(int) { | 
 |       ChildIterator Result(*this); | 
 |       ++(*this); | 
 |       return Result; | 
 |     } | 
 |  | 
 |     /// Dereference operator. | 
 |     NodeType *operator*() { | 
 |       // Find the next unvisited child node. | 
 |       for (unsigned i = 0; i != N; ++i) | 
 |         if (Children.count(i)) | 
 |           // Return a pointer to it. | 
 |           return FirstNode + i; | 
 |       assert(false && "Dereferencing end iterator!"); | 
 |       return 0; // Avoid compiler warning. | 
 |     } | 
 |   }; | 
 |  | 
 |   /// child_begin - Return an iterator pointing to the first child of the given | 
 |   /// node. | 
 |   static ChildIterator child_begin(NodeType *Parent) { | 
 |     return ChildIterator(Parent - Parent->first, Parent->second); | 
 |   } | 
 |  | 
 |   /// child_end - Return the end iterator for children of the given node. | 
 |   static ChildIterator child_end(NodeType *Parent) { | 
 |     return ChildIterator(Parent - Parent->first, NodeSubset()); | 
 |   } | 
 | }; | 
 |  | 
 | template <unsigned N> | 
 | struct GraphTraits<Graph<N> > { | 
 |   typedef typename Graph<N>::NodeType NodeType; | 
 |   typedef typename Graph<N>::ChildIterator ChildIteratorType; | 
 |  | 
 |  static inline NodeType *getEntryNode(const Graph<N> &G) { return G.AccessNode(0); } | 
 |  static inline ChildIteratorType child_begin(NodeType *Node) { | 
 |    return Graph<N>::child_begin(Node); | 
 |  } | 
 |  static inline ChildIteratorType child_end(NodeType *Node) { | 
 |    return Graph<N>::child_end(Node); | 
 |  } | 
 | }; | 
 |  | 
 | TEST(SCCIteratorTest, AllSmallGraphs) { | 
 |   // Test SCC computation against every graph with NUM_NODES nodes or less. | 
 |   // Since SCC considers every node to have an implicit self-edge, we only | 
 |   // create graphs for which every node has a self-edge. | 
 | #define NUM_NODES 4 | 
 | #define NUM_GRAPHS (NUM_NODES * (NUM_NODES - 1)) | 
 |   typedef Graph<NUM_NODES> GT; | 
 |  | 
 |   /// Enumerate all graphs using NUM_GRAPHS bits. | 
 |   assert(NUM_GRAPHS < sizeof(unsigned) * CHAR_BIT && "Too many graphs!"); | 
 |   for (unsigned GraphDescriptor = 0; GraphDescriptor < (1U << NUM_GRAPHS); | 
 |        ++GraphDescriptor) { | 
 |     GT G; | 
 |  | 
 |     // Add edges as specified by the descriptor. | 
 |     unsigned DescriptorCopy = GraphDescriptor; | 
 |     for (unsigned i = 0; i != NUM_NODES; ++i) | 
 |       for (unsigned j = 0; j != NUM_NODES; ++j) { | 
 |         // Always add a self-edge. | 
 |         if (i == j) { | 
 |           G.AddEdge(i, j); | 
 |           continue; | 
 |         } | 
 |         if (DescriptorCopy & 1) | 
 |           G.AddEdge(i, j); | 
 |         DescriptorCopy >>= 1; | 
 |       } | 
 |  | 
 |     // Test the SCC logic on this graph. | 
 |  | 
 |     /// NodesInSomeSCC - Those nodes which are in some SCC. | 
 |     GT::NodeSubset NodesInSomeSCC; | 
 |  | 
 |     for (scc_iterator<GT> I = scc_begin(G), E = scc_end(G); I != E; ++I) { | 
 |       std::vector<GT::NodeType*> &SCC = *I; | 
 |  | 
 |       // Get the nodes in this SCC as a NodeSubset rather than a vector. | 
 |       GT::NodeSubset NodesInThisSCC; | 
 |       for (unsigned i = 0, e = SCC.size(); i != e; ++i) | 
 |         NodesInThisSCC.AddNode(SCC[i]->first); | 
 |  | 
 |       // There should be at least one node in every SCC. | 
 |       EXPECT_FALSE(NodesInThisSCC.isEmpty()); | 
 |  | 
 |       // Check that every node in the SCC is reachable from every other node in | 
 |       // the SCC. | 
 |       for (unsigned i = 0; i != NUM_NODES; ++i) | 
 |         if (NodesInThisSCC.count(i)) | 
 |           EXPECT_TRUE(NodesInThisSCC.isSubsetOf(G.NodesReachableFrom(i))); | 
 |  | 
 |       // OK, now that we now that every node in the SCC is reachable from every | 
 |       // other, this means that the set of nodes reachable from any node in the | 
 |       // SCC is the same as the set of nodes reachable from every node in the | 
 |       // SCC.  Check that for every node N not in the SCC but reachable from the | 
 |       // SCC, no element of the SCC is reachable from N. | 
 |       for (unsigned i = 0; i != NUM_NODES; ++i) | 
 |         if (NodesInThisSCC.count(i)) { | 
 |           GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i); | 
 |           GT::NodeSubset ReachableButNotInSCC = | 
 |             NodesReachableFromSCC.Meet(NodesInThisSCC.Complement()); | 
 |  | 
 |           for (unsigned j = 0; j != NUM_NODES; ++j) | 
 |             if (ReachableButNotInSCC.count(j)) | 
 |               EXPECT_TRUE(G.NodesReachableFrom(j).Meet(NodesInThisSCC).isEmpty()); | 
 |  | 
 |           // The result must be the same for all other nodes in this SCC, so | 
 |           // there is no point in checking them. | 
 |           break; | 
 |         } | 
 |  | 
 |       // This is indeed a SCC: a maximal set of nodes for which each node is | 
 |       // reachable from every other. | 
 |  | 
 |       // Check that we didn't already see this SCC. | 
 |       EXPECT_TRUE(NodesInSomeSCC.Meet(NodesInThisSCC).isEmpty()); | 
 |  | 
 |       NodesInSomeSCC = NodesInSomeSCC.Join(NodesInThisSCC); | 
 |  | 
 |       // Check a property that is specific to the LLVM SCC iterator and | 
 |       // guaranteed by it: if a node in SCC S1 has an edge to a node in | 
 |       // SCC S2, then S1 is visited *after* S2.  This means that the set | 
 |       // of nodes reachable from this SCC must be contained either in the | 
 |       // union of this SCC and all previously visited SCC's. | 
 |  | 
 |       for (unsigned i = 0; i != NUM_NODES; ++i) | 
 |         if (NodesInThisSCC.count(i)) { | 
 |           GT::NodeSubset NodesReachableFromSCC = G.NodesReachableFrom(i); | 
 |           EXPECT_TRUE(NodesReachableFromSCC.isSubsetOf(NodesInSomeSCC)); | 
 |           // The result must be the same for all other nodes in this SCC, so | 
 |           // there is no point in checking them. | 
 |           break; | 
 |         } | 
 |     } | 
 |  | 
 |     // Finally, check that the nodes in some SCC are exactly those that are | 
 |     // reachable from the initial node. | 
 |     EXPECT_EQ(NodesInSomeSCC, G.NodesReachableFrom(0)); | 
 |   } | 
 | } | 
 |  | 
 | } |