diff --git a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp index 49f89e1bd17f3..c515d92e24ff5 100644 --- a/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp +++ b/mlir/lib/Dialect/Arith/IR/InferIntRangeInterfaceImpls.cpp @@ -245,6 +245,9 @@ void arith::TruncIOp::inferResultRanges(ArrayRef argRanges, SetIntRangeFn setResultRange) { unsigned destWidth = ConstantIntRanges::getStorageBitwidth(getResult().getType()); + // i0 has no bits; APInt arithmetic is undefined for width 0, skip it. + if (destWidth == 0) + return; setResultRange(getResult(), truncRange(argRanges[0], destWidth)); } diff --git a/mlir/test/Dialect/Arith/int-range-narrowing.mlir b/mlir/test/Dialect/Arith/int-range-narrowing.mlir index e2cd9b50f6736..f527f8c4bb7ee 100644 --- a/mlir/test/Dialect/Arith/int-range-narrowing.mlir +++ b/mlir/test/Dialect/Arith/int-range-narrowing.mlir @@ -417,3 +417,12 @@ func.func @narrow_loop_bounds() { } return } + +// Verify that truncating to i0 does not crash (issue #177822). +// The pass cannot narrow i0 types; the trunci should be preserved. +// CHECK-LABEL: @trunci_to_i0_no_crash +// CHECK: arith.trunci %arg0 : i32 to i0 +func.func @trunci_to_i0_no_crash(%arg0: i32) -> i0 { + %0 = arith.trunci %arg0 : i32 to i0 + return %0 : i0 +}