Skip to content

Commit 2e612f8

Browse files
authored
[MLIR][Arith] Improve accuracy of inferDivU (#113789)
1) We can always bound the maximum with the numerator. - https://alive2.llvm.org/ce/z/PqHvuT 2) Even if denominator min can be zero, we can still bound the minimum result with `lhs.umin u/ rhs.umax`. This is similar to #110169
1 parent a388df7 commit 2e612f8

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,14 @@ static ConstantIntRanges inferDivURange(const ConstantIntRanges &lhs,
298298
return minMaxBy(udiv, {lhsMin, lhsMax}, {rhsMin, rhsMax},
299299
/*isSigned=*/false);
300300
}
301-
// Otherwise, it's possible we might divide by 0.
302-
return ConstantIntRanges::maxRange(rhsMin.getBitWidth());
301+
302+
APInt umin = APInt::getZero(rhsMin.getBitWidth());
303+
if (lhsMin.uge(rhsMax) && !rhsMax.isZero())
304+
umin = lhsMin.udiv(rhsMax);
305+
306+
// X u/ Y u<= X.
307+
APInt umax = lhsMax;
308+
return ConstantIntRanges::fromUnsigned(umin, umax);
303309
}
304310

305311
ConstantIntRanges

mlir/test/Dialect/Arith/int-range-interface.mlir

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,8 @@ func.func @div_bounds_negative(%arg0 : index) -> i1 {
178178
}
179179

180180
// CHECK-LABEL: func @div_zero_undefined
181-
// CHECK: %[[ret:.*]] = arith.cmpi ule
182-
// CHECK: return %[[ret]]
181+
// CHECK: %[[true:.*]] = arith.constant true
182+
// CHECK: return %[[true]]
183183
func.func @div_zero_undefined(%arg0 : index) -> i1 {
184184
%c0 = arith.constant 0 : index
185185
%c1 = arith.constant 1 : index
@@ -190,6 +190,19 @@ func.func @div_zero_undefined(%arg0 : index) -> i1 {
190190
func.return %2 : i1
191191
}
192192

193+
// CHECK-LABEL: func @div_refine_min
194+
// CHECK: %[[true:.*]] = arith.constant true
195+
// CHECK: return %[[true]]
196+
func.func @div_refine_min(%arg0 : index) -> i1 {
197+
%c0 = arith.constant 1 : index
198+
%c1 = arith.constant 2 : index
199+
%c4 = arith.constant 4 : index
200+
%0 = arith.andi %arg0, %c1 : index
201+
%1 = arith.divui %c4, %0 : index
202+
%2 = arith.cmpi uge, %1, %c0 : index
203+
func.return %2 : i1
204+
}
205+
193206
// CHECK-LABEL: func @ceil_divui
194207
// CHECK: %[[ret:.*]] = arith.cmpi eq
195208
// CHECK: return %[[ret]]
@@ -271,13 +284,13 @@ func.func @remui_base(%arg0 : index, %arg1 : index ) -> i1 {
271284
// CHECK: return %[[true]]
272285
func.func @remui_base_maybe_zero(%arg0 : index, %arg1 : index ) -> i1 {
273286
%c4 = arith.constant 4 : index
274-
%c5 = arith.constant 5 : index
287+
%c5 = arith.constant 5 : index
275288

276289
%0 = arith.minui %arg1, %c4 : index
277290
%1 = arith.remui %arg0, %0 : index
278291
%2 = arith.cmpi ult, %1, %c5 : index
279292
func.return %2 : i1
280-
}
293+
}
281294

282295
// CHECK-LABEL: func @remsi_base
283296
// CHECK: %[[ret:.*]] = arith.cmpi sge

0 commit comments

Comments
 (0)