15
15
#ifndef LLVM_ADT_EQUIVALENCECLASSES_H
16
16
#define LLVM_ADT_EQUIVALENCECLASSES_H
17
17
18
- #include " llvm/ADT/DenseMap.h"
19
- #include " llvm/ADT/SmallVector.h"
18
+ #include " llvm/ADT/SetVector.h"
20
19
#include " llvm/Support/Allocator.h"
21
20
#include < cassert>
22
21
#include < cstddef>
@@ -58,66 +57,101 @@ namespace llvm {
58
57
// / 4
59
58
// / 5 1 2
60
59
// /
61
- template <class ElemTy > class EquivalenceClasses {
62
- // / ECValue - The EquivalenceClasses data structure is just a set of these.
63
- // / Each of these represents a relation for a value. First it stores the
64
- // / value itself, which provides the ordering that the set queries. Next, it
65
- // / provides a "next pointer", which is used to enumerate all of the elements
66
- // / in the unioned set. Finally, it defines either a "end of list pointer" or
67
- // / "leader pointer" depending on whether the value itself is a leader. A
68
- // / "leader pointer" points to the node that is the leader for this element,
69
- // / if the node is not a leader. A "end of list pointer" points to the last
70
- // / node in the list of members of this list. Whether or not a node is a
71
- // / leader is determined by a bit stolen from one of the pointers.
72
- class ECValue {
73
- friend class EquivalenceClasses ;
74
60
75
- mutable const ECValue *Leader, *Next;
76
- ElemTy Data;
61
+ template <class ElemTy > class EquivalenceClasses ;
62
+ // / ECValue - The EquivalenceClasses data structure is just a set of these.
63
+ // / Each of these represents a relation for a value. First it stores the
64
+ // / value itself, which provides the ordering that the set queries. Next, it
65
+ // / provides a "next pointer", which is used to enumerate all of the elements
66
+ // / in the unioned set. Finally, it defines either a "end of list pointer" or
67
+ // / "leader pointer" depending on whether the value itself is a leader. A
68
+ // / "leader pointer" points to the node that is the leader for this element,
69
+ // / if the node is not a leader. A "end of list pointer" points to the last
70
+ // / node in the list of members of this list. Whether or not a node is a
71
+ // / leader is determined by a bit stolen from one of the pointers.
72
+ template <class ElemTy > class ECValue {
73
+ friend class EquivalenceClasses <ElemTy>;
74
+
75
+ mutable const ECValue *Leader, *Next;
76
+ ElemTy Data;
77
+
78
+ // ECValue ctor - Start out with EndOfList pointing to this node, Next is
79
+ // Null, isLeader = true.
80
+ ECValue (const ElemTy &Elt)
81
+ : Leader(this ), Next((ECValue *)(intptr_t )1 ), Data(Elt) {}
82
+
83
+ const ECValue *getLeader () const {
84
+ if (isLeader ())
85
+ return this ;
86
+ if (Leader->isLeader ())
87
+ return Leader;
88
+ // Path compression.
89
+ return Leader = Leader->getLeader ();
90
+ }
77
91
78
- // ECValue ctor - Start out with EndOfList pointing to this node, Next is
79
- // Null, isLeader = true.
80
- ECValue ( const ElemTy &Elt)
81
- : Leader( this ), Next((ECValue*)( intptr_t ) 1 ), Data(Elt) { }
92
+ const ECValue * getEndOfList () const {
93
+ assert ( isLeader () && " Cannot get the end of a list for a non-leader! " );
94
+ return Leader;
95
+ }
82
96
83
- const ECValue *getLeader () const {
84
- if (isLeader ()) return this ;
85
- if (Leader->isLeader ()) return Leader;
86
- // Path compression.
87
- return Leader = Leader->getLeader ();
88
- }
97
+ void setNext (const ECValue *NewNext) const {
98
+ assert (getNext () == nullptr && " Already has a next pointer!" );
99
+ Next = (const ECValue *)((intptr_t )NewNext | (intptr_t )isLeader ());
100
+ }
89
101
90
- const ECValue *getEndOfList () const {
91
- assert (isLeader () && " Cannot get the end of a list for a non-leader!" );
92
- return Leader;
93
- }
102
+ public:
103
+ ECValue (const ECValue &RHS)
104
+ : Leader(this ), Next((ECValue *)(intptr_t )1 ), Data(RHS.Data) {
105
+ // Only support copying of singleton nodes.
106
+ essert (RHS.isLeader () && RHS.getNext () == nullptr && " Not a singleton!" );
107
+ }
94
108
95
- void setNext (const ECValue *NewNext) const {
96
- assert (getNext () == nullptr && " Already has a next pointer!" );
97
- Next = (const ECValue*)((intptr_t )NewNext | (intptr_t )isLeader ());
98
- }
109
+ bool isLeader () const { return (intptr_t )Next & 1 ; }
110
+ const ElemTy &getData () const { return Data; }
99
111
100
- public:
101
- ECValue (const ECValue &RHS) : Leader(this ), Next((ECValue*)(intptr_t )1 ),
102
- Data (RHS.Data) {
103
- // Only support copying of singleton nodes.
104
- assert (RHS.isLeader () && RHS.getNext () == nullptr && " Not a singleton!" );
105
- }
112
+ const ECValue *getNext () const {
113
+ return (ECValue *)((intptr_t )Next & ~(intptr_t )1 );
114
+ }
115
+ };
106
116
107
- bool isLeader () const { return ( intptr_t )Next & 1 ; }
108
- const ElemTy & getData () const { return Data; }
117
+ template < class ElemTy > struct DenseMapInfo <ECValue<ElemTy> *> {
118
+ static constexpr uintptr_t Log2MaxAlign = 12 ;
109
119
110
- const ECValue *getNext () const {
111
- return (ECValue*)((intptr_t )Next & ~(intptr_t )1 );
112
- }
113
- };
120
+ static inline ECValue<ElemTy> *getEmptyKey () {
121
+ uintptr_t Val = static_cast <uintptr_t >(-1 );
122
+ Val <<= Log2MaxAlign;
123
+ return reinterpret_cast <ECValue<ElemTy> *>(Val);
124
+ }
125
+
126
+ static inline ECValue<ElemTy> *getTombstoneKey () {
127
+ uintptr_t Val = static_cast <uintptr_t >(-2 );
128
+ Val <<= Log2MaxAlign;
129
+ return reinterpret_cast <ECValue<ElemTy> *>(Val);
130
+ }
131
+
132
+ static unsigned getHashValue (const ECValue<ElemTy> *PtrVal) {
133
+ return DenseMapInfo<ElemTy>::getHashValue (PtrVal->getData ());
134
+ }
114
135
136
+ static bool isEqual (const ECValue<ElemTy> *LHS, const ECValue<ElemTy> *RHS) {
137
+ if (LHS == RHS)
138
+ return true ;
139
+ if (LHS == getEmptyKey () && RHS != getEmptyKey ())
140
+ return false ;
141
+ if (RHS == getEmptyKey () && LHS != getEmptyKey ())
142
+ return false ;
143
+ if (LHS == getTombstoneKey () && RHS != getTombstoneKey ())
144
+ return false ;
145
+ if (RHS == getTombstoneKey () && LHS != getTombstoneKey ())
146
+ return false ;
147
+ return DenseMapInfo<ElemTy>::isEqual (LHS->getData (), RHS->getData ());
148
+ }
149
+ };
150
+
151
+ template <class ElemTy > class EquivalenceClasses {
115
152
// / TheMapping - This implicitly provides a mapping from ElemTy values to the
116
153
// / ECValues, it just keeps the key as part of the value.
117
- DenseMap<ElemTy, ECValue *> TheMapping;
118
-
119
- // / List of all members, used to provide a determinstic iteration order.
120
- SmallVector<const ECValue *> Members;
154
+ SetVector<ECValue<ElemTy> *> TheMapping;
121
155
122
156
mutable BumpPtrAllocator ECValueAllocator;
123
157
@@ -129,7 +163,6 @@ template <class ElemTy> class EquivalenceClasses {
129
163
130
164
EquivalenceClasses &operator =(const EquivalenceClasses &RHS) {
131
165
TheMapping.clear ();
132
- Members.clear ();
133
166
for (const auto &E : RHS)
134
167
if (E->isLeader ()) {
135
168
member_iterator MI = RHS.member_begin (*E);
@@ -145,16 +178,16 @@ template <class ElemTy> class EquivalenceClasses {
145
178
//
146
179
147
180
// / iterator* - Provides a way to iterate over all values in the set.
148
- using iterator = typename SmallVector< const ECValue *> ::const_iterator;
181
+ using iterator = typename decltype (TheMapping) ::const_iterator;
149
182
150
- iterator begin () const { return Members .begin (); }
151
- iterator end () const { return Members .end (); }
183
+ iterator begin () const { return TheMapping .begin (); }
184
+ iterator end () const { return TheMapping .end (); }
152
185
153
186
bool empty () const { return TheMapping.empty (); }
154
187
155
188
// / member_* Iterate over the members of an equivalence class.
156
189
class member_iterator ;
157
- member_iterator member_begin (const ECValue &ECV) const {
190
+ member_iterator member_begin (const ECValue<ElemTy> &ECV) const {
158
191
// Only leaders provide anything to iterate over.
159
192
return member_iterator (ECV.isLeader () ? &ECV : nullptr );
160
193
}
@@ -165,7 +198,8 @@ template <class ElemTy> class EquivalenceClasses {
165
198
166
199
// / Returns true if \p V is contained an equivalence class.
167
200
bool contains (const ElemTy &V) const {
168
- return TheMapping.find (V) != TheMapping.end ();
201
+ ECValue<ElemTy> Tmp (V);
202
+ return TheMapping.set_find (&Tmp) != TheMapping.set_end ();
169
203
}
170
204
171
205
// / getLeaderValue - Return the leader for the specified value that is in the
@@ -201,14 +235,14 @@ template <class ElemTy> class EquivalenceClasses {
201
235
202
236
// / insert - Insert a new value into the union/find set, ignoring the request
203
237
// / if the value already exists.
204
- const ECValue &insert (const ElemTy &Data) {
205
- auto I = TheMapping. insert ({ Data, nullptr } );
206
- if (!I. second )
207
- return *I. first -> second ;
208
-
209
- auto *ECV = new (ECValueAllocator) ECValue (Data);
210
- I. first -> second = ECV ;
211
- Members. push_back (ECV);
238
+ const ECValue<ElemTy> &insert (const ElemTy &Data) {
239
+ ECValue<ElemTy> Tmp ( Data);
240
+ auto I = TheMapping. set_find (&Tmp);
241
+ if (I != TheMapping. set_end ())
242
+ return **I;
243
+
244
+ auto *ECV = new (ECValueAllocator) ECValue<ElemTy>(Data) ;
245
+ TheMapping. insert (ECV);
212
246
return *ECV;
213
247
}
214
248
@@ -217,19 +251,20 @@ template <class ElemTy> class EquivalenceClasses {
217
251
// / makes union-find "union findy". This returns an end iterator if the value
218
252
// / is not in the equivalence class.
219
253
member_iterator findLeader (const ElemTy &V) const {
220
- auto I = TheMapping.find (V);
221
- if (I == TheMapping.end ())
254
+ ECValue<ElemTy> Tmp (V);
255
+ auto I = TheMapping.set_find (&Tmp);
256
+ if (I == TheMapping.set_end ())
222
257
return member_iterator (nullptr );
223
- return findLeader (*I-> second );
258
+ return findLeader (**I );
224
259
}
225
- member_iterator findLeader (const ECValue &ECV) const {
260
+ member_iterator findLeader (const ECValue<ElemTy> &ECV) const {
226
261
return member_iterator (ECV.getLeader ());
227
262
}
228
263
229
264
// / union - Merge the two equivalence sets for the specified values, inserting
230
265
// / them if they do not already exist in the equivalence set.
231
266
member_iterator unionSets (const ElemTy &V1, const ElemTy &V2) {
232
- const ECValue &V1I = insert (V1), &V2I = insert (V2);
267
+ const ECValue<ElemTy> &V1I = insert (V1), &V2I = insert (V2);
233
268
return unionSets (findLeader (V1I), findLeader (V2I));
234
269
}
235
270
member_iterator unionSets (member_iterator L1, member_iterator L2) {
@@ -238,7 +273,7 @@ template <class ElemTy> class EquivalenceClasses {
238
273
239
274
// Otherwise, this is a real union operation. Set the end of the L1 list to
240
275
// point to the L2 leader node.
241
- const ECValue &L1LV = *L1.Node , &L2LV = *L2.Node ;
276
+ const ECValue<ElemTy> &L1LV = *L1.Node , &L2LV = *L2.Node ;
242
277
L1LV.getEndOfList ()->setNext (&L2LV);
243
278
244
279
// Update L1LV's end of list pointer.
@@ -265,7 +300,7 @@ template <class ElemTy> class EquivalenceClasses {
265
300
class member_iterator {
266
301
friend class EquivalenceClasses ;
267
302
268
- const ECValue *Node;
303
+ const ECValue<ElemTy> *Node;
269
304
270
305
public:
271
306
using iterator_category = std::forward_iterator_tag;
@@ -276,7 +311,7 @@ template <class ElemTy> class EquivalenceClasses {
276
311
using reference = value_type &;
277
312
278
313
explicit member_iterator () = default;
279
- explicit member_iterator (const ECValue *N) : Node(N) {}
314
+ explicit member_iterator (const ECValue<ElemTy> *N) : Node(N) {}
280
315
281
316
reference operator *() const {
282
317
assert (Node != nullptr && " Dereferencing end()!" );
0 commit comments