Skip to content

Commit 13c9d7f

Browse files
[mlir][Interfaces][NFC] ValueBoundsConstraintSet: Add columns for constant values/dims
`ValueBoundsConstraintSet` maintains an internal constraint set (`IntegerRelation`), where every analyzed index-typed SSA value or dimension of a shaped type is represented with a dimension/symbol. Prior to this change, index-typed values with a statically known constant value and static shaped type dimensions were not added to the constraint set. Instead, `getExpr` directly returned an affine constrant expression. With this commit, dynamic and static values/dimension sizes are treated in the same way: in either case, a dimension/symbol is added to the constraint set. This is needed for a subsequent commit that adds support for branches.
1 parent d93cfd8 commit 13c9d7f

File tree

2 files changed

+55
-17
lines changed

2 files changed

+55
-17
lines changed

mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,13 @@ class ValueBoundsConstraintSet {
280280

281281
/// Insert a value/dimension into the constraint set. If `isSymbol` is set to
282282
/// "false", a dimension is added. The value/dimension is added to the
283-
/// worklist.
283+
/// worklist if `addToWorklist` is set.
284284
///
285285
/// Note: There are certain affine restrictions wrt. dimensions. E.g., they
286286
/// cannot be multiplied. Furthermore, bounds can only be queried for
287287
/// dimensions but not for symbols.
288-
int64_t insert(Value value, std::optional<int64_t> dim, bool isSymbol = true);
288+
int64_t insert(Value value, std::optional<int64_t> dim, bool isSymbol = true,
289+
bool addToWorklist = true);
289290

290291
/// Insert an anonymous column into the constraint set. The column is not
291292
/// bound to any value/dimension. If `isSymbol` is set to "false", a dimension

mlir/lib/Interfaces/ValueBoundsOpInterface.cpp

Lines changed: 52 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -105,25 +105,57 @@ AffineExpr ValueBoundsConstraintSet::getExpr(Value value,
105105
assertValidValueDim(value, dim);
106106
#endif // NDEBUG
107107

108+
// Helper function that returns an affine expression that represents column
109+
// `pos` in the constraint set.
110+
auto getPosExpr = [&](int64_t pos) {
111+
assert(pos >= 0 && pos < cstr.getNumDimAndSymbolVars() &&
112+
"invalid position");
113+
return pos < cstr.getNumDimVars()
114+
? builder.getAffineDimExpr(pos)
115+
: builder.getAffineSymbolExpr(pos - cstr.getNumDimVars());
116+
};
117+
118+
// Check if the value/dim is statically known. In that case, an affine
119+
// constant expression should be returned. This allows us to support
120+
// multiplications with constants. (Multiplications of two columns in the
121+
// constraint set is not supported.)
122+
std::optional<int64_t> constSize = std::nullopt;
108123
auto shapedType = dyn_cast<ShapedType>(value.getType());
109124
if (shapedType) {
110-
// Static dimension: return constant directly.
111125
if (shapedType.hasRank() && !shapedType.isDynamicDim(*dim))
112-
return builder.getAffineConstantExpr(shapedType.getDimSize(*dim));
113-
} else {
114-
// Constant index value: return directly.
115-
if (auto constInt = ::getConstantIntValue(value))
116-
return builder.getAffineConstantExpr(*constInt);
126+
constSize = shapedType.getDimSize(*dim);
127+
} else if (auto constInt = ::getConstantIntValue(value)) {
128+
constSize = *constInt;
117129
}
118130

119-
// Dynamic value: add to constraint set.
131+
// If the value/dim is already mapped, return the corresponding expression
132+
// directly.
120133
ValueDim valueDim = std::make_pair(value, dim.value_or(kIndexValue));
121-
if (!valueDimToPosition.contains(valueDim))
122-
(void)insert(value, dim);
123-
int64_t pos = getPos(value, dim);
124-
return pos < cstr.getNumDimVars()
125-
? builder.getAffineDimExpr(pos)
126-
: builder.getAffineSymbolExpr(pos - cstr.getNumDimVars());
134+
if (valueDimToPosition.contains(valueDim)) {
135+
// If it is a constant, return an affine constant expression. Otherwise,
136+
// return an affine expression that represents the respective column in the
137+
// constraint set.
138+
if (constSize)
139+
return builder.getAffineConstantExpr(*constSize);
140+
return getPosExpr(getPos(value, dim));
141+
}
142+
143+
if (constSize) {
144+
// Constant index value/dim: add column to the constraint set, add EQ bound
145+
// and return an affine constant expression without pushing the newly added
146+
// column to the worklist.
147+
(void)insert(value, dim, /*isSymbol=*/true, /*addToWorklist=*/false);
148+
if (shapedType)
149+
bound(value)[*dim] == *constSize;
150+
else
151+
bound(value) == *constSize;
152+
return builder.getAffineConstantExpr(*constSize);
153+
}
154+
155+
// Dynamic value/dim: insert column to the constraint set and put it on the
156+
// worklist. Return an affine expression that represents the newly inserted
157+
// column in the constraint set.
158+
return getPosExpr(insert(value, dim, /*isSymbol=*/true));
127159
}
128160

129161
AffineExpr ValueBoundsConstraintSet::getExpr(OpFoldResult ofr) {
@@ -140,7 +172,7 @@ AffineExpr ValueBoundsConstraintSet::getExpr(int64_t constant) {
140172

141173
int64_t ValueBoundsConstraintSet::insert(Value value,
142174
std::optional<int64_t> dim,
143-
bool isSymbol) {
175+
bool isSymbol, bool addToWorklist) {
144176
#ifndef NDEBUG
145177
assertValidValueDim(value, dim);
146178
#endif // NDEBUG
@@ -155,7 +187,12 @@ int64_t ValueBoundsConstraintSet::insert(Value value,
155187
if (positionToValueDim[i].has_value())
156188
valueDimToPosition[*positionToValueDim[i]] = i;
157189

158-
worklist.push(pos);
190+
if (addToWorklist) {
191+
LLVM_DEBUG(llvm::dbgs() << "Push to worklist: " << value
192+
<< " (dim: " << dim.value_or(kIndexValue) << ")\n");
193+
worklist.push(pos);
194+
}
195+
159196
return pos;
160197
}
161198

0 commit comments

Comments
 (0)