[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