[Mlir-commits] [mlir] [mlir][arith] Drop `nsw` when canonicalizing shifted truncations (PR #233176)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Sat Oct 17 20:29:11 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mlir-arith
Author: Matthias Springer (matthias-springer)
<details>
<summary>Changes</summary>
Assisted-by: Codex
---
Full diff: https://github.com/llvm/llvm-project/pull/233176.diff
2 Files Affected:
- (modified) mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td (+12-2)
- (modified) mlir/test/Dialect/Arith/canonicalize.mlir (+54)
``````````diff
diff --git a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td
index 2615bcca23e35c..8da7efbef40a8f 100644
--- a/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td
+++ b/mlir/lib/Dialect/Arith/IR/ArithCanonicalization.td
@@ -45,6 +45,11 @@ def XorIntAttrs : NativeCodeCall<"xorIntegerAttrs($_builder, $0, $1, $2)">;
// Merge overflow flags from 2 ops, selecting the most conservative combination.
def MergeOverflow : NativeCodeCall<"mergeOverflowFlags($0, $1)">;
+// Drop the signed no-wrap flag.
+def DropNSW : NativeCodeCall<
+ "IntegerOverflowFlagsAttr::get($_builder.getContext(), "
+ "$0.getValue() & ~IntegerOverflowFlags::nsw)">;
+
// Default overflow flag (all wraparounds allowed).
defvar DefOverflow = ConstantEnumCase<Arith_IntegerOverflowAttr, "none">;
@@ -486,10 +491,15 @@ def TruncIExtUIToExtUI :
(ValueWiderThan $tr, $x)]>;
// trunci(shrsi(x, c)) -> trunci(shrui(x, c))
+// Drop nsw because the zero-filled bits may differ from the truncated result's
+// sign bit. These bits satisfy nuw, and exact is unaffected.
def TruncIShrSIToTrunciShrUI :
Pat<(Arith_TruncIOp:$tr
- (Arith_ShRSIOp $x, (ConstantLikeMatcher TypedAttrInterface:$c0), $exact), $overflow),
- (Arith_TruncIOp (Arith_ShRUIOp $x, (Arith_ConstantOp (cast<"TypedAttr"> $c0)), $exact), $overflow),
+ (Arith_ShRSIOp $x, (ConstantLikeMatcher TypedAttrInterface:$c0), $exact),
+ $overflow),
+ (Arith_TruncIOp
+ (Arith_ShRUIOp $x, (Arith_ConstantOp (cast<"TypedAttr"> $c0)), $exact),
+ (DropNSW $overflow)),
[(TruncationMatchesShiftAmount $x, $tr, $c0)]>;
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/Dialect/Arith/canonicalize.mlir b/mlir/test/Dialect/Arith/canonicalize.mlir
index 0da65a4a0f4028..a85c4ca7f0f002 100644
--- a/mlir/test/Dialect/Arith/canonicalize.mlir
+++ b/mlir/test/Dialect/Arith/canonicalize.mlir
@@ -4578,6 +4578,60 @@ func.func @truncIShrSIExactToTrunciShrUIExact(%a: i64) -> i32 {
return %hi : i32
}
+// For %a = -256, the arithmetic shift produces -1, which fits in signed i8.
+// The logical shift produces 255, so retaining nsw would introduce poison.
+// CHECK-LABEL: @truncIShrSIToTrunciShrUI_nsw(
+// CHECK-SAME: %[[A:.+]]: i16
+// CHECK-NEXT: %[[C8:.+]] = arith.constant 8 : i16
+// CHECK-NEXT: %[[SHR:.+]] = arith.shrui %[[A]], %[[C8]] : i16
+// CHECK-NEXT: %[[TRU:.+]] = arith.trunci %[[SHR]] : i16 to i8
+// CHECK-NEXT: return %[[TRU]] : i8
+func.func @truncIShrSIToTrunciShrUI_nsw(%a: i16) -> i8 {
+ %c8 = arith.constant 8 : i16
+ %sh = arith.shrsi %a, %c8 : i16
+ %hi = arith.trunci %sh overflow<nsw> : i16 to i8
+ return %hi : i8
+}
+
+// CHECK-LABEL: @truncIShrSIToTrunciShrUI_nuw(
+// CHECK-SAME: %[[A:.+]]: i16
+// CHECK-NEXT: %[[C8:.+]] = arith.constant 8 : i16
+// CHECK-NEXT: %[[SHR:.+]] = arith.shrui %[[A]], %[[C8]] : i16
+// CHECK-NEXT: %[[TRU:.+]] = arith.trunci %[[SHR]] overflow<nuw> : i16 to i8
+// CHECK-NEXT: return %[[TRU]] : i8
+func.func @truncIShrSIToTrunciShrUI_nuw(%a: i16) -> i8 {
+ %c8 = arith.constant 8 : i16
+ %sh = arith.shrsi %a, %c8 : i16
+ %hi = arith.trunci %sh overflow<nuw> : i16 to i8
+ return %hi : i8
+}
+
+// CHECK-LABEL: @truncIShrSIToTrunciShrUI_exact_nsw_nuw(
+// CHECK-SAME: %[[A:.+]]: i16
+// CHECK-NEXT: %[[C8:.+]] = arith.constant 8 : i16
+// CHECK-NEXT: %[[SHR:.+]] = arith.shrui %[[A]], %[[C8]] exact : i16
+// CHECK-NEXT: %[[TRU:.+]] = arith.trunci %[[SHR]] overflow<nuw> : i16 to i8
+// CHECK-NEXT: return %[[TRU]] : i8
+func.func @truncIShrSIToTrunciShrUI_exact_nsw_nuw(%a: i16) -> i8 {
+ %c8 = arith.constant 8 : i16
+ %sh = arith.shrsi %a, %c8 exact : i16
+ %hi = arith.trunci %sh overflow<nsw, nuw> : i16 to i8
+ return %hi : i8
+}
+
+// CHECK-LABEL: @truncIShrSIToTrunciShrUI_nsw_vector(
+// CHECK-SAME: %[[A:.+]]: vector<2xi16>
+// CHECK-NEXT: %[[C8:.+]] = arith.constant dense<8> : vector<2xi16>
+// CHECK-NEXT: %[[SHR:.+]] = arith.shrui %[[A]], %[[C8]] : vector<2xi16>
+// CHECK-NEXT: %[[TRU:.+]] = arith.trunci %[[SHR]] : vector<2xi16> to vector<2xi8>
+// CHECK-NEXT: return %[[TRU]] : vector<2xi8>
+func.func @truncIShrSIToTrunciShrUI_nsw_vector(%a: vector<2xi16>) -> vector<2xi8> {
+ %c8 = arith.constant dense<8> : vector<2xi16>
+ %sh = arith.shrsi %a, %c8 : vector<2xi16>
+ %hi = arith.trunci %sh overflow<nsw> : vector<2xi16> to vector<2xi8>
+ return %hi : vector<2xi8>
+}
+
// CHECK-LABEL: @truncIShrSIToTrunciShrUIBadShiftAmt1
// CHECK: arith.shrsi
func.func @truncIShrSIToTrunciShrUIBadShiftAmt1(%a: i64) -> i32 {
``````````
</details>
https://github.com/llvm/llvm-project/pull/233176
More information about the Mlir-commits
mailing list