@@ -28,6 +28,90 @@ namespace presburger {
28
28
// / as relations with zero domain vars.
29
29
enum class VarKind { Symbol, Local, Domain, Range, SetDim = Range };
30
30
31
+ // / An Identifier stores a pointer to an object, such as a Value or an
32
+ // / Operation. Identifiers are intended to be attached to a variable in a
33
+ // / PresburgerSpace and can be used to check if two variables correspond to the
34
+ // / same object.
35
+ // /
36
+ // / Take for example the following code:
37
+ // /
38
+ // / for i = 0 to 100
39
+ // / for j = 0 to 100
40
+ // / S0: A[j] = 0
41
+ // / for k = 0 to 100
42
+ // / S1: A[k] = 1
43
+ // /
44
+ // / If we represent the space of iteration variables surrounding S0, S1 we have:
45
+ // / space(S0): {d0, d1}
46
+ // / space(S1): {d0, d1}
47
+ // /
48
+ // / Since the variables are in different spaces, without an identifier, there
49
+ // / is no way to distinguish if the variables in the two spaces correspond to
50
+ // / different SSA values in the program. So, we attach an Identifier
51
+ // / corresponding to the loop iteration variable to them. Now,
52
+ // /
53
+ // / space(S0) = {d0(id = i), d1(id = j)}
54
+ // / space(S1) = {d0(id = i), d1(id = k)}.
55
+ // /
56
+ // / Using the identifier, we can check that the first iteration variable in
57
+ // / both the spaces correspond to the same variable in the program, while they
58
+ // / are different for second iteration variable.
59
+ // /
60
+ // / The equality of Identifiers is checked by comparing the stored pointers.
61
+ // / Checking equality asserts that the type of the equal identifiers is same.
62
+ // / Identifiers storing null pointers are treated as having no attachment and
63
+ // / are considered unequal to any other identifier, including other identifiers
64
+ // / with no attachments.
65
+ // /
66
+ // / The type of the pointer stored must have an `llvm::PointerLikeTypeTraits`
67
+ // / specialization.
68
+ class Identifier {
69
+ public:
70
+ Identifier () = default ;
71
+
72
+ // Create an identifier from a pointer.
73
+ template <typename T>
74
+ explicit Identifier (T value)
75
+ : value(llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(value)) {
76
+ #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
77
+ idType = TypeID::get<T>();
78
+ #endif
79
+ }
80
+
81
+ // / Get the value of the identifier casted to type `T`. `T` here should match
82
+ // / the type of the identifier used to create it.
83
+ template <typename T>
84
+ T getValue () const {
85
+ #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
86
+ assert (TypeID::get<T>() == idType &&
87
+ " Identifier was initialized with a different type than the one used "
88
+ " to retrieve it." );
89
+ #endif
90
+ return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer (value);
91
+ }
92
+
93
+ bool hasValue () const { return value != nullptr ; }
94
+
95
+ // / Check if the two identifiers are equal. Null identifiers are considered
96
+ // / not equal. Asserts if two identifiers are equal but their types are not.
97
+ bool isEqual (const Identifier &other) const ;
98
+
99
+ bool operator ==(const Identifier &other) const { return isEqual (other); }
100
+ bool operator !=(const Identifier &other) const { return !isEqual (other); }
101
+
102
+ void print (llvm::raw_ostream &os) const ;
103
+ void dump () const ;
104
+
105
+ private:
106
+ // / The value of the identifier.
107
+ void *value = nullptr ;
108
+
109
+ #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
110
+ // / TypeID of the identifiers in space. This should be used in asserts only.
111
+ TypeID idType = TypeID::get<void >();
112
+ #endif
113
+ };
114
+
31
115
// / PresburgerSpace is the space of all possible values of a tuple of integer
32
116
// / valued variables/variables. Each variable has one of the three types:
33
117
// /
@@ -66,14 +150,12 @@ enum class VarKind { Symbol, Local, Domain, Range, SetDim = Range };
66
150
// / other than Locals are equal. Equality of two spaces implies that number of
67
151
// / variables of each kind are equal.
68
152
// /
69
- // / PresburgerSpace optionally also supports attaching some information to each
70
- // / variable in space, called "identifier" of that variable. `resetIds<IdType>`
71
- // / is used to enable/reset these identifiers. All identifiers must be of the
72
- // / same type, `IdType`. `IdType` must have a `llvm::PointerLikeTypeTraits`
73
- // / specialization available and should be supported via `mlir::TypeID`.
74
- // /
75
- // / These identifiers can be used to check if two variables in two different
76
- // / spaces are actually same variable.
153
+ // / PresburgerSpace optionally also supports attaching an Identifier with each
154
+ // / non-local variable in the space. This is disabled by default. `resetIds` is
155
+ // / used to enable/reset these identifiers. The user can identify each variable
156
+ // / in the space as corresponding to some Identifier. Some example use cases
157
+ // / are described in the `Identifier` documentation above. The type attached to
158
+ // / the Identifier can be different for different variables in the space.
77
159
class PresburgerSpace {
78
160
public:
79
161
static PresburgerSpace getRelationSpace (unsigned numDomain = 0 ,
@@ -142,6 +224,20 @@ class PresburgerSpace {
142
224
// / varLimit). The range is relative to the kind of variable.
143
225
void removeVarRange (VarKind kind, unsigned varStart, unsigned varLimit);
144
226
227
+ // / Converts variables of the specified kind in the column range [srcPos,
228
+ // / srcPos + num) to variables of the specified kind at position dstPos. The
229
+ // / ranges are relative to the kind of variable.
230
+ // /
231
+ // / srcKind and dstKind must be different.
232
+ void convertVarKind (VarKind srcKind, unsigned srcPos, unsigned num,
233
+ VarKind dstKind, unsigned dstPos);
234
+
235
+ // / Changes the partition between dimensions and symbols. Depending on the new
236
+ // / symbol count, either a chunk of dimensional variables immediately before
237
+ // / the split become symbols, or some of the symbols immediately after the
238
+ // / split become dimensions.
239
+ void setVarSymbolSeperation (unsigned newSymbolCount);
240
+
145
241
// / Swaps the posA^th variable of kindA and posB^th variable of kindB.
146
242
void swapVar (VarKind kindA, VarKind kindB, unsigned posA, unsigned posB);
147
243
@@ -154,77 +250,29 @@ class PresburgerSpace {
154
250
// / locals).
155
251
bool isEqual (const PresburgerSpace &other) const ;
156
252
157
- // / Changes the partition between dimensions and symbols. Depending on the new
158
- // / symbol count, either a chunk of dimensional variables immediately before
159
- // / the split become symbols, or some of the symbols immediately after the
160
- // / split become dimensions.
161
- void setVarSymbolSeperation (unsigned newSymbolCount);
162
-
163
- void print (llvm::raw_ostream &os) const ;
164
- void dump () const ;
165
-
166
- // ===--------------------------------------------------------------------===//
167
- // Identifier Interactions
168
- // ===--------------------------------------------------------------------===//
169
-
170
- // / Set the identifier for `i^th` variable to `id`. `T` here should match the
171
- // / type used to enable identifiers.
172
- template <typename T>
173
- void setId (VarKind kind, unsigned i, T id) {
174
- #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
175
- assert (TypeID::get<T>() == idType && " Type mismatch" );
176
- #endif
177
- atId (kind, i) = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer (id);
178
- }
179
-
180
- // / Get the identifier for `i^th` variable casted to type `T`. `T` here
181
- // / should match the type used to enable identifiers.
182
- template <typename T>
183
- T getId (VarKind kind, unsigned i) const {
184
- #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
185
- assert (TypeID::get<T>() == idType && " Type mismatch" );
186
- #endif
187
- return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer (atId (kind, i));
253
+ // / Get the identifier of the specified variable.
254
+ Identifier &getId (VarKind kind, unsigned pos) {
255
+ assert (kind != VarKind::Local && " Local variables have no identifiers" );
256
+ return identifiers[getVarKindOffset (kind) + pos];
188
257
}
189
-
190
- // / Check if the i^th variable of the specified kind has a non-null
191
- // / identifier.
192
- bool hasId (VarKind kind, unsigned i) const {
193
- return atId (kind, i) != nullptr ;
258
+ Identifier getId (VarKind kind, unsigned pos) const {
259
+ assert (kind != VarKind::Local && " Local variables have no identifiers" );
260
+ return identifiers[getVarKindOffset (kind) + pos];
194
261
}
195
262
196
- // / Check if the spaces are compatible, as well as have the same identifiers
197
- // / for each variable.
198
- bool isAligned (const PresburgerSpace &other) const ;
199
- // / Check if the number of variables of the specified kind match, and have
200
- // / same identifiers with the other space.
201
- bool isAligned (const PresburgerSpace &other, VarKind kind) const ;
202
-
203
- // / Find the variable of the specified kind with identifier `id`.
204
- // / Returns PresburgerSpace::kIdNotFound if identifier is not found.
205
- template <typename T>
206
- unsigned findId (VarKind kind, T id) const {
207
- unsigned i = 0 ;
208
- for (unsigned e = getNumVarKind (kind); i < e; ++i)
209
- if (hasId (kind, i) && getId<T>(kind, i) == id)
210
- return i;
211
- return kIdNotFound ;
263
+ ArrayRef<Identifier> getIds (VarKind kind) const {
264
+ assert (kind != VarKind::Local && " Local variables have no identifiers" );
265
+ return {identifiers.data () + getVarKindOffset (kind), getNumVarKind (kind)};
212
266
}
213
- static const unsigned kIdNotFound = UINT_MAX;
214
267
215
268
// / Returns if identifiers are being used.
216
269
bool isUsingIds () const { return usingIds; }
217
270
218
271
// / Reset the stored identifiers in the space. Enables `usingIds` if it was
219
272
// / `false` before.
220
- template <typename T>
221
273
void resetIds () {
222
274
identifiers.clear ();
223
275
identifiers.resize (getNumDimAndSymbolVars ());
224
- #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
225
- idType = TypeID::get<T>();
226
- #endif
227
-
228
276
usingIds = true ;
229
277
}
230
278
@@ -234,26 +282,23 @@ class PresburgerSpace {
234
282
usingIds = false ;
235
283
}
236
284
285
+ // / Check if the spaces are compatible, and the non-local variables having
286
+ // / same identifiers are in the same positions. If the space is not using
287
+ // / Identifiers, this check is same as isCompatible.
288
+ bool isAligned (const PresburgerSpace &other) const ;
289
+ // / Same as above but only check the specified VarKind. Useful to check if
290
+ // / the symbols in two spaces are aligned.
291
+ bool isAligned (const PresburgerSpace &other, VarKind kind) const ;
292
+
293
+ void print (llvm::raw_ostream &os) const ;
294
+ void dump () const ;
295
+
237
296
protected:
238
- PresburgerSpace (unsigned numDomain = 0 , unsigned numRange = 0 ,
239
- unsigned numSymbols = 0 , unsigned numLocals = 0 )
297
+ PresburgerSpace (unsigned numDomain, unsigned numRange, unsigned numSymbols ,
298
+ unsigned numLocals)
240
299
: numDomain(numDomain), numRange(numRange), numSymbols(numSymbols),
241
300
numLocals (numLocals) {}
242
301
243
- void *&atId (VarKind kind, unsigned i) {
244
- assert (usingIds && " Cannot access identifiers when `usingIds` is false." );
245
- assert (kind != VarKind::Local &&
246
- " Local variables cannot have identifiers." );
247
- return identifiers[getVarKindOffset (kind) + i];
248
- }
249
-
250
- void *atId (VarKind kind, unsigned i) const {
251
- assert (usingIds && " Cannot access identifiers when `usingIds` is false." );
252
- assert (kind != VarKind::Local &&
253
- " Local variables cannot have identifiers." );
254
- return identifiers[getVarKindOffset (kind) + i];
255
- }
256
-
257
302
private:
258
303
// Number of variables corresponding to domain variables.
259
304
unsigned numDomain;
@@ -272,13 +317,8 @@ class PresburgerSpace {
272
317
// / Stores whether or not identifiers are being used in this space.
273
318
bool usingIds = false ;
274
319
275
- #ifdef LLVM_ENABLE_ABI_BREAKING_CHECKS
276
- // / TypeID of the identifiers in space. This should be used in asserts only.
277
- TypeID idType;
278
- #endif
279
-
280
320
// / Stores an identifier for each non-local variable as a `void` pointer.
281
- SmallVector<void * , 0 > identifiers;
321
+ SmallVector<Identifier , 0 > identifiers;
282
322
};
283
323
284
324
} // namespace presburger
0 commit comments