Skip to content

[MLIR][Affine] Remove restriction in slice validity check on symbols#180709

Merged
bondhugula merged 1 commit into
llvm:mainfrom
bondhugula:uday/fusion_symbolic_bounds
Feb 11, 2026
Merged

[MLIR][Affine] Remove restriction in slice validity check on symbols#180709
bondhugula merged 1 commit into
llvm:mainfrom
bondhugula:uday/fusion_symbolic_bounds

Conversation

@bondhugula
Copy link
Copy Markdown
Contributor

@bondhugula bondhugula commented Feb 10, 2026

Remove restriction in affine analysis utility for checking slice validity. This was unnecessarily bailing out still after the underlying methods were extended. This update enables fusion of affine nests with symbolic bounds.

Fixes: #61784

Based on and revived from https://reviews.llvm.org/D148559 from @anoopjs.

Remove restriction in affine analysis utility for checking slice
validity. This was unnecessarily bailing out still after the underlying
methods were extended. This update enables fusion of affine nests with
symbolic bounds.

Fixes: llvm#61784

Based on https://reviews.llvm.org/D148559 from anoopjs
@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Feb 10, 2026

@llvm/pr-subscribers-mlir

@llvm/pr-subscribers-mlir-affine

Author: Uday Bondhugula (bondhugula)

Changes

Remove restriction in affine analysis utility for checking slice validity. This was unnecessarily bailing out still after the underlying methods were extended. This update enables fusion of affine nests with symbolic bounds.

Fixes: #61784

Based on and revived from https://reviews.llvm.org/D148559 from @anoopjs.


Full diff: https://github.com/llvm/llvm-project/pull/180709.diff

2 Files Affected:

  • (modified) mlir/lib/Dialect/Affine/Analysis/Utils.cpp (+2-6)
  • (modified) mlir/test/Dialect/Affine/loop-fusion-4.mlir (+59)
diff --git a/mlir/lib/Dialect/Affine/Analysis/Utils.cpp b/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
index 92d8846a4640d..ee893c14c9c6b 100644
--- a/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
+++ b/mlir/lib/Dialect/Affine/Analysis/Utils.cpp
@@ -1056,12 +1056,6 @@ std::optional<bool> ComputationSliceState::isSliceValid() const {
     LDBG() << "Unable to compute source's domain";
     return std::nullopt;
   }
-  // As the set difference utility currently cannot handle symbols in its
-  // operands, validity of the slice cannot be determined.
-  if (srcConstraints.getNumSymbolVars() > 0) {
-    LDBG() << "Cannot handle symbols in source domain";
-    return std::nullopt;
-  }
   // TODO: Handle local vars in the source domains while using the 'projectOut'
   // utility below. Currently, aligning is not done assuming that there will be
   // no local vars in the source domain.
@@ -1082,6 +1076,8 @@ std::optional<bool> ComputationSliceState::isSliceValid() const {
   // domain completely in terms of source's IVs.
   sliceConstraints.projectOut(ivs.size(),
                               sliceConstraints.getNumVars() - ivs.size());
+  srcConstraints.projectOut(ivs.size(),
+                            srcConstraints.getNumVars() - ivs.size());
 
   LDBG() << "Domain of the source of the slice:\n"
          << "Source constraints:" << srcConstraints
diff --git a/mlir/test/Dialect/Affine/loop-fusion-4.mlir b/mlir/test/Dialect/Affine/loop-fusion-4.mlir
index 04c8c3ee809a1..d6884fb921ad2 100644
--- a/mlir/test/Dialect/Affine/loop-fusion-4.mlir
+++ b/mlir/test/Dialect/Affine/loop-fusion-4.mlir
@@ -771,3 +771,62 @@ func.func @memref_cast_reused(%arg: memref<*xf32>) {
   // SIBLING-MAXIMAL-NEXT:   affine.store
   return
 }
+
+// -----
+
+// Test with symbolic loop bounds.
+
+// PRODUCER-CONSUMER-MAXIMAL-LABEL: func @fusion_non_constant_bounds_0
+func.func @fusion_non_constant_bounds_0(%arg0: memref<?xf32>) {
+  %cst = arith.constant 1.000000e+00 : f32
+  %cst_0 = arith.constant 2.000000e+00 : f32
+  %c0 = arith.constant 0 : index
+  %dim = memref.dim %arg0, %c0 : memref<?xf32>
+  affine.for %arg1 = 0 to %dim {
+    %0 = affine.load %arg0[%arg1] : memref<?xf32>
+    %1 = arith.addf %0, %cst : f32
+    affine.store %1, %arg0[%arg1] : memref<?xf32>
+  }
+  affine.for %arg1 = 0 to %dim {
+    %0 = affine.load %arg0[%arg1] : memref<?xf32>
+    %1 = arith.addf %0, %cst_0 : f32
+    affine.store %1, %arg0[%arg1] : memref<?xf32>
+  }
+  // PRODUCER-CONSUMER-MAXIMAL:      affine.for %[[idx:.*]] = 0 to %{{.*}} {
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   affine.load %[[arr:.*]][%[[idx]]] : memref<?xf32>
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   arith.addf
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   affine.store %{{.*}}, %[[arr]][%[[idx]]] : memref<?xf32>
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   affine.load %[[arr:.*]][%[[idx]]] : memref<?xf32>
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   arith.addf
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   affine.store %{{.*}}, %[[arr]][%[[idx]]] : memref<?xf32>
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT: }
+  return
+}
+
+// PRODUCER-CONSUMER-MAXIMAL-LABEL: func @fusion_non_constant_bounds_1
+func.func @fusion_non_constant_bounds_1(%N: index, %M: memref<?xf32>, %cst: f32) {
+  affine.for %i = 0 to %N {
+    affine.store %cst, %M[%i] : memref<?xf32>
+  }
+  affine.for %i = 0 to %N {
+    affine.load %M[%i] : memref<?xf32>
+  }
+  // Should be fused.
+  // PRODUCER-CONSUMER-MAXIMAL: affine.for
+  // PRODUCER-CONSUMER-MAXIMAL-NOT: affine.for
+
+  // Bounds not matching. Still fused; source remains.
+  // PRODUCER-CONSUMER-MAXIMAL:      affine.for
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   affine.store
+  affine.for %i = 0 to %N {
+    affine.store %cst, %M[%i] : memref<?xf32>
+  }
+  // PRODUCER-CONSUMER-MAXIMAL:      affine.for
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   affine.store
+  // PRODUCER-CONSUMER-MAXIMAL-NEXT:   affine.load
+  affine.for %i = 1 to %N {
+    affine.load %M[%i] : memref<?xf32>
+  }
+
+  return
+}

@bondhugula
Copy link
Copy Markdown
Contributor Author

bondhugula commented Feb 10, 2026

This was posted and reviewed earlier here: https://reviews.llvm.org/D148559, but was somehow lost. Affine fusion with symbolic/non-constant bounds has always been possible, but for these now outdated guards.

@bondhugula bondhugula requested a review from dcaballe February 10, 2026 09:11
@bondhugula bondhugula merged commit 8a00fd0 into llvm:main Feb 11, 2026
13 checks passed
bgrady-tt added a commit to tenstorrent/tt-mlir that referenced this pull request Feb 14, 2026
Applies very small code changes in
llvm/llvm-project#180709 to unblock use of
affine loop fusion ahead of LLVM uplift.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mlir/Affine: affine loop fusion is unable to fuse loops with non-constant extents

2 participants