[llvm-branch-commits] [llvm] [InstCombine] Canonicalize atomicrmw sub of a constant to add (PR #232626)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Oct 16 00:05:06 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Harrison Hao (harrisonGPU)

<details>
<summary>Changes</summary>

Rewrite `atomicrmw sub ptr, C` as `atomicrmw add ptr, -C`. This
matches the canonical form InstCombine already uses for plain `sub`.
In wrapping arithmetic $old - C = old + (-C)$, so both the stored
value and the returned old value stay the same, including when C is
`INT_MIN`. Ordering, syncscope and metadata are kept.

```llvm
; before
%old = atomicrmw sub ptr %p, i32 1 syncscope("agent") monotonic
; after
%old = atomicrmw add ptr %p, i32 -1 syncscope("agent") monotonic
```
This benefits AMDGPU, for example: https://godbolt.org/z/39xsYro3o

---

<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

---
Full diff: https://github.com/llvm/llvm-project/pull/232626.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp (+7) 
- (modified) llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll (+2-2) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp
index 4d6b0684abe4d..f9eab910fc56a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp
@@ -134,6 +134,13 @@ Instruction *InstCombinerImpl::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
                                                  : AtomicRMWInst::Add);
       return replaceOperand(RMWI, 1, X);
     }
+
+    // atomicrmw sub(ptr, C) -> atomicrmw add(ptr, -C)
+    const APInt *C;
+    if (Op == AtomicRMWInst::Sub && match(Val, m_APInt(C)) && !C->isZero()) {
+      RMWI.setOperation(AtomicRMWInst::Add);
+      return replaceOperand(RMWI, 1, ConstantInt::get(RMWI.getType(), -*C));
+    }
   }
 
   if (!isIdempotentRMW(RMWI))
diff --git a/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll b/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll
index 05f38e749910d..48212c9df7a8d 100644
--- a/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll
+++ b/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll
@@ -97,7 +97,7 @@ define i64 @fn_add_of_two_vars(ptr %p, i64 %a, i64 %b) {
 define i32 @fn_sub_const(ptr %a) {
 ; CHECK-LABEL: define i32 @fn_sub_const(
 ; CHECK-SAME: ptr [[A:%.*]]) {
-; CHECK-NEXT:    [[OLD:%.*]] = atomicrmw sub ptr [[A]], i32 5 syncscope("agent") acq_rel, align 4
+; CHECK-NEXT:    [[OLD:%.*]] = atomicrmw add ptr [[A]], i32 -5 syncscope("agent") acq_rel, align 4
 ; CHECK-NEXT:    ret i32 [[OLD]]
 ;
   %old = atomicrmw sub ptr %a, i32 5 syncscope("agent") acq_rel
@@ -107,7 +107,7 @@ define i32 @fn_sub_const(ptr %a) {
 define i64 @fn_sub_const_int_min(ptr %a) {
 ; CHECK-LABEL: define i64 @fn_sub_const_int_min(
 ; CHECK-SAME: ptr [[A:%.*]]) {
-; CHECK-NEXT:    [[OLD:%.*]] = atomicrmw sub ptr [[A]], i64 -9223372036854775808 monotonic, align 8
+; CHECK-NEXT:    [[OLD:%.*]] = atomicrmw add ptr [[A]], i64 -9223372036854775808 monotonic, align 8
 ; CHECK-NEXT:    ret i64 [[OLD]]
 ;
   %old = atomicrmw sub ptr %a, i64 -9223372036854775808 monotonic

``````````

</details>


https://github.com/llvm/llvm-project/pull/232626


More information about the llvm-branch-commits mailing list