[Mlir-commits] [mlir] 14f7334 - [mlir][dataflow] Fix crash in IntegerRangeAnalysis with non-constant loop bounds (#183660)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Fri Feb 27 02:47:14 PST 2026


Author: Mehdi Amini
Date: 2026-02-27T11:47:10+01:00
New Revision: 14f73345ff0caa0694e9033d0c805f9cfa7ff519

URL: https://github.com/llvm/llvm-project/commit/14f73345ff0caa0694e9033d0c805f9cfa7ff519
DIFF: https://github.com/llvm/llvm-project/commit/14f73345ff0caa0694e9033d0c805f9cfa7ff519.diff

LOG: [mlir][dataflow] Fix crash in IntegerRangeAnalysis with non-constant loop bounds (#183660)

When visiting non-control-flow arguments of a LoopLikeOpInterface op,
IntegerRangeAnalysis assumed that getLoopLowerBounds(),
getLoopUpperBounds(), and getLoopSteps() always return non-null values
when getLoopInductionVars() is non-null. This assumption is incorrect:
for example, AffineForOp returns nullopt from getLoopUpperBounds() when
the upper bound is not a constant affine expression (e.g., a dynamic
index from a tensor.dim).

Fix this by checking whether the bound optionals are engaged before
dereferencing them and falling back to the generic analysis if any bound
is unavailable.

Fixes #180312

Added: 
    

Modified: 
    mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
    mlir/test/Dialect/Arith/int-range-narrowing.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp b/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
index 7b567f043577a..818450e2bc696 100644
--- a/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
+++ b/mlir/lib/Analysis/DataFlow/IntegerRangeAnalysis.cpp
@@ -217,10 +217,21 @@ void IntegerRangeAnalysis::visitNonControlFlowArguments(
       return SparseForwardDataFlowAnalysis ::visitNonControlFlowArguments(
           op, successor, nonSuccessorInputs, nonSuccessorInputLattices);
     }
-    // This shouldn't be returning nullopt if there are indunction variables.
-    SmallVector<OpFoldResult> lowerBounds = *loop.getLoopLowerBounds();
-    SmallVector<OpFoldResult> upperBounds = *loop.getLoopUpperBounds();
-    SmallVector<OpFoldResult> steps = *loop.getLoopSteps();
+    // Some loop implementations may return nullopt for non-constant bounds
+    // (e.g. affine.for with a dynamic upper bound), even when induction
+    // variables exist. Fall back to the generic analysis in that case.
+    std::optional<SmallVector<OpFoldResult>> maybeLowerBounds =
+        loop.getLoopLowerBounds();
+    std::optional<SmallVector<OpFoldResult>> maybeUpperBounds =
+        loop.getLoopUpperBounds();
+    std::optional<SmallVector<OpFoldResult>> maybeSteps = loop.getLoopSteps();
+    if (!maybeLowerBounds || !maybeUpperBounds || !maybeSteps) {
+      return SparseForwardDataFlowAnalysis::visitNonControlFlowArguments(
+          op, successor, nonSuccessorInputs, nonSuccessorInputLattices);
+    }
+    SmallVector<OpFoldResult> lowerBounds = *maybeLowerBounds;
+    SmallVector<OpFoldResult> upperBounds = *maybeUpperBounds;
+    SmallVector<OpFoldResult> steps = *maybeSteps;
     for (auto [iv, lowerBound, upperBound, step] :
          llvm::zip_equal(*maybeIvs, lowerBounds, upperBounds, steps)) {
       Block *block = iv.getParentBlock();

diff  --git a/mlir/test/Dialect/Arith/int-range-narrowing.mlir b/mlir/test/Dialect/Arith/int-range-narrowing.mlir
index e2cd9b50f6736..c3b0d280b1350 100644
--- a/mlir/test/Dialect/Arith/int-range-narrowing.mlir
+++ b/mlir/test/Dialect/Arith/int-range-narrowing.mlir
@@ -417,3 +417,17 @@ func.func @narrow_loop_bounds() {
   }
   return
 }
+
+// Ensure affine.for with a non-constant (dynamic) upper bound doesn't crash.
+// affine.for implements LoopLikeOpInterface but getLoopUpperBounds() returns
+// nullopt for non-constant bounds, which must be handled gracefully.
+func.func private @use_index(index) -> ()
+// CHECK-LABEL: func @affine_for_dynamic_bound
+func.func @affine_for_dynamic_bound(%n: index) {
+  // CHECK: affine.for %[[IV:.*]] = 0 to %{{.*}} {
+  affine.for %i = 0 to %n {
+    // CHECK: func.call @use_index(%[[IV]])
+    func.call @use_index(%i) : (index) -> ()
+  }
+  return
+}


        


More information about the Mlir-commits mailing list