[Mlir-commits] [mlir] [mlir][IntRange] Avoid division by zero for empty divisor ranges in divs (PR #234159)

Sajid Zubair llvmlistbot at llvm.org
Wed Oct 21 04:20:32 PDT 2026


https://github.com/Sajid-Zubair created https://github.com/llvm/llvm-project/pull/234159

inferSub can produce an empty range (smin > smax) when both nsw and nuw saturate, e.g. for `arith.subi 0, 1 overflow<nsw, nuw>`, whose result is poison. inferDivSRange only checked rhsMax.isNegative() to rule out a zero divisor, so it then evaluated sdiv with rhsMin == 0 and asserted in APInt::udiv. Treat an empty divisor range as unknown and return the max range instead.

Fixes #231845

>From 1aa7a4d67b60522c367be2c1af29dee38ad46c13 Mon Sep 17 00:00:00 2001
From: Sajid-Zubair <sajid10zubair at gmail.com>
Date: Wed, 21 Oct 2026 16:49:43 +0530
Subject: [PATCH] [mlir][IntRange] Avoid division by zero for empty divisor
 ranges in divs

inferSub can produce an empty range (smin > smax) when both nsw and nuw
saturate, e.g. for `arith.subi 0, 1 overflow<nsw, nuw>`, whose result is
poison. inferDivSRange only checked rhsMax.isNegative() to rule out a zero
divisor, so it then evaluated sdiv with rhsMin == 0 and asserted in
APInt::udiv. Treat an empty divisor range as unknown and return the max
range instead.

Fixes #231845

Assisted by: Opus 5.5
---
 mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp |  5 ++++-
 mlir/test/Dialect/Arith/int-range-opts-crash.mlir | 12 ++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
index c9f49fda726e7..24fb166ce91c1 100644
--- a/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
+++ b/mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp
@@ -342,7 +342,10 @@ static ConstantIntRanges inferDivSRange(const ConstantIntRanges &lhs,
                                         DivisionFixupFn fixup) {
   const APInt &lhsMin = lhs.smin(), &lhsMax = lhs.smax(), &rhsMin = rhs.smin(),
               &rhsMax = rhs.smax();
-  bool canDivide = rhsMin.isStrictlyPositive() || rhsMax.isNegative();
+  // An empty (min > max) divisor range can arise from poison, e.g. a
+  // saturated `nsw`/`nuw` subtraction. Don't trust its bounds.
+  bool canDivide = rhsMin.sle(rhsMax) &&
+                   (rhsMin.isStrictlyPositive() || rhsMax.isNegative());
 
   if (canDivide) {
     auto sdiv = [&fixup](const APInt &a,
diff --git a/mlir/test/Dialect/Arith/int-range-opts-crash.mlir b/mlir/test/Dialect/Arith/int-range-opts-crash.mlir
index fa763c163160d..77b173311f6ac 100644
--- a/mlir/test/Dialect/Arith/int-range-opts-crash.mlir
+++ b/mlir/test/Dialect/Arith/int-range-opts-crash.mlir
@@ -11,3 +11,15 @@ func.func @repro_crash() -> !test.i32 {
   // CHECK: return %[[RES]] : !test.i32
   return %0 : !test.i32
 }
+
+// The divisor is poison (0 - 1 with nuw), giving an empty range.
+// This used to divide by zero in inferDivSRange.
+// CHECK-LABEL: func.func @divs_by_poison_sub
+// CHECK: index.divs
+func.func @divs_by_poison_sub() -> index {
+  %z = arith.constant 0 : index
+  %o = arith.constant 1 : index
+  %bad = arith.subi %z, %o overflow<nsw, nuw> : index
+  %q = index.divs %o, %bad
+  return %q : index
+}



More information about the Mlir-commits mailing list