Skip to content

Commit 9ab16d4

Browse files
authored
[mlir][IntRangeInference] Fix arith.ceildivsi range inference when it includes INT_MIN (llvm#121062)
There is a special case in `arith.ceildivsi` range inference for handling `lhs.smin()==INT_MIN`, but when `lhs` is not a single value, it can cause it to skip entire negative range. Add `lhs.smin() + 1` check to handle it.
1 parent 5ad4213 commit 9ab16d4

File tree

2 files changed

+21
-1
lines changed

2 files changed

+21
-1
lines changed

mlir/lib/Interfaces/Utils/InferIntRangeCommon.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,15 @@ mlir::intrange::inferCeilDivS(ArrayRef<ConstantIntRanges> argRanges) {
386386
}
387387
return result;
388388
};
389-
return inferDivSRange(lhs, rhs, ceilDivSIFix);
389+
ConstantIntRanges result = inferDivSRange(lhs, rhs, ceilDivSIFix);
390+
if (lhs.smin().isMinSignedValue() && lhs.smax().sgt(lhs.smin())) {
391+
// If lhs range includes INT_MIN and lhs is not a single value, we can
392+
// suddenly wrap to positive val, skipping entire negative range, add
393+
// [INT_MIN + 1, smax()] range to the result to handle this.
394+
auto newLhs = ConstantIntRanges::fromSigned(lhs.smin() + 1, lhs.smax());
395+
result = result.rangeUnion(inferDivSRange(newLhs, rhs, ceilDivSIFix));
396+
}
397+
return result;
390398
}
391399

392400
ConstantIntRanges

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,18 @@ func.func @ceil_divsi(%arg0 : index) -> i1 {
249249
func.return %10 : i1
250250
}
251251

252+
// There was a bug, which was causing this expr errorneously fold to constant
253+
// CHECK-LABEL: func @ceil_divsi_full_range
254+
// CHECK-SAME: (%[[arg:.*]]: index)
255+
// CHECK: %[[c64:.*]] = arith.constant 64 : index
256+
// CHECK: %[[ret:.*]] = arith.ceildivsi %[[arg]], %[[c64]] : index
257+
// CHECK: return %[[ret]]
258+
func.func @ceil_divsi_full_range(%6: index) -> index {
259+
%c64 = arith.constant 64 : index
260+
%55 = arith.ceildivsi %6, %c64 : index
261+
return %55 : index
262+
}
263+
252264
// CHECK-LABEL: func @ceil_divsi_intmin_bug_115293
253265
// CHECK: %[[ret:.*]] = arith.constant true
254266
// CHECK: return %[[ret]]

0 commit comments

Comments
 (0)