[mlir][int-range] Limit xor int range inference to i1 (#116968)

Fixes https://github.com/llvm/llvm-project/issues/82168

`intrange::inferXor` was incorrectly handling ranges for widths > i1
(see example in code). Limit it to i1 for now. For bigger widths it will
return maxRange.
This commit is contained in:
Ivan Butygin 2024-11-20 18:12:33 +01:00 committed by GitHub
parent 81c2024311
commit 0733f38414
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 2 deletions

View File

@ -558,6 +558,20 @@ mlir::intrange::inferOr(ArrayRef<ConstantIntRanges> argRanges) {
ConstantIntRanges
mlir::intrange::inferXor(ArrayRef<ConstantIntRanges> argRanges) {
// TODO: The code below doesn't work for bitwidths > i1.
// For input ranges lhs=[2060639849, 2060639850], rhs=[2060639849, 2060639849]
// widenBitwiseBounds will produce:
// lhs:
// 2060639848 01111010110100101101111001101000
// 2060639851 01111010110100101101111001101011
// rhs:
// 2060639849 01111010110100101101111001101001
// 2060639849 01111010110100101101111001101001
// None of those combinations xor to 0, while intermediate values does.
unsigned width = argRanges[0].umin().getBitWidth();
if (width > 1)
return ConstantIntRanges::maxRange(width);
auto [lhsZeros, lhsOnes] = widenBitwiseBounds(argRanges[0]);
auto [rhsZeros, rhsOnes] = widenBitwiseBounds(argRanges[1]);
auto xori = [](const APInt &a, const APInt &b) -> std::optional<APInt> {

View File

@ -454,9 +454,35 @@ func.func @ori(%arg0 : i128, %arg1 : i128) -> i1 {
func.return %2 : i1
}
// CHECK-LABEL: func @xori_issue_82168
// arith.cmpi was erroneously folded to %false, see Issue #82168.
// CHECK: %[[R:.*]] = arith.cmpi eq, %{{.*}}, %{{.*}} : i64
// CHECK: return %[[R]]
func.func @xori_issue_82168() -> i1 {
%c0_i64 = arith.constant 0 : i64
%c2060639849_i64 = arith.constant 2060639849 : i64
%2 = test.with_bounds { umin = 2060639849 : i64, umax = 2060639850 : i64, smin = 2060639849 : i64, smax = 2060639850 : i64 } : i64
%3 = arith.xori %2, %c2060639849_i64 : i64
%4 = arith.cmpi eq, %3, %c0_i64 : i64
func.return %4 : i1
}
// CHECK-LABEL: func @xori_i1
// CHECK-DAG: %[[true:.*]] = arith.constant true
// CHECK-DAG: %[[false:.*]] = arith.constant false
// CHECK: return %[[true]], %[[false]]
func.func @xori_i1() -> (i1, i1) {
%true = arith.constant true
%1 = test.with_bounds { umin = 0 : i1, umax = 0 : i1, smin = 0 : i1, smax = 0 : i1 } : i1
%2 = test.with_bounds { umin = 1 : i1, umax = 1 : i1, smin = 1 : i1, smax = 1 : i1 } : i1
%3 = arith.xori %1, %true : i1
%4 = arith.xori %2, %true : i1
func.return %3, %4 : i1, i1
}
// CHECK-LABEL: func @xori
// CHECK: %[[false:.*]] = arith.constant false
// CHECK: return %[[false]]
// TODO: xor folding is temporarily disabled
// CHECK-NOT: arith.constant false
func.func @xori(%arg0 : i64, %arg1 : i64) -> i1 {
%c0 = arith.constant 0 : i64
%c7 = arith.constant 7 : i64