Skip to content

Commit 24da7fa

Browse files
authored
[MLIR][Presburger] Use Identifiers outside Presburger library (#77316)
The pull request includes the following changes. 1. Refactors the interface to `PresburgerSpace::identifiers` to `setId` and a const `getId`, instead of previous `getId` which returned a mutable reference. `resetIds` does not need to be called to use identifiers, `setId` calls `resetIds` if identifiers are not enabled. 2. Deprecates `FlatAffineRelation` by refactoring all usages of `FlatAffineRelation` to `IntegerRelation`. To achieve this, `FlatAffineRelation::compose` is refactored into `IntegerRelation::mergeAndCompose`. 3. Deletes unneeded overrides of virtual functions `hasConsistentState`, `clearAndCopyFrom` and `fourierMotzkinEliminate` from `FlatLinearValueConstraints` as these were only used through `FlatAffineRelation` and we now use `IntegerRelation`'s member functions instead. 4. Fixes an existing bug in FlatLinearValueConstraints' constructor which caused identifiers set by superclass FlatLinearConstraints' constructor to be erased. 5. Fixes `IntegerRelation::convertVarKind` not preserving identifiers.
1 parent 6870ac2 commit 24da7fa

File tree

12 files changed

+512
-338
lines changed

12 files changed

+512
-338
lines changed

mlir/include/mlir/Analysis/FlatLinearValueConstraints.h

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,10 @@ class FlatLinearConstraints : public presburger::IntegerPolyhedron {
205205
/// where each non-local variable can have an SSA Value attached to it.
206206
class FlatLinearValueConstraints : public FlatLinearConstraints {
207207
public:
208+
/// The SSA Values attached to each non-local variable are stored as
209+
/// identifiers in the constraint system's space.
210+
using Identifier = presburger::Identifier;
211+
208212
/// Constructs a constraint system reserving memory for the specified number
209213
/// of constraints and variables. `valArgs` are the optional SSA values
210214
/// associated with each dimension/symbol. These must either be empty or match
@@ -217,11 +221,9 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
217221
: FlatLinearConstraints(numReservedInequalities, numReservedEqualities,
218222
numReservedCols, numDims, numSymbols, numLocals) {
219223
assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
220-
values.reserve(numReservedCols);
221-
if (valArgs.empty())
222-
values.resize(getNumDimAndSymbolVars(), std::nullopt);
223-
else
224-
values.append(valArgs.begin(), valArgs.end());
224+
for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
225+
if (valArgs[i])
226+
setValue(i, *valArgs[i]);
225227
}
226228

227229
/// Constructs a constraint system reserving memory for the specified number
@@ -236,11 +238,9 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
236238
: FlatLinearConstraints(numReservedInequalities, numReservedEqualities,
237239
numReservedCols, numDims, numSymbols, numLocals) {
238240
assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
239-
values.reserve(numReservedCols);
240-
if (valArgs.empty())
241-
values.resize(getNumDimAndSymbolVars(), std::nullopt);
242-
else
243-
values.append(valArgs.begin(), valArgs.end());
241+
for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
242+
if (valArgs[i])
243+
setValue(i, valArgs[i]);
244244
}
245245

246246
/// Constructs a constraint system with the specified number of dimensions
@@ -272,11 +272,12 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
272272
FlatLinearValueConstraints(const IntegerPolyhedron &fac,
273273
ArrayRef<std::optional<Value>> valArgs = {})
274274
: FlatLinearConstraints(fac) {
275-
assert(valArgs.empty() || valArgs.size() == getNumDimAndSymbolVars());
276275
if (valArgs.empty())
277-
values.resize(getNumDimAndSymbolVars(), std::nullopt);
278-
else
279-
values.append(valArgs.begin(), valArgs.end());
276+
return;
277+
assert(valArgs.size() == getNumDimAndSymbolVars());
278+
for (unsigned i = 0, e = valArgs.size(); i < e; ++i)
279+
if (valArgs[i])
280+
setValue(i, *valArgs[i]);
280281
}
281282

282283
/// Creates an affine constraint system from an IntegerSet.
@@ -290,9 +291,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
290291
cst->getKind() <= Kind::FlatAffineRelation;
291292
}
292293

293-
/// Replaces the contents of this FlatLinearValueConstraints with `other`.
294-
void clearAndCopyFrom(const IntegerRelation &other) override;
295-
296294
/// Adds a constant bound for the variable associated with the given Value.
297295
void addBound(presburger::BoundType type, Value val, int64_t value);
298296
using FlatLinearConstraints::addBound;
@@ -302,7 +300,9 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
302300
inline Value getValue(unsigned pos) const {
303301
assert(pos < getNumDimAndSymbolVars() && "Invalid position");
304302
assert(hasValue(pos) && "variable's Value not set");
305-
return *values[pos];
303+
VarKind kind = getVarKindAt(pos);
304+
unsigned relativePos = pos - getVarKindOffset(kind);
305+
return space.getId(kind, relativePos).getValue<Value>();
306306
}
307307

308308
/// Returns the Values associated with variables in range [start, end).
@@ -313,25 +313,44 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
313313
assert(start <= end && "invalid start position");
314314
values->clear();
315315
values->reserve(end - start);
316-
for (unsigned i = start; i < end; i++)
316+
for (unsigned i = start; i < end; ++i)
317317
values->push_back(getValue(i));
318318
}
319319

320-
inline ArrayRef<std::optional<Value>> getMaybeValues() const {
321-
return {values.data(), values.size()};
320+
inline SmallVector<std::optional<Value>> getMaybeValues() const {
321+
SmallVector<std::optional<Value>> maybeValues;
322+
maybeValues.reserve(getNumDimAndSymbolVars());
323+
for (unsigned i = 0, e = getNumDimAndSymbolVars(); i < e; ++i)
324+
if (hasValue(i)) {
325+
maybeValues.push_back(getValue(i));
326+
} else {
327+
maybeValues.push_back(std::nullopt);
328+
}
329+
return maybeValues;
322330
}
323331

324-
inline ArrayRef<std::optional<Value>>
332+
inline SmallVector<std::optional<Value>>
325333
getMaybeValues(presburger::VarKind kind) const {
326334
assert(kind != VarKind::Local &&
327335
"Local variables do not have any value attached to them.");
328-
return {values.data() + getVarKindOffset(kind), getNumVarKind(kind)};
336+
SmallVector<std::optional<Value>> maybeValues;
337+
maybeValues.reserve(getNumVarKind(kind));
338+
const unsigned offset = space.getVarKindOffset(kind);
339+
for (unsigned i = 0, e = getNumVarKind(kind); i < e; ++i) {
340+
if (hasValue(offset + i))
341+
maybeValues.push_back(getValue(offset + i));
342+
else
343+
maybeValues.push_back(std::nullopt);
344+
}
345+
return maybeValues;
329346
}
330347

331348
/// Returns true if the pos^th variable has an associated Value.
332349
inline bool hasValue(unsigned pos) const {
333350
assert(pos < getNumDimAndSymbolVars() && "Invalid position");
334-
return values[pos].has_value();
351+
VarKind kind = getVarKindAt(pos);
352+
unsigned relativePos = pos - getVarKindOffset(kind);
353+
return space.getId(kind, relativePos).hasValue();
335354
}
336355

337356
unsigned appendDimVar(ValueRange vals);
@@ -358,9 +377,12 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
358377
using IntegerPolyhedron::removeVarRange;
359378

360379
/// Sets the Value associated with the pos^th variable.
380+
/// Stores the Value in the space's identifiers.
361381
inline void setValue(unsigned pos, Value val) {
362382
assert(pos < getNumDimAndSymbolVars() && "invalid var position");
363-
values[pos] = val;
383+
VarKind kind = getVarKindAt(pos);
384+
unsigned relativePos = pos - getVarKindOffset(kind);
385+
space.setId(kind, relativePos, presburger::Identifier(val));
364386
}
365387

366388
/// Sets the Values associated with the variables in the range [start, end).
@@ -387,9 +409,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
387409
void projectOut(Value val);
388410
using IntegerPolyhedron::projectOut;
389411

390-
/// Swap the posA^th variable with the posB^th variable.
391-
void swapVar(unsigned posA, unsigned posB) override;
392-
393412
/// Prints the number of constraints, dimensions, symbols and locals in the
394413
/// FlatAffineValueConstraints. Also, prints for each variable whether there
395414
/// is an SSA Value attached to it.
@@ -444,28 +463,6 @@ class FlatLinearValueConstraints : public FlatLinearConstraints {
444463
/// output = {0 <= d0 <= 6, 1 <= d1 <= 15}
445464
LogicalResult unionBoundingBox(const FlatLinearValueConstraints &other);
446465
using IntegerPolyhedron::unionBoundingBox;
447-
448-
protected:
449-
/// Eliminates the variable at the specified position using Fourier-Motzkin
450-
/// variable elimination, but uses Gaussian elimination if there is an
451-
/// equality involving that variable. If the result of the elimination is
452-
/// integer exact, `*isResultIntegerExact` is set to true. If `darkShadow` is
453-
/// set to true, a potential under approximation (subset) of the rational
454-
/// shadow / exact integer shadow is computed.
455-
// See implementation comments for more details.
456-
void fourierMotzkinEliminate(unsigned pos, bool darkShadow = false,
457-
bool *isResultIntegerExact = nullptr) override;
458-
459-
/// Returns false if the fields corresponding to various variable counts, or
460-
/// equality/inequality buffer sizes aren't consistent; true otherwise. This
461-
/// is meant to be used within an assert internally.
462-
bool hasConsistentState() const override;
463-
464-
/// Values corresponding to the (column) non-local variables of this
465-
/// constraint system appearing in the order the variables correspond to
466-
/// columns. Variables that aren't associated with any Value are set to
467-
/// std::nullopt.
468-
SmallVector<std::optional<Value>, 8> values;
469466
};
470467

471468
/// Flattens 'expr' into 'flattenedExpr', which contains the coefficients of the

mlir/include/mlir/Analysis/Presburger/IntegerRelation.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ class IntegerRelation {
127127
/// the variable.
128128
void setId(VarKind kind, unsigned i, Identifier id);
129129

130+
void resetIds() { space.resetIds(); }
131+
132+
/// Get the identifiers for the variables of specified varKind. Calls resetIds
133+
/// on the relations space if identifiers are not enabled.
134+
ArrayRef<Identifier> getIds(VarKind kind);
135+
130136
/// Returns a copy of the space without locals.
131137
PresburgerSpace getSpaceWithoutLocals() const {
132138
return PresburgerSpace::getRelationSpace(space.getNumDomainVars(),
@@ -674,6 +680,11 @@ class IntegerRelation {
674680
/// this for uniformity with `applyDomain`.
675681
void applyRange(const IntegerRelation &rel);
676682

683+
/// Given a relation `other: (A -> B)`, this operation merges the symbol and
684+
/// local variables and then takes the composition of `other` on `this: (B ->
685+
/// C)`. The resulting relation represents tuples of the form: `A -> C`.
686+
void mergeAndCompose(const IntegerRelation &other);
687+
677688
/// Compute an equivalent representation of the same set, such that all local
678689
/// vars in all disjuncts have division representations. This representation
679690
/// may involve local vars that correspond to divisions, and may also be a

mlir/include/mlir/Analysis/Presburger/PresburgerSpace.h

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,21 +250,34 @@ class PresburgerSpace {
250250
/// locals).
251251
bool isEqual(const PresburgerSpace &other) const;
252252

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];
257-
}
253+
/// Get the identifier of pos^th variable of the specified kind.
258254
Identifier getId(VarKind kind, unsigned pos) const {
259255
assert(kind != VarKind::Local && "Local variables have no identifiers");
256+
if (!usingIds)
257+
return Identifier();
260258
return identifiers[getVarKindOffset(kind) + pos];
261259
}
262260

263261
ArrayRef<Identifier> getIds(VarKind kind) const {
264262
assert(kind != VarKind::Local && "Local variables have no identifiers");
263+
assert(usingIds && "Identifiers not enabled for space");
265264
return {identifiers.data() + getVarKindOffset(kind), getNumVarKind(kind)};
266265
}
267266

267+
ArrayRef<Identifier> getIds() const {
268+
assert(usingIds && "Identifiers not enabled for space");
269+
return identifiers;
270+
}
271+
272+
/// Set the identifier of pos^th variable of the specified kind. Calls
273+
/// resetIds if identifiers are not enabled.
274+
void setId(VarKind kind, unsigned pos, Identifier id) {
275+
assert(kind != VarKind::Local && "Local variables have no identifiers");
276+
if (!usingIds)
277+
resetIds();
278+
identifiers[getVarKindOffset(kind) + pos] = id;
279+
}
280+
268281
/// Returns if identifiers are being used.
269282
bool isUsingIds() const { return usingIds; }
270283

mlir/include/mlir/Dialect/Affine/Analysis/AffineAnalysis.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#ifndef MLIR_DIALECT_AFFINE_ANALYSIS_AFFINEANALYSIS_H
1616
#define MLIR_DIALECT_AFFINE_ANALYSIS_AFFINEANALYSIS_H
1717

18+
#include "mlir/Analysis/Presburger/IntegerRelation.h"
1819
#include "mlir/Dialect/Arith/IR/Arith.h"
1920
#include "mlir/IR/Value.h"
2021
#include "llvm/ADT/SmallVector.h"
@@ -115,7 +116,7 @@ struct MemRefAccess {
115116
///
116117
/// Returns failure for yet unimplemented/unsupported cases (see docs of
117118
/// mlir::getIndexSet and mlir::getRelationFromMap for these cases).
118-
LogicalResult getAccessRelation(FlatAffineRelation &accessRel) const;
119+
LogicalResult getAccessRelation(presburger::IntegerRelation &accessRel) const;
119120

120121
/// Populates 'accessMap' with composition of AffineApplyOps reachable from
121122
/// 'indices'.

mlir/include/mlir/Dialect/Affine/Analysis/AffineStructures.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,14 @@ class FlatAffineValueConstraints : public FlatLinearValueConstraints {
154154
/// represented as a FlatAffineValueConstraints with separation of dimension
155155
/// variables into domain and range. The variables are stored as:
156156
/// [domainVars, rangeVars, symbolVars, localVars, constant].
157+
///
158+
/// Deprecated: use IntegerRelation and store SSA Values in the PresburgerSpace
159+
/// of the relation using PresburgerSpace::identifiers. Note that
160+
/// FlatAffineRelation::numDomainDims and FlatAffineRelation::numRangeDims are
161+
/// independent of numDomain and numRange of the relation's space. In
162+
/// particular, operations such as FlatAffineRelation::compose do not ensure
163+
/// consistency between numDomainDims/numRangeDims and numDomain/numRange which
164+
/// may lead to unexpected behaviour.
157165
class FlatAffineRelation : public FlatAffineValueConstraints {
158166
public:
159167
FlatAffineRelation(unsigned numReservedInequalities,
@@ -251,9 +259,10 @@ class FlatAffineRelation : public FlatAffineValueConstraints {
251259
/// For AffineValueMap, the domain and symbols have Value set corresponding to
252260
/// the Value in `map`. Returns failure if the AffineMap could not be flattened
253261
/// (i.e., semi-affine is not yet handled).
254-
LogicalResult getRelationFromMap(AffineMap &map, FlatAffineRelation &rel);
262+
LogicalResult getRelationFromMap(AffineMap &map,
263+
presburger::IntegerRelation &rel);
255264
LogicalResult getRelationFromMap(const AffineValueMap &map,
256-
FlatAffineRelation &rel);
265+
presburger::IntegerRelation &rel);
257266

258267
} // namespace affine
259268
} // namespace mlir

0 commit comments

Comments
 (0)