[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