[Mlir-commits] [mlir] [mlir][scf] Clamp normalized loop sizes where they are combined (PR #223256)

Samarth Narang llvmlistbot at llvm.org
Thu Sep 24 05:08:01 PDT 2026


================
@@ -989,6 +989,21 @@ delinearizeInductionVariable(RewriterBase &rewriter, Location loc,
   return {delinearizedIvs, preservedUsers};
 }
 
+/// Clamp a normalized loop size at zero. `emitNormalizedLoopBounds` returns
+/// `ceilDiv(ub - lb, step)`, which is negative for an empty loop: combining two
+/// such sizes cancels the signs into a positive extent, and a negative value is
+/// not a legal `affine.delinearize_index` basis.
+static Value clampSizeToNonNegative(RewriterBase &rewriter, Location loc,
+                                    Value size) {
+  if (auto cst = getConstantIntValue(size))
+    return *cst >= 0 ? size
+                     : getValueOrCreateConstantIntOp(rewriter, loc,
+                                                     rewriter.getIndexAttr(0));
+  Value zero = arith::ConstantOp::create(rewriter, loc,
+                                         rewriter.getZeroAttr(size.getType()));
+  return arith::MaxSIOp::create(rewriter, loc, size, zero);
----------------
snarang181 wrote:

The clamped value is the loop's upper bound with lb = 0 and step = 1, so a zero would imply zero iterations, not one as `max(0, ceilDiv(ub - lb, step))` is exactly the trip count of the original loop, and the product is the trip count of the nest. 

Although, you're right that zero wasn't safe everywhere: the same value also went into the `affine.delinearize_index` basis and the `remsi`/`divsi` divisors, where zero is UB dynamically and a verifier error once it's a constant. Those now clamp at one instead. A statically empty nest now becomes `scf.for %i = %c0 to %c0` with basis `(1, 1)` rather than failing verification  (see `@coalesce_empty_static_loops`).



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


More information about the Mlir-commits mailing list