[Mlir-commits] [mlir] [mlir][Interfaces][NFC] `ValueBoundsConstraintSet`: Add columns for constant values/dims (PR #86097)
Matthias Springer
llvmlistbot at llvm.org
Thu Mar 21 01:00:30 PDT 2024
https://github.com/matthias-springer created https://github.com/llvm/llvm-project/pull/86097
`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 constant 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.
>From 13c9d7f5a70f80de8b2c2ba404b7df2e887f8dba Mon Sep 17 00:00:00 2001
From: Matthias Springer <springerm at google.com>
Date: Thu, 21 Mar 2024 07:58:36 +0000
Subject: [PATCH] [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.
---
.../mlir/Interfaces/ValueBoundsOpInterface.h | 5 +-
.../lib/Interfaces/ValueBoundsOpInterface.cpp | 67 ++++++++++++++-----
2 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h b/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h
index 28dadfb9ecf868..94a8a8b429c801 100644
--- a/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h
+++ b/mlir/include/mlir/Interfaces/ValueBoundsOpInterface.h
@@ -280,12 +280,13 @@ class ValueBoundsConstraintSet {
/// Insert a value/dimension into the constraint set. If `isSymbol` is set to
/// "false", a dimension is added. The value/dimension is added to the
- /// worklist.
+ /// worklist if `addToWorklist` is set.
///
/// Note: There are certain affine restrictions wrt. dimensions. E.g., they
/// cannot be multiplied. Furthermore, bounds can only be queried for
/// dimensions but not for symbols.
- int64_t insert(Value value, std::optional<int64_t> dim, bool isSymbol = true);
+ int64_t insert(Value value, std::optional<int64_t> dim, bool isSymbol = true,
+ bool addToWorklist = true);
/// Insert an anonymous column into the constraint set. The column is not
/// bound to any value/dimension. If `isSymbol` is set to "false", a dimension
diff --git a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
index 85abc2df894797..02af3a83166dfb 100644
--- a/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
+++ b/mlir/lib/Interfaces/ValueBoundsOpInterface.cpp
@@ -105,25 +105,57 @@ AffineExpr ValueBoundsConstraintSet::getExpr(Value value,
assertValidValueDim(value, dim);
#endif // NDEBUG
+ // Helper function that returns an affine expression that represents column
+ // `pos` in the constraint set.
+ auto getPosExpr = [&](int64_t pos) {
+ assert(pos >= 0 && pos < cstr.getNumDimAndSymbolVars() &&
+ "invalid position");
+ return pos < cstr.getNumDimVars()
+ ? builder.getAffineDimExpr(pos)
+ : builder.getAffineSymbolExpr(pos - cstr.getNumDimVars());
+ };
+
+ // Check if the value/dim is statically known. In that case, an affine
+ // constant expression should be returned. This allows us to support
+ // multiplications with constants. (Multiplications of two columns in the
+ // constraint set is not supported.)
+ std::optional<int64_t> constSize = std::nullopt;
auto shapedType = dyn_cast<ShapedType>(value.getType());
if (shapedType) {
- // Static dimension: return constant directly.
if (shapedType.hasRank() && !shapedType.isDynamicDim(*dim))
- return builder.getAffineConstantExpr(shapedType.getDimSize(*dim));
- } else {
- // Constant index value: return directly.
- if (auto constInt = ::getConstantIntValue(value))
- return builder.getAffineConstantExpr(*constInt);
+ constSize = shapedType.getDimSize(*dim);
+ } else if (auto constInt = ::getConstantIntValue(value)) {
+ constSize = *constInt;
}
- // Dynamic value: add to constraint set.
+ // If the value/dim is already mapped, return the corresponding expression
+ // directly.
ValueDim valueDim = std::make_pair(value, dim.value_or(kIndexValue));
- if (!valueDimToPosition.contains(valueDim))
- (void)insert(value, dim);
- int64_t pos = getPos(value, dim);
- return pos < cstr.getNumDimVars()
- ? builder.getAffineDimExpr(pos)
- : builder.getAffineSymbolExpr(pos - cstr.getNumDimVars());
+ if (valueDimToPosition.contains(valueDim)) {
+ // If it is a constant, return an affine constant expression. Otherwise,
+ // return an affine expression that represents the respective column in the
+ // constraint set.
+ if (constSize)
+ return builder.getAffineConstantExpr(*constSize);
+ return getPosExpr(getPos(value, dim));
+ }
+
+ if (constSize) {
+ // Constant index value/dim: add column to the constraint set, add EQ bound
+ // and return an affine constant expression without pushing the newly added
+ // column to the worklist.
+ (void)insert(value, dim, /*isSymbol=*/true, /*addToWorklist=*/false);
+ if (shapedType)
+ bound(value)[*dim] == *constSize;
+ else
+ bound(value) == *constSize;
+ return builder.getAffineConstantExpr(*constSize);
+ }
+
+ // Dynamic value/dim: insert column to the constraint set and put it on the
+ // worklist. Return an affine expression that represents the newly inserted
+ // column in the constraint set.
+ return getPosExpr(insert(value, dim, /*isSymbol=*/true));
}
AffineExpr ValueBoundsConstraintSet::getExpr(OpFoldResult ofr) {
@@ -140,7 +172,7 @@ AffineExpr ValueBoundsConstraintSet::getExpr(int64_t constant) {
int64_t ValueBoundsConstraintSet::insert(Value value,
std::optional<int64_t> dim,
- bool isSymbol) {
+ bool isSymbol, bool addToWorklist) {
#ifndef NDEBUG
assertValidValueDim(value, dim);
#endif // NDEBUG
@@ -155,7 +187,12 @@ int64_t ValueBoundsConstraintSet::insert(Value value,
if (positionToValueDim[i].has_value())
valueDimToPosition[*positionToValueDim[i]] = i;
- worklist.push(pos);
+ if (addToWorklist) {
+ LLVM_DEBUG(llvm::dbgs() << "Push to worklist: " << value
+ << " (dim: " << dim.value_or(kIndexValue) << ")\n");
+ worklist.push(pos);
+ }
+
return pos;
}
More information about the Mlir-commits
mailing list