[llvm] [GlobalISel] Clear nsw flags when converting sub to add. (PR #137288)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 24 23:49:02 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-aarch64
Author: David Green (davemgreen)
<details>
<summary>Changes</summary>
As shown in https://alive2.llvm.org/ce/z/PVwcTL we need to clear the nsw flags too when converting a sub to a add if the constant is INT_MIN.
Fixes #<!-- -->137254
---
Full diff: https://github.com/llvm/llvm-project/pull/137288.diff
3 Files Affected:
- (modified) llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp (+2)
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir (+45)
- (modified) llvm/test/CodeGen/AArch64/sub1.ll (+14)
``````````diff
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 333f0c17bacc5..5191360c7718a 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2112,6 +2112,8 @@ bool CombinerHelper::matchCombineSubToAdd(MachineInstr &MI,
MI.setDesc(B.getTII().get(TargetOpcode::G_ADD));
MI.getOperand(2).setReg(NegCst.getReg(0));
MI.clearFlag(MachineInstr::MIFlag::NoUWrap);
+ if (Imm.isMinSignedValue())
+ MI.clearFlags(MachineInstr::MIFlag::NoSWrap);
Observer.changedInstr(MI);
};
return true;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir
index 4c3faa9403909..de95527ceb1a2 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizercombiner-trivial-arith.mir
@@ -551,3 +551,48 @@ body: |
RET_ReallyLR implicit $w0
...
+---
+name: sub_to_add_nsw_128
+body: |
+ bb.0:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: sub_to_add_nsw_128
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s32) = COPY $w0
+ ; CHECK-NEXT: %b:_(s8) = G_TRUNC %a(s32)
+ ; CHECK-NEXT: %c:_(s8) = G_CONSTANT i8 -128
+ ; CHECK-NEXT: %add:_(s8) = G_ADD %b, %c
+ ; CHECK-NEXT: %d:_(s32) = G_ZEXT %add(s8)
+ ; CHECK-NEXT: $w0 = COPY %d(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(s32) = COPY $w0
+ %b:_(s8) = G_TRUNC %a
+ %c:_(s8) = G_CONSTANT i8 -128
+ %add:_(s8) = nsw nuw G_SUB %b, %c
+ %d:_(s32) = G_ZEXT %add
+ $w0 = COPY %d
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: sub_to_add_nsw_intmin
+body: |
+ bb.0:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: sub_to_add_nsw_intmin
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s32) = COPY $w0
+ ; CHECK-NEXT: %c:_(s32) = G_CONSTANT i32 -2147483648
+ ; CHECK-NEXT: %add:_(s32) = G_ADD %a, %c
+ ; CHECK-NEXT: $w0 = COPY %add(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(s32) = COPY $w0
+ %c:_(s32) = G_CONSTANT i32 -2147483648
+ %add:_(s32) = nsw nuw G_SUB %a, %c
+ $w0 = COPY %add
+ RET_ReallyLR implicit $x0
+...
diff --git a/llvm/test/CodeGen/AArch64/sub1.ll b/llvm/test/CodeGen/AArch64/sub1.ll
index 02893e2b63287..c359be57c27da 100644
--- a/llvm/test/CodeGen/AArch64/sub1.ll
+++ b/llvm/test/CodeGen/AArch64/sub1.ll
@@ -117,3 +117,17 @@ define <4 x i32> @masked_sub_v4i32(<4 x i32> %x) {
%m = sub <4 x i32> <i32 511, i32 511, i32 511, i32 511>, %a
ret <4 x i32> %m
}
+
+define i32 @pr137254(i32 %0) {
+; CHECK-LABEL: pr137254:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov w8, #-2147483648 // =0x80000000
+; CHECK-NEXT: add w8, w0, w8
+; CHECK-NEXT: cmp w8, #0
+; CHECK-NEXT: cset w0, gt
+; CHECK-NEXT: ret
+ %2 = sub nsw i32 %0, -2147483648
+ %3 = icmp sgt i32 %2, 0
+ %4 = select i1 %3, i32 1, i32 0
+ ret i32 %4
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/137288
More information about the llvm-commits
mailing list