File indexing completed on 2026-05-10 08:43:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_ADT_EQUIVALENCECLASSES_H
0016 #define LLVM_ADT_EQUIVALENCECLASSES_H
0017
0018 #include <cassert>
0019 #include <cstddef>
0020 #include <cstdint>
0021 #include <iterator>
0022 #include <set>
0023
0024 namespace llvm {
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 template <class ElemTy, class Compare = std::less<ElemTy>>
0060 class EquivalenceClasses {
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071 class ECValue {
0072 friend class EquivalenceClasses;
0073
0074 mutable const ECValue *Leader, *Next;
0075 ElemTy Data;
0076
0077
0078
0079 ECValue(const ElemTy &Elt)
0080 : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {}
0081
0082 const ECValue *getLeader() const {
0083 if (isLeader()) return this;
0084 if (Leader->isLeader()) return Leader;
0085
0086 return Leader = Leader->getLeader();
0087 }
0088
0089 const ECValue *getEndOfList() const {
0090 assert(isLeader() && "Cannot get the end of a list for a non-leader!");
0091 return Leader;
0092 }
0093
0094 void setNext(const ECValue *NewNext) const {
0095 assert(getNext() == nullptr && "Already has a next pointer!");
0096 Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader());
0097 }
0098
0099 public:
0100 ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1),
0101 Data(RHS.Data) {
0102
0103 assert(RHS.isLeader() && RHS.getNext() == nullptr && "Not a singleton!");
0104 }
0105
0106 bool isLeader() const { return (intptr_t)Next & 1; }
0107 const ElemTy &getData() const { return Data; }
0108
0109 const ECValue *getNext() const {
0110 return (ECValue*)((intptr_t)Next & ~(intptr_t)1);
0111 }
0112 };
0113
0114
0115 struct ECValueComparator {
0116 using is_transparent = void;
0117
0118 ECValueComparator() : compare(Compare()) {}
0119
0120 bool operator()(const ECValue &lhs, const ECValue &rhs) const {
0121 return compare(lhs.Data, rhs.Data);
0122 }
0123
0124 template <typename T>
0125 bool operator()(const T &lhs, const ECValue &rhs) const {
0126 return compare(lhs, rhs.Data);
0127 }
0128
0129 template <typename T>
0130 bool operator()(const ECValue &lhs, const T &rhs) const {
0131 return compare(lhs.Data, rhs);
0132 }
0133
0134 const Compare compare;
0135 };
0136
0137
0138
0139 std::set<ECValue, ECValueComparator> TheMapping;
0140
0141 public:
0142 EquivalenceClasses() = default;
0143 EquivalenceClasses(const EquivalenceClasses &RHS) {
0144 operator=(RHS);
0145 }
0146
0147 const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) {
0148 TheMapping.clear();
0149 for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I)
0150 if (I->isLeader()) {
0151 member_iterator MI = RHS.member_begin(I);
0152 member_iterator LeaderIt = member_begin(insert(*MI));
0153 for (++MI; MI != member_end(); ++MI)
0154 unionSets(LeaderIt, member_begin(insert(*MI)));
0155 }
0156 return *this;
0157 }
0158
0159
0160
0161
0162
0163
0164 using iterator =
0165 typename std::set<ECValue, ECValueComparator>::const_iterator;
0166
0167 iterator begin() const { return TheMapping.begin(); }
0168 iterator end() const { return TheMapping.end(); }
0169
0170 bool empty() const { return TheMapping.empty(); }
0171
0172
0173 class member_iterator;
0174 member_iterator member_begin(iterator I) const {
0175
0176 return member_iterator(I->isLeader() ? &*I : nullptr);
0177 }
0178 member_iterator member_end() const {
0179 return member_iterator(nullptr);
0180 }
0181
0182
0183
0184 iterator findValue(const ElemTy &V) const {
0185 return TheMapping.find(V);
0186 }
0187
0188
0189
0190
0191 const ElemTy &getLeaderValue(const ElemTy &V) const {
0192 member_iterator MI = findLeader(V);
0193 assert(MI != member_end() && "Value is not in the set!");
0194 return *MI;
0195 }
0196
0197
0198
0199
0200 const ElemTy &getOrInsertLeaderValue(const ElemTy &V) {
0201 member_iterator MI = findLeader(insert(V));
0202 assert(MI != member_end() && "Value is not in the set!");
0203 return *MI;
0204 }
0205
0206
0207
0208 unsigned getNumClasses() const {
0209 unsigned NC = 0;
0210 for (iterator I = begin(), E = end(); I != E; ++I)
0211 if (I->isLeader()) ++NC;
0212 return NC;
0213 }
0214
0215
0216
0217
0218
0219
0220 iterator insert(const ElemTy &Data) {
0221 return TheMapping.insert(ECValue(Data)).first;
0222 }
0223
0224
0225
0226
0227
0228 member_iterator findLeader(iterator I) const {
0229 if (I == TheMapping.end()) return member_end();
0230 return member_iterator(I->getLeader());
0231 }
0232 member_iterator findLeader(const ElemTy &V) const {
0233 return findLeader(TheMapping.find(V));
0234 }
0235
0236
0237
0238 member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) {
0239 iterator V1I = insert(V1), V2I = insert(V2);
0240 return unionSets(findLeader(V1I), findLeader(V2I));
0241 }
0242 member_iterator unionSets(member_iterator L1, member_iterator L2) {
0243 assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!");
0244 if (L1 == L2) return L1;
0245
0246
0247
0248 const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node;
0249 L1LV.getEndOfList()->setNext(&L2LV);
0250
0251
0252 L1LV.Leader = L2LV.getEndOfList();
0253
0254
0255 L2LV.Next = L2LV.getNext();
0256
0257
0258 L2LV.Leader = &L1LV;
0259 return L1;
0260 }
0261
0262
0263
0264 bool isEquivalent(const ElemTy &V1, const ElemTy &V2) const {
0265
0266 if (V1 == V2)
0267 return true;
0268 auto It = findLeader(V1);
0269 return It != member_end() && It == findLeader(V2);
0270 }
0271
0272 class member_iterator {
0273 friend class EquivalenceClasses;
0274
0275 const ECValue *Node;
0276
0277 public:
0278 using iterator_category = std::forward_iterator_tag;
0279 using value_type = const ElemTy;
0280 using size_type = std::size_t;
0281 using difference_type = std::ptrdiff_t;
0282 using pointer = value_type *;
0283 using reference = value_type &;
0284
0285 explicit member_iterator() = default;
0286 explicit member_iterator(const ECValue *N) : Node(N) {}
0287
0288 reference operator*() const {
0289 assert(Node != nullptr && "Dereferencing end()!");
0290 return Node->getData();
0291 }
0292 pointer operator->() const { return &operator*(); }
0293
0294 member_iterator &operator++() {
0295 assert(Node != nullptr && "++'d off the end of the list!");
0296 Node = Node->getNext();
0297 return *this;
0298 }
0299
0300 member_iterator operator++(int) {
0301 member_iterator tmp = *this;
0302 ++*this;
0303 return tmp;
0304 }
0305
0306 bool operator==(const member_iterator &RHS) const {
0307 return Node == RHS.Node;
0308 }
0309 bool operator!=(const member_iterator &RHS) const {
0310 return Node != RHS.Node;
0311 }
0312 };
0313 };
0314
0315 }
0316
0317 #endif