[Mlir-commits] [mlir] [mlir][linalg] Constrain tiling semi-affine maps (PR #212240)

Chuanqi Xu llvmlistbot at llvm.org
Thu Jul 30 00:09:15 PDT 2026


================
@@ -82,6 +82,79 @@ static LogicalResult inlinePayload(OpBuilder &b, LinalgOp linalgOp,
   return success();
 }
 
+/// Verify that tiling can be applied in presence of semi-affine maps.
+static LogicalResult
+validateTilingSemiAffineMaps(LinalgOp linalgOp, ArrayRef<OpFoldResult> offsets,
+                             ArrayRef<OpFoldResult> sizes) {
+  auto isTiledDim = [&](unsigned pos) {
+    return pos < offsets.size() && !isZeroInteger(offsets[pos]);
+  };
+
+  for (AffineMap map : linalgOp.getIndexingMapsArray()) {
+    for (AffineExpr result : map.getResults()) {
+      WalkResult status = result.walk([&](AffineExpr expr) -> WalkResult {
+        auto binExpr = dyn_cast<AffineBinaryOpExpr>(expr);
+        if (!binExpr)
+          return WalkResult::advance();
+        AffineExprKind kind = binExpr.getKind();
+        if (kind != AffineExprKind::Mod && kind != AffineExprKind::FloorDiv &&
+            kind != AffineExprKind::CeilDiv)
+          return WalkResult::advance();
+
+        // Skip if the semi-affine expression does not involve any of the tiled
+        // dimensions.
+        bool involvesTiledDim = false;
+        for (unsigned pos = 0, e = offsets.size(); pos < e; ++pos) {
+          if (isTiledDim(pos) && expr.isFunctionOfDim(pos)) {
+            involvesTiledDim = true;
+            break;
+          }
+        }
+        if (!involvesTiledDim)
+          return WalkResult::advance();
+
+        // Allow only `d OP C` map where `d` is a dimension and `C` is a
+        // constant. A compound LHS (e.g. `(d0 + d1)`, `(d0 * 2)`, a nested
+        // semi-affine expression) or a non-constant step is not provably safe,
+        // so reject it.
+        auto dimExpr = dyn_cast<AffineDimExpr>(binExpr.getLHS());
+        auto stepExpr = dyn_cast<AffineConstantExpr>(binExpr.getRHS());
+        if (!dimExpr || !stepExpr || stepExpr.getValue() <= 0) {
+          linalgOp.emitOpError()
+              << "tiling is not supported for the semi-affine indexing map: "
+                 "only a single iteration dimension divided by a positive "
+                 "constant step can be tiled over a tiled dimension";
+          return WalkResult::interrupt();
+        }
+        unsigned dimPos = dimExpr.getPosition();
+        int64_t step = stepExpr.getValue();
+
+        // Tile boundaries stay aligned to the step only when the tile size and
+        // step divide one another.
+        // Dynamic tile sizes are assumed to be valid.
+        FailureOr<int64_t> tileSize =
+            ValueBoundsConstraintSet::computeConstantBound(
+                presburger::BoundType::UB, sizes[dimPos],
+                /*stopCondition=*/nullptr,
+                ValueBoundsOptions{/*closedUB=*/true});
----------------
ChuanqiXu9 wrote:

I am not sure. But it seems like computeConstantBound will return a **upper bound**. It has  a upper bound doesn't mean it is it. Maybe we should get the lower bound too.

https://github.com/llvm/llvm-project/pull/212240


More information about the Mlir-commits mailing list