[Mlir-commits] [mlir] [mlir][affine] Add AffineValueMap::combine and sum (PR #228837)
lonely eagle
llvmlistbot at llvm.org
Sat Oct 3 23:43:45 PDT 2026
https://github.com/linuxlonelyeagle created https://github.com/llvm/llvm-project/pull/228837
Applying a schedule to loops requires bounds for the new loops. For supported schedules, these bounds can be derived by combining lower or upper bounds from multiple source loops. Add `AffineValueMap::combine` to apply an expression over `d0` and `d1` to corresponding results of two value maps. Compose, canonicalize, and simplify the result. Use it to implement difference and pairwise sum.
>From eb4dae05b8f4e1229eb2e2eb285ffd877aba3e1d Mon Sep 17 00:00:00 2001
From: linuxlonelyeagle <2020382038 at qq.com>
Date: Sun, 4 Oct 2026 06:37:42 +0000
Subject: [PATCH] Add AffineValueMap::combine and sum.
---
.../mlir/Dialect/Affine/IR/AffineValueMap.h | 13 +++++
mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp | 55 ++++++++++++++-----
2 files changed, 54 insertions(+), 14 deletions(-)
diff --git a/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h b/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h
index ac480d6997ef430..1f2f8e788fbbe66 100644
--- a/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h
+++ b/mlir/include/mlir/Dialect/Affine/IR/AffineValueMap.h
@@ -49,12 +49,25 @@ class AffineValueMap {
/// operands, but the result count remains the same.
void composeSimplifyAndCanonicalize();
+ /// Combine corresponding results of 'a' and 'b' using 'expr'. The expression
+ /// may refer only to d0 and d1, which stand for the corresponding results of
+ /// 'a' and 'b'. For example, difference() uses `d0 - d1`, and sum() uses
+ /// `d0 + d1`.
+ static void combine(const AffineValueMap &a, const AffineValueMap &b,
+ AffineExpr expr, AffineValueMap *res);
+
/// Return the value map that is the difference of value maps 'a' and 'b',
/// represented as an affine map and its operands. The output map + operands
/// are canonicalized and simplified.
static void difference(const AffineValueMap &a, const AffineValueMap &b,
AffineValueMap *res);
+ /// Return the value map that is the sum of value maps 'a' and 'b',
+ /// represented as an affine map and its operands. The output map + operands
+ /// are canonicalized and simplified.
+ static void sum(const AffineValueMap &a, const AffineValueMap &b,
+ AffineValueMap *res);
+
/// Return true if the idx^th result can be proved to be a multiple of
/// 'factor', false otherwise.
inline bool isMultipleOf(unsigned idx, int64_t factor) const;
diff --git a/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp b/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp
index 6d2d3212c696b50..3a02b56154aac66 100644
--- a/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp
+++ b/mlir/lib/Dialect/Affine/IR/AffineValueMap.cpp
@@ -33,10 +33,19 @@ void AffineValueMap::composeSimplifyAndCanonicalize() {
this->map.reset(sMap);
}
-void AffineValueMap::difference(const AffineValueMap &a,
- const AffineValueMap &b, AffineValueMap *res) {
+void AffineValueMap::combine(const AffineValueMap &a, const AffineValueMap &b,
+ AffineExpr expr, AffineValueMap *res) {
assert(a.getNumResults() == b.getNumResults() && "invalid inputs");
+ bool validExpr = true;
+ expr.walk([&](AffineExpr subExpr) {
+ if (auto dim = llvm::dyn_cast<AffineDimExpr>(subExpr))
+ validExpr &= dim.getPosition() < 2;
+ else if (llvm::isa<AffineSymbolExpr>(subExpr))
+ validExpr = false;
+ });
+ assert(validExpr && "combining expression must use only d0 and d1");
+
SmallVector<Value, 4> allOperands;
allOperands.reserve(a.getNumOperands() + b.getNumOperands());
auto aDims = a.getOperands().take_front(a.getNumDims());
@@ -53,19 +62,37 @@ void AffineValueMap::difference(const AffineValueMap &a,
.shiftDims(a.getNumDims())
.shiftSymbols(a.getNumSymbols());
- // Construct the difference expressions.
+ // Substitute the corresponding results into the combining expression.
auto aMap = a.getAffineMap();
- SmallVector<AffineExpr, 4> diffExprs;
- diffExprs.reserve(a.getNumResults());
- for (unsigned i = 0, e = bMap.getNumResults(); i < e; ++i)
- diffExprs.push_back(aMap.getResult(i) - bMap.getResult(i));
-
- auto diffMap = AffineMap::get(bMap.getNumDims(), bMap.getNumSymbols(),
- diffExprs, bMap.getContext());
- fullyComposeAffineMapAndOperands(&diffMap, &allOperands);
- canonicalizeMapAndOperands(&diffMap, &allOperands);
- diffMap = simplifyAffineMap(diffMap);
- res->reset(diffMap, allOperands);
+ SmallVector<AffineExpr, 4> resultExprs;
+ resultExprs.reserve(a.getNumResults());
+ for (unsigned i = 0, e = bMap.getNumResults(); i < e; ++i) {
+ AffineExpr replacements[] = {aMap.getResult(i), bMap.getResult(i)};
+ resultExprs.push_back(expr.replaceDims(replacements));
+ }
+
+ auto resultMap = AffineMap::get(bMap.getNumDims(), bMap.getNumSymbols(),
+ resultExprs, bMap.getContext());
+ fullyComposeAffineMapAndOperands(&resultMap, &allOperands);
+ canonicalizeMapAndOperands(&resultMap, &allOperands);
+ resultMap = simplifyAffineMap(resultMap);
+ res->reset(resultMap, allOperands);
+}
+
+void AffineValueMap::difference(const AffineValueMap &a,
+ const AffineValueMap &b, AffineValueMap *res) {
+ MLIRContext *context = a.getAffineMap().getContext();
+ AffineExpr lhs = getAffineDimExpr(0, context);
+ AffineExpr rhs = getAffineDimExpr(1, context);
+ combine(a, b, lhs - rhs, res);
+}
+
+void AffineValueMap::sum(const AffineValueMap &a, const AffineValueMap &b,
+ AffineValueMap *res) {
+ MLIRContext *context = a.getAffineMap().getContext();
+ AffineExpr lhs = getAffineDimExpr(0, context);
+ AffineExpr rhs = getAffineDimExpr(1, context);
+ combine(a, b, lhs + rhs, res);
}
// Returns true and sets 'indexOfMatch' if 'valueToMatch' is found in
More information about the Mlir-commits
mailing list