https://github.com/harrisonGPU updated https://github.com/llvm/llvm-project/pull/232626
>From 8f6d4791d627072e5e2b6a4a89f79880e8cee5d4 Mon Sep 17 00:00:00 2001 From: Harrison Hao <[email protected]> Date: Fri, 16 Oct 2026 14:35:13 +0800 Subject: [PATCH 1/3] [InstCombine] Canonicalize atomicrmw sub of a constant to add 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 --- llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp | 7 +++++++ llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) 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 9d304429335d5..147ae828fdac1 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 >From 51f427b07d7448195c2b108227eb1440b5ce225e Mon Sep 17 00:00:00 2001 From: Harrison Hao <[email protected]> Date: Fri, 16 Oct 2026 16:00:35 +0800 Subject: [PATCH 2/3] Fix clang lit test --- clang/test/CodeGen/ms-intrinsics-other.c | 8 ++++---- clang/test/CodeGen/ms-intrinsics.c | 24 ++++++++++++------------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clang/test/CodeGen/ms-intrinsics-other.c b/clang/test/CodeGen/ms-intrinsics-other.c index 9f183aee85824..6f55bcb86fdd6 100644 --- a/clang/test/CodeGen/ms-intrinsics-other.c +++ b/clang/test/CodeGen/ms-intrinsics-other.c @@ -178,7 +178,7 @@ LONG test_InterlockedDecrement(LONG volatile *Addend) { return _InterlockedDecrement(Addend); } // CHECK: define{{.*}}i32 @test_InterlockedDecrement(ptr{{.*}}%Addend){{.*}}{ -// CHECK: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 seq_cst, align 4 +// CHECK: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 seq_cst, align 4 // CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK: ret i32 [[RESULT]] // CHECK: } @@ -427,7 +427,7 @@ LONG test_InterlockedDecrement_acq(LONG volatile *Addend) { return _InterlockedDecrement_acq(Addend); } // CHECK-ARM: define{{.*}}i32 @test_InterlockedDecrement_acq(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 acquire, align 4 +// CHECK-ARM: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 acquire, align 4 // CHECK-ARM: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK-ARM: ret i32 [[RESULT]] // CHECK-ARM: } @@ -436,7 +436,7 @@ LONG test_InterlockedDecrement_rel(LONG volatile *Addend) { return _InterlockedDecrement_rel(Addend); } // CHECK-ARM: define{{.*}}i32 @test_InterlockedDecrement_rel(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 release, align 4 +// CHECK-ARM: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 release, align 4 // CHECK-ARM: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK-ARM: ret i32 [[RESULT]] // CHECK-ARM: } @@ -445,7 +445,7 @@ LONG test_InterlockedDecrement_nf(LONG volatile *Addend) { return _InterlockedDecrement_nf(Addend); } // CHECK-ARM: define{{.*}}i32 @test_InterlockedDecrement_nf(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 monotonic, align 4 +// CHECK-ARM: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 monotonic, align 4 // CHECK-ARM: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK-ARM: ret i32 [[RESULT]] // CHECK-ARM: } diff --git a/clang/test/CodeGen/ms-intrinsics.c b/clang/test/CodeGen/ms-intrinsics.c index 8b719ef8cc1fd..d15310e41a267 100644 --- a/clang/test/CodeGen/ms-intrinsics.c +++ b/clang/test/CodeGen/ms-intrinsics.c @@ -572,7 +572,7 @@ short test_InterlockedDecrement16(short volatile *Addend) { return _InterlockedDecrement16(Addend); } // CHECK: define{{.*}}i16 @test_InterlockedDecrement16(ptr{{.*}}%Addend){{.*}}{ -// CHECK: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i16 1 seq_cst, align 2 +// CHECK: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i16 -1 seq_cst, align 2 // CHECK: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1 // CHECK: ret i16 [[RESULT]] // CHECK: } @@ -581,7 +581,7 @@ long test_InterlockedDecrement(long volatile *Addend) { return _InterlockedDecrement(Addend); } // CHECK: define{{.*}}i32 @test_InterlockedDecrement(ptr{{.*}}%Addend){{.*}}{ -// CHECK: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 seq_cst, align 4 +// CHECK: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 seq_cst, align 4 // CHECK: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK: ret i32 [[RESULT]] // CHECK: } @@ -677,7 +677,7 @@ __int64 test_InterlockedDecrement64(__int64 volatile *Addend) { return _InterlockedDecrement64(Addend); } // CHECK: define{{.*}}i64 @test_InterlockedDecrement64(ptr{{.*}}%Addend){{.*}}{ -// CHECK: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i64 1 seq_cst, align 8 +// CHECK: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i64 -1 seq_cst, align 8 // CHECK: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1 // CHECK: ret i64 [[RESULT]] // CHECK: } @@ -1385,7 +1385,7 @@ short test_InterlockedDecrement16_acq(short volatile *Addend) { return _InterlockedDecrement16_acq(Addend); } // CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedDecrement16_acq(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i16 1 acquire, align 2 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i16 -1 acquire, align 2 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1 // CHECK-ARM-ARM64: ret i16 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1394,7 +1394,7 @@ short test_InterlockedDecrement16_rel(short volatile *Addend) { return _InterlockedDecrement16_rel(Addend); } // CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedDecrement16_rel(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i16 1 release, align 2 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i16 -1 release, align 2 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1 // CHECK-ARM-ARM64: ret i16 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1403,7 +1403,7 @@ short test_InterlockedDecrement16_nf(short volatile *Addend) { return _InterlockedDecrement16_nf(Addend); } // CHECK-ARM-ARM64: define{{.*}}i16 @test_InterlockedDecrement16_nf(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i16 1 monotonic, align 2 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i16 -1 monotonic, align 2 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i16 [[TMP]], -1 // CHECK-ARM-ARM64: ret i16 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1412,7 +1412,7 @@ long test_InterlockedDecrement_acq(long volatile *Addend) { return _InterlockedDecrement_acq(Addend); } // CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedDecrement_acq(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 acquire, align 4 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 acquire, align 4 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK-ARM-ARM64: ret i32 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1421,7 +1421,7 @@ long test_InterlockedDecrement_rel(long volatile *Addend) { return _InterlockedDecrement_rel(Addend); } // CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedDecrement_rel(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 release, align 4 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 release, align 4 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK-ARM-ARM64: ret i32 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1430,7 +1430,7 @@ long test_InterlockedDecrement_nf(long volatile *Addend) { return _InterlockedDecrement_nf(Addend); } // CHECK-ARM-ARM64: define{{.*}}i32 @test_InterlockedDecrement_nf(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i32 1 monotonic, align 4 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i32 -1 monotonic, align 4 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i32 [[TMP]], -1 // CHECK-ARM-ARM64: ret i32 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1439,7 +1439,7 @@ __int64 test_InterlockedDecrement64_acq(__int64 volatile *Addend) { return _InterlockedDecrement64_acq(Addend); } // CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedDecrement64_acq(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i64 1 acquire, align 8 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i64 -1 acquire, align 8 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1 // CHECK-ARM-ARM64: ret i64 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1448,7 +1448,7 @@ __int64 test_InterlockedDecrement64_rel(__int64 volatile *Addend) { return _InterlockedDecrement64_rel(Addend); } // CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedDecrement64_rel(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i64 1 release, align 8 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i64 -1 release, align 8 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1 // CHECK-ARM-ARM64: ret i64 [[RESULT]] // CHECK-ARM-ARM64: } @@ -1457,7 +1457,7 @@ __int64 test_InterlockedDecrement64_nf(__int64 volatile *Addend) { return _InterlockedDecrement64_nf(Addend); } // CHECK-ARM-ARM64: define{{.*}}i64 @test_InterlockedDecrement64_nf(ptr{{.*}}%Addend){{.*}}{ -// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw sub ptr %Addend, i64 1 monotonic, align 8 +// CHECK-ARM-ARM64: [[TMP:%[0-9]+]] = atomicrmw add ptr %Addend, i64 -1 monotonic, align 8 // CHECK-ARM-ARM64: [[RESULT:%[0-9]+]] = add i64 [[TMP]], -1 // CHECK-ARM-ARM64: ret i64 [[RESULT]] // CHECK-ARM-ARM64: } >From 94f4c92b704ddc22c648612677e38539eef8c160 Mon Sep 17 00:00:00 2001 From: Harrison Hao <[email protected]> Date: Sat, 17 Oct 2026 11:07:27 +0800 Subject: [PATCH 3/3] Support vector --- llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp | 7 ++++--- llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp index f9eab910fc56a..0dcf1585aef96 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAtomicRMW.cpp @@ -136,10 +136,11 @@ Instruction *InstCombinerImpl::visitAtomicRMWInst(AtomicRMWInst &RMWI) { } // atomicrmw sub(ptr, C) -> atomicrmw add(ptr, -C) - const APInt *C; - if (Op == AtomicRMWInst::Sub && match(Val, m_APInt(C)) && !C->isZero()) { + Constant *C; + if (Op == AtomicRMWInst::Sub && match(Val, m_ImmConstant(C)) && + !C->isNullValue()) { RMWI.setOperation(AtomicRMWInst::Add); - return replaceOperand(RMWI, 1, ConstantInt::get(RMWI.getType(), -*C)); + return replaceOperand(RMWI, 1, ConstantExpr::getNeg(C)); } } diff --git a/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll b/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll index 147ae828fdac1..0fbee0d6ce878 100644 --- a/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll +++ b/llvm/test/Transforms/InstCombine/atomicrmw-add-neg.ll @@ -139,7 +139,7 @@ define i64 @neg_fn_sub_constexpr(ptr %a) { define <2 x i32> @fn_sub_const_vec(ptr %a) { ; CHECK-LABEL: define <2 x i32> @fn_sub_const_vec( ; CHECK-SAME: ptr [[A:%.*]]) { -; CHECK-NEXT: [[OLD:%.*]] = atomicrmw sub ptr [[A]], <2 x i32> splat (i32 5) monotonic, align 8 +; CHECK-NEXT: [[OLD:%.*]] = atomicrmw add ptr [[A]], <2 x i32> splat (i32 -5) monotonic, align 8 ; CHECK-NEXT: ret <2 x i32> [[OLD]] ; %old = atomicrmw sub ptr %a, <2 x i32> splat (i32 5) monotonic @@ -149,7 +149,7 @@ define <2 x i32> @fn_sub_const_vec(ptr %a) { define <2 x i64> @fn_sub_const_vec_elementwise(ptr %a) { ; CHECK-LABEL: define <2 x i64> @fn_sub_const_vec_elementwise( ; CHECK-SAME: ptr [[A:%.*]]) { -; CHECK-NEXT: [[OLD:%.*]] = atomicrmw elementwise sub ptr [[A]], <2 x i64> <i64 1, i64 -9223372036854775808> monotonic, align 16 +; CHECK-NEXT: [[OLD:%.*]] = atomicrmw elementwise add ptr [[A]], <2 x i64> <i64 -1, i64 -9223372036854775808> monotonic, align 16 ; CHECK-NEXT: ret <2 x i64> [[OLD]] ; %old = atomicrmw elementwise sub ptr %a, <2 x i64> <i64 1, i64 -9223372036854775808> monotonic @@ -159,7 +159,7 @@ define <2 x i64> @fn_sub_const_vec_elementwise(ptr %a) { define <2 x i32> @fn_sub_const_vec_poison(ptr %a) { ; CHECK-LABEL: define <2 x i32> @fn_sub_const_vec_poison( ; CHECK-SAME: ptr [[A:%.*]]) { -; CHECK-NEXT: [[OLD:%.*]] = atomicrmw sub ptr [[A]], <2 x i32> <i32 1, i32 poison> monotonic, align 8 +; CHECK-NEXT: [[OLD:%.*]] = atomicrmw add ptr [[A]], <2 x i32> <i32 -1, i32 poison> monotonic, align 8 ; CHECK-NEXT: ret <2 x i32> [[OLD]] ; %old = atomicrmw sub ptr %a, <2 x i32> <i32 1, i32 poison> monotonic _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
