EquivalenceClasses.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. //===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===//
  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. // Generic implementation of equivalence classes through the use Tarjan's
  11. // efficient union-find algorithm.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_ADT_EQUIVALENCECLASSES_H
  15. #define LLVM_ADT_EQUIVALENCECLASSES_H
  16. #include "llvm/Support/DataTypes.h"
  17. #include <cassert>
  18. #include <cstddef>
  19. #include <set>
  20. namespace llvm {
  21. /// EquivalenceClasses - This represents a collection of equivalence classes and
  22. /// supports three efficient operations: insert an element into a class of its
  23. /// own, union two classes, and find the class for a given element. In
  24. /// addition to these modification methods, it is possible to iterate over all
  25. /// of the equivalence classes and all of the elements in a class.
  26. ///
  27. /// This implementation is an efficient implementation that only stores one copy
  28. /// of the element being indexed per entry in the set, and allows any arbitrary
  29. /// type to be indexed (as long as it can be ordered with operator<).
  30. ///
  31. /// Here is a simple example using integers:
  32. ///
  33. /// \code
  34. /// EquivalenceClasses<int> EC;
  35. /// EC.unionSets(1, 2); // insert 1, 2 into the same set
  36. /// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets
  37. /// EC.unionSets(5, 1); // merge the set for 1 with 5's set.
  38. ///
  39. /// for (EquivalenceClasses<int>::iterator I = EC.begin(), E = EC.end();
  40. /// I != E; ++I) { // Iterate over all of the equivalence sets.
  41. /// if (!I->isLeader()) continue; // Ignore non-leader sets.
  42. /// for (EquivalenceClasses<int>::member_iterator MI = EC.member_begin(I);
  43. /// MI != EC.member_end(); ++MI) // Loop over members in this set.
  44. /// cerr << *MI << " "; // Print member.
  45. /// cerr << "\n"; // Finish set.
  46. /// }
  47. /// \endcode
  48. ///
  49. /// This example prints:
  50. /// 4
  51. /// 5 1 2
  52. ///
  53. template <class ElemTy>
  54. class EquivalenceClasses {
  55. /// ECValue - The EquivalenceClasses data structure is just a set of these.
  56. /// Each of these represents a relation for a value. First it stores the
  57. /// value itself, which provides the ordering that the set queries. Next, it
  58. /// provides a "next pointer", which is used to enumerate all of the elements
  59. /// in the unioned set. Finally, it defines either a "end of list pointer" or
  60. /// "leader pointer" depending on whether the value itself is a leader. A
  61. /// "leader pointer" points to the node that is the leader for this element,
  62. /// if the node is not a leader. A "end of list pointer" points to the last
  63. /// node in the list of members of this list. Whether or not a node is a
  64. /// leader is determined by a bit stolen from one of the pointers.
  65. class ECValue {
  66. friend class EquivalenceClasses;
  67. mutable const ECValue *Leader, *Next;
  68. ElemTy Data;
  69. // ECValue ctor - Start out with EndOfList pointing to this node, Next is
  70. // Null, isLeader = true.
  71. ECValue(const ElemTy &Elt)
  72. : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {}
  73. const ECValue *getLeader() const {
  74. if (isLeader()) return this;
  75. if (Leader->isLeader()) return Leader;
  76. // Path compression.
  77. return Leader = Leader->getLeader();
  78. }
  79. const ECValue *getEndOfList() const {
  80. assert(isLeader() && "Cannot get the end of a list for a non-leader!");
  81. return Leader;
  82. }
  83. void setNext(const ECValue *NewNext) const {
  84. assert(getNext() == nullptr && "Already has a next pointer!");
  85. Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader());
  86. }
  87. public:
  88. ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1),
  89. Data(RHS.Data) {
  90. // Only support copying of singleton nodes.
  91. assert(RHS.isLeader() && RHS.getNext() == nullptr && "Not a singleton!");
  92. }
  93. bool operator<(const ECValue &UFN) const { return Data < UFN.Data; }
  94. bool isLeader() const { return (intptr_t)Next & 1; }
  95. const ElemTy &getData() const { return Data; }
  96. const ECValue *getNext() const {
  97. return (ECValue*)((intptr_t)Next & ~(intptr_t)1);
  98. }
  99. template<typename T>
  100. bool operator<(const T &Val) const { return Data < Val; }
  101. };
  102. /// TheMapping - This implicitly provides a mapping from ElemTy values to the
  103. /// ECValues, it just keeps the key as part of the value.
  104. std::set<ECValue> TheMapping;
  105. public:
  106. EquivalenceClasses() {}
  107. EquivalenceClasses(const EquivalenceClasses &RHS) {
  108. operator=(RHS);
  109. }
  110. const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) {
  111. TheMapping.clear();
  112. for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I)
  113. if (I->isLeader()) {
  114. member_iterator MI = RHS.member_begin(I);
  115. member_iterator LeaderIt = member_begin(insert(*MI));
  116. for (++MI; MI != member_end(); ++MI)
  117. unionSets(LeaderIt, member_begin(insert(*MI)));
  118. }
  119. return *this;
  120. }
  121. //===--------------------------------------------------------------------===//
  122. // Inspection methods
  123. //
  124. /// iterator* - Provides a way to iterate over all values in the set.
  125. typedef typename std::set<ECValue>::const_iterator iterator;
  126. iterator begin() const { return TheMapping.begin(); }
  127. iterator end() const { return TheMapping.end(); }
  128. bool empty() const { return TheMapping.empty(); }
  129. /// member_* Iterate over the members of an equivalence class.
  130. ///
  131. class member_iterator;
  132. member_iterator member_begin(iterator I) const {
  133. // Only leaders provide anything to iterate over.
  134. return member_iterator(I->isLeader() ? &*I : nullptr);
  135. }
  136. member_iterator member_end() const {
  137. return member_iterator(nullptr);
  138. }
  139. /// findValue - Return an iterator to the specified value. If it does not
  140. /// exist, end() is returned.
  141. iterator findValue(const ElemTy &V) const {
  142. return TheMapping.find(V);
  143. }
  144. /// getLeaderValue - Return the leader for the specified value that is in the
  145. /// set. It is an error to call this method for a value that is not yet in
  146. /// the set. For that, call getOrInsertLeaderValue(V).
  147. const ElemTy &getLeaderValue(const ElemTy &V) const {
  148. member_iterator MI = findLeader(V);
  149. assert(MI != member_end() && "Value is not in the set!");
  150. return *MI;
  151. }
  152. /// getOrInsertLeaderValue - Return the leader for the specified value that is
  153. /// in the set. If the member is not in the set, it is inserted, then
  154. /// returned.
  155. const ElemTy &getOrInsertLeaderValue(const ElemTy &V) {
  156. member_iterator MI = findLeader(insert(V));
  157. assert(MI != member_end() && "Value is not in the set!");
  158. return *MI;
  159. }
  160. /// getNumClasses - Return the number of equivalence classes in this set.
  161. /// Note that this is a linear time operation.
  162. unsigned getNumClasses() const {
  163. unsigned NC = 0;
  164. for (iterator I = begin(), E = end(); I != E; ++I)
  165. if (I->isLeader()) ++NC;
  166. return NC;
  167. }
  168. //===--------------------------------------------------------------------===//
  169. // Mutation methods
  170. /// insert - Insert a new value into the union/find set, ignoring the request
  171. /// if the value already exists.
  172. iterator insert(const ElemTy &Data) {
  173. return TheMapping.insert(ECValue(Data)).first;
  174. }
  175. /// findLeader - Given a value in the set, return a member iterator for the
  176. /// equivalence class it is in. This does the path-compression part that
  177. /// makes union-find "union findy". This returns an end iterator if the value
  178. /// is not in the equivalence class.
  179. ///
  180. member_iterator findLeader(iterator I) const {
  181. if (I == TheMapping.end()) return member_end();
  182. return member_iterator(I->getLeader());
  183. }
  184. member_iterator findLeader(const ElemTy &V) const {
  185. return findLeader(TheMapping.find(V));
  186. }
  187. /// union - Merge the two equivalence sets for the specified values, inserting
  188. /// them if they do not already exist in the equivalence set.
  189. member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) {
  190. iterator V1I = insert(V1), V2I = insert(V2);
  191. return unionSets(findLeader(V1I), findLeader(V2I));
  192. }
  193. member_iterator unionSets(member_iterator L1, member_iterator L2) {
  194. assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!");
  195. if (L1 == L2) return L1; // Unifying the same two sets, noop.
  196. // Otherwise, this is a real union operation. Set the end of the L1 list to
  197. // point to the L2 leader node.
  198. const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node;
  199. L1LV.getEndOfList()->setNext(&L2LV);
  200. // Update L1LV's end of list pointer.
  201. L1LV.Leader = L2LV.getEndOfList();
  202. // Clear L2's leader flag:
  203. L2LV.Next = L2LV.getNext();
  204. // L2's leader is now L1.
  205. L2LV.Leader = &L1LV;
  206. return L1;
  207. }
  208. class member_iterator : public std::iterator<std::forward_iterator_tag,
  209. const ElemTy, ptrdiff_t> {
  210. typedef std::iterator<std::forward_iterator_tag,
  211. const ElemTy, ptrdiff_t> super;
  212. const ECValue *Node;
  213. friend class EquivalenceClasses;
  214. public:
  215. typedef size_t size_type;
  216. typedef typename super::pointer pointer;
  217. typedef typename super::reference reference;
  218. explicit member_iterator() {}
  219. explicit member_iterator(const ECValue *N) : Node(N) {}
  220. reference operator*() const {
  221. assert(Node != nullptr && "Dereferencing end()!");
  222. return Node->getData();
  223. }
  224. pointer operator->() const { return &operator*(); }
  225. member_iterator &operator++() {
  226. assert(Node != nullptr && "++'d off the end of the list!");
  227. Node = Node->getNext();
  228. return *this;
  229. }
  230. member_iterator operator++(int) { // postincrement operators.
  231. member_iterator tmp = *this;
  232. ++*this;
  233. return tmp;
  234. }
  235. bool operator==(const member_iterator &RHS) const {
  236. return Node == RHS.Node;
  237. }
  238. bool operator!=(const member_iterator &RHS) const {
  239. return Node != RHS.Node;
  240. }
  241. };
  242. };
  243. } // End llvm namespace
  244. #endif