[Mlir-commits] [mlir] [MLIR][Utils] Fix overflow in constantTripCount for narrow types (PR #179985)

Matthias Springer llvmlistbot at llvm.org
Fri Feb 6 01:46:40 PST 2026


================
@@ -397,11 +404,28 @@ std::optional<APInt> constantTripCount(
     return std::nullopt;
   }
 
+  // Extend stepCst to match the bitwidth of diff if needed (e.g., when diff was
+  // extended to avoid overflow). Step is always positive here, so zero-extend.
+  llvm::APInt extendedStepCst = stepCst;
+  if (extendedStepCst.getBitWidth() < diff.getBitWidth()) {
+    extendedStepCst = extendedStepCst.zext(diff.getBitWidth());
+  }
+
   // Create new APSInt instances with explicit signedness to ensure they match
-  llvm::APInt tripCount = isSigned ? diff.sdiv(stepCst) : diff.udiv(stepCst);
-  llvm::APInt remainder = isSigned ? diff.srem(stepCst) : diff.urem(stepCst);
+  llvm::APInt tripCount =
----------------
matthias-springer wrote:

At this point, we can assume that `diff` is non-negative (see above comment) and that `step` is non-negative, even if interpreted as signed integer. The reason is the above check:
```
  // For signed loops, a negative step size could indicate an infinite number of
  // iterations.
  if (isSigned && stepCst.isSignBitSet()) {
    LDBG() << "constantTripCount is infinite because step is negative";
    return std::nullopt;
  }
```

That means we don't have to distinguish between signed and unsigned semantics anymore at this point.

I.e., no need to check `isSigned`, use `udiv` and `urem` only. We need to document this reasoning here.

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


More information about the Mlir-commits mailing list