[Mlir-commits] [mlir] 301dc7d - [mlir][arith] Fix overflow flags when folding nested truncations (#233167)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sun Oct 18 23:06:54 PDT 2026
Author: Matthias Springer
Date: 2026-10-19T15:06:50+09:00
New Revision: 301dc7de591ae8aef7fea3c50c9b6210e491567a
URL: https://github.com/llvm/llvm-project/commit/301dc7de591ae8aef7fea3c50c9b6210e491567a
DIFF: https://github.com/llvm/llvm-project/commit/301dc7de591ae8aef7fea3c50c9b6210e491567a.diff
LOG: [mlir][arith] Fix overflow flags when folding nested truncations (#233167)
Assisted-by: Codex
Added:
Modified:
mlir/lib/Dialect/Arith/IR/ArithOps.cpp
mlir/test/Dialect/Arith/canonicalize.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
index ce8851cdea997..7ed50c6ab787c 100644
--- a/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
+++ b/mlir/lib/Dialect/Arith/IR/ArithOps.cpp
@@ -2077,9 +2077,11 @@ OpFoldResult arith::TruncIOp::fold(FoldAdaptor adaptor) {
return src;
}
- // trunci(trunci(a)) -> trunci(a))
- if (matchPattern(getOperand(), m_Op<arith::TruncIOp>())) {
- setOperand(getOperand().getDefiningOp()->getOperand(0));
+ // trunci(trunci(a)) -> trunci(a)
+ if (auto truncOp = getOperand().getDefiningOp<arith::TruncIOp>()) {
+ // Preserve a flag only if both truncations are lossless in that signedness.
+ setOverflowFlags(getOverflowFlags() & truncOp.getOverflowFlags());
+ setOperand(truncOp.getIn());
return getResult();
}
diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir
index 5a376e29176a0..128ff3d3b98aa 100644
--- a/mlir/test/Dialect/Arith/canonicalize.mlir
+++ b/mlir/test/Dialect/Arith/canonicalize.mlir
@@ -1668,6 +1668,58 @@ func.func @truncTrunc(%arg0: i64) -> i8 {
return %tr2 : i8
}
+// The first truncation may discard nonzero bits. For example, 65537 truncates
+// to 1 without poison, but a direct flagged truncation would produce poison.
+// CHECK-LABEL: @truncTruncDropFlags(
+// CHECK-SAME: %[[ARG:.*]]: i32
+// CHECK-NEXT: %[[RES:.*]] = arith.trunci %[[ARG]] : i32 to i8
+// CHECK-NEXT: return %[[RES]] : i8
+func.func @truncTruncDropFlags(%arg0: i32) -> i8 {
+ %tr1 = arith.trunci %arg0 : i32 to i16
+ %tr2 = arith.trunci %tr1 overflow<nsw, nuw> : i16 to i8
+ return %tr2 : i8
+}
+
+// CHECK-LABEL: @truncTruncNsw(
+// CHECK-SAME: %[[ARG:.*]]: i32
+// CHECK-NEXT: %[[RES:.*]] = arith.trunci %[[ARG]] overflow<nsw> : i32 to i8
+// CHECK-NEXT: return %[[RES]] : i8
+func.func @truncTruncNsw(%arg0: i32) -> i8 {
+ %tr1 = arith.trunci %arg0 overflow<nsw> : i32 to i16
+ %tr2 = arith.trunci %tr1 overflow<nsw, nuw> : i16 to i8
+ return %tr2 : i8
+}
+
+// CHECK-LABEL: @truncTruncNuw(
+// CHECK-SAME: %[[ARG:.*]]: i32
+// CHECK-NEXT: %[[RES:.*]] = arith.trunci %[[ARG]] overflow<nuw> : i32 to i8
+// CHECK-NEXT: return %[[RES]] : i8
+func.func @truncTruncNuw(%arg0: i32) -> i8 {
+ %tr1 = arith.trunci %arg0 overflow<nuw> : i32 to i16
+ %tr2 = arith.trunci %tr1 overflow<nsw, nuw> : i16 to i8
+ return %tr2 : i8
+}
+
+// CHECK-LABEL: @truncTruncBothFlags(
+// CHECK-SAME: %[[ARG:.*]]: i32
+// CHECK-NEXT: %[[RES:.*]] = arith.trunci %[[ARG]] overflow<nsw, nuw> : i32 to i8
+// CHECK-NEXT: return %[[RES]] : i8
+func.func @truncTruncBothFlags(%arg0: i32) -> i8 {
+ %tr1 = arith.trunci %arg0 overflow<nsw, nuw> : i32 to i16
+ %tr2 = arith.trunci %tr1 overflow<nsw, nuw> : i16 to i8
+ return %tr2 : i8
+}
+
+// CHECK-LABEL: @truncTruncDisjointFlags(
+// CHECK-SAME: %[[ARG:.*]]: i32
+// CHECK-NEXT: %[[RES:.*]] = arith.trunci %[[ARG]] : i32 to i8
+// CHECK-NEXT: return %[[RES]] : i8
+func.func @truncTruncDisjointFlags(%arg0: i32) -> i8 {
+ %tr1 = arith.trunci %arg0 overflow<nsw> : i32 to i16
+ %tr2 = arith.trunci %tr1 overflow<nuw> : i16 to i8
+ return %tr2 : i8
+}
+
// CHECK-LABEL: @truncFPConstant
// CHECK: %[[cres:.+]] = arith.constant 1.000000e+00 : bf16
// CHECK: return %[[cres]]
More information about the Mlir-commits
mailing list