[llvm] [PowerPC] Remove memory attributes on larx/stcx (PR #186395)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 25 02:12:19 PDT 2026
https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/186395
>From 8a2b7c8e2b32252ab2cfbac30a288b9e7f688f8b Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Fri, 13 Mar 2026 14:36:47 +0100
Subject: [PATCH 1/2] [PowerPC] Remove memory attributes on larx/stcx
Modelling these as ll/sc style instructions as `memory(argmem: read)`
and `memory(argmem: write)` is not correct. The read/write additional
microarchitectural state, so they should at least read/write
`inaccessiblemem` as well. To be conservative, I've dropped the
memory attributes entirely, matching how AArch64 handles the
equivalent instructions.
---
llvm/include/llvm/IR/IntrinsicsPowerPC.td | 24 ++++++----------
llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 4 +--
llvm/lib/Target/PowerPC/PPCInstrInfo.td | 4 +--
llvm/test/CodeGen/PowerPC/atomics.ll | 2 +-
llvm/test/CodeGen/PowerPC/ldst-16-byte.mir | 33 +++++++++++-----------
5 files changed, 30 insertions(+), 37 deletions(-)
diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
index bd8fb9e9a564d..767b9d033f954 100644
--- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -1918,33 +1918,25 @@ let TargetPrefix = "ppc" in {
def int_ppc_iospace_eieio : ClangBuiltin<"__builtin_ppc_iospace_eieio">,
Intrinsic<[],[],[]>;
def int_ppc_lbarx :
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty],
- [IntrReadMem, IntrArgMemOnly]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], []>;
def int_ppc_lharx :
- Intrinsic<[llvm_i32_ty],[llvm_ptr_ty],
- [IntrReadMem, IntrArgMemOnly]>;
+ Intrinsic<[llvm_i32_ty],[llvm_ptr_ty], []>;
def int_ppc_lwarx :
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty],
- [IntrReadMem, IntrArgMemOnly]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], []>;
def int_ppc_ldarx :
- Intrinsic<[llvm_i64_ty],[llvm_ptr_ty],
- [IntrReadMem, IntrArgMemOnly]>;
+ Intrinsic<[llvm_i64_ty],[llvm_ptr_ty], []>;
def int_ppc_stdcx :
ClangBuiltin<"__builtin_ppc_stdcx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i64_ty],
- [IntrWriteMem, IntrArgMemOnly, IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrNoDuplicate]>;
def int_ppc_stwcx :
ClangBuiltin<"__builtin_ppc_stwcx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
- [IntrWriteMem, IntrArgMemOnly]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrNoDuplicate]>;
def int_ppc_sthcx :
- Intrinsic<[llvm_i32_ty], [ llvm_ptr_ty, llvm_i32_ty],
- [IntrWriteMem, IntrArgMemOnly, IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [ llvm_ptr_ty, llvm_i32_ty], [IntrNoDuplicate]>;
def int_ppc_stbcx :
ClangBuiltin<"__builtin_ppc_stbcx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
- [IntrWriteMem, IntrArgMemOnly, IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrNoDuplicate]>;
def int_ppc_dcbtstt : ClangBuiltin<"__builtin_ppc_dcbtstt">,
Intrinsic<[], [llvm_ptr_ty],
[IntrArgMemOnly, NoCapture<ArgIndex<0>>]>;
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 8089c6077860d..a973654c22c38 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -307,7 +307,7 @@ let Defs = [CR0] in {
}
// Instructions to support atomic operations
-let mayLoad = 1, hasSideEffects = 0 in {
+let mayLoad = 1, mayStore = 1, hasSideEffects = 1 in {
def LDARX : XForm_1_memOp<31, 84, (outs g8rc:$RST), (ins (memrr $RA, $RB):$addr),
"ldarx $RST, $addr", IIC_LdStLDARX, []>;
// TODO: Add scheduling info.
@@ -348,7 +348,7 @@ def LDAT_COND_PSEUDO : PPCCustomInserterPseudo <
[(set i64:$dst, (int_ppc_amo_ldat_cond ptr_rc_nor0:$ptr,
u5imm_timm:$fc))]>;
-let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
+let Defs = [CR0], mayStore = 1, mayLoad = 1, hasSideEffects = 1 in {
def STDCX : XForm_1_memOp<31, 214, (outs), (ins g8rc:$RST, (memrr $RA, $RB):$addr),
"stdcx. $RST, $addr", IIC_LdStSTDCX, []>, isRecordForm;
// TODO: Add scheduling info.
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 3271e4d279f56..865efee9906b7 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -2130,7 +2130,7 @@ def : Pat<(PPCatomicCmpSwap_16 ForceXForm:$ptr, i32:$old, i32:$new),
(ATOMIC_CMP_SWAP_I16 ForceXForm:$ptr, i32:$old, i32:$new)>;
// Instructions to support atomic operations
-let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in {
+let mayLoad = 1, mayStore = 1, hasSideEffects = 1 in {
def LBARX : XForm_1_memOp<31, 52, (outs gprc:$RST), (ins (memrr $RA, $RB):$addr),
"lbarx $RST, $addr", IIC_LdStLWARX, []>,
Requires<[HasPartwordAtomics]>;
@@ -2176,7 +2176,7 @@ def LWAT_COND_PSEUDO : PPCCustomInserterPseudo <
"#LWAT_COND_PSEUDO",
[(set i32:$dst, (int_ppc_amo_lwat_cond ptr_rc_nor0:$ptr, u5imm_timm:$fc))]>;
-let Defs = [CR0], mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
+let Defs = [CR0], mayStore = 1, mayLoad = 1, hasSideEffects = 1 in {
def STBCX : XForm_1_memOp<31, 694, (outs), (ins gprc:$RST, (memrr $RA, $RB):$addr),
"stbcx. $RST, $addr", IIC_LdStSTWCX, []>,
isRecordForm, Requires<[HasPartwordAtomics]>;
diff --git a/llvm/test/CodeGen/PowerPC/atomics.ll b/llvm/test/CodeGen/PowerPC/atomics.ll
index 54a35dab2a422..af2b8646d18ae 100644
--- a/llvm/test/CodeGen/PowerPC/atomics.ll
+++ b/llvm/test/CodeGen/PowerPC/atomics.ll
@@ -315,8 +315,8 @@ define i64 @cas_weak_i64_release_monotonic(ptr %mem) {
; PPC64-NEXT: cmpldi r3, 0
; PPC64-NEXT: bnelr- cr0
; PPC64-NEXT: # %bb.1: # %cmpxchg.fencedstore
-; PPC64-NEXT: li r5, 1
; PPC64-NEXT: lwsync
+; PPC64-NEXT: li r5, 1
; PPC64-NEXT: stdcx. r5, 0, r4
; PPC64-NEXT: blr
%val = cmpxchg weak ptr %mem, i64 0, i64 1 release monotonic
diff --git a/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir b/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir
index e000fece687b8..06dcc720d5643 100644
--- a/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir
+++ b/llvm/test/CodeGen/PowerPC/ldst-16-byte.mir
@@ -98,31 +98,31 @@ body: |
; CHECK-NEXT: renamable $g8p4 = LQARX $x5, $x6
; CHECK-NEXT: STD killed $x8, -176, $x1
; CHECK-NEXT: STD killed $x9, -168, $x1
- ; CHECK-NEXT: renamable $g8p1 = LQARX $x3, renamable $x4
- ; CHECK-NEXT: renamable $g8p4 = LQARX renamable $x7, renamable $x4
+ ; CHECK-NEXT: renamable $g8p14 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p4 = LQARX $x3, renamable $x4
; CHECK-NEXT: STD killed $x8, -192, $x1
; CHECK-NEXT: STD killed $x9, -184, $x1
- ; CHECK-NEXT: renamable $g8p4 = LQARX renamable $x7, renamable $x4
+ ; CHECK-NEXT: renamable $g8p4 = LQARX $x3, renamable $x4
; CHECK-NEXT: STD killed $x8, -208, $x1
; CHECK-NEXT: STD killed $x9, -200, $x1
- ; CHECK-NEXT: renamable $g8p4 = LQARX renamable $x7, renamable $x4
+ ; CHECK-NEXT: renamable $g8p4 = LQARX $x3, renamable $x4
; CHECK-NEXT: STD killed $x8, -224, $x1
; CHECK-NEXT: STD killed $x9, -216, $x1
- ; CHECK-NEXT: renamable $g8p12 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p11 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p10 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p9 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p8 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p7 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p15 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p13 = LQARX renamable $x7, renamable $x4
- ; CHECK-NEXT: renamable $g8p14 = LQARX renamable $x7, renamable $x4
+ ; CHECK-NEXT: renamable $g8p12 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p11 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p10 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p9 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p8 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p7 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p15 = LQARX $x3, renamable $x4
+ ; CHECK-NEXT: renamable $g8p1 = LQARX $x3, renamable $x4
; CHECK-NEXT: renamable $g8p5 = LQARX renamable $x7, renamable $x4
; CHECK-NEXT: renamable $g8p4 = LQARX renamable $x7, renamable $x4
+ ; CHECK-NEXT: renamable $g8p13 = LQARX renamable $x7, renamable $x4
+ ; CHECK-NEXT: STQCX killed renamable $g8p13, renamable $x7, renamable $x4, implicit-def dead $cr0
; CHECK-NEXT: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0
; CHECK-NEXT: STQCX killed renamable $g8p5, renamable $x7, renamable $x4, implicit-def dead $cr0
- ; CHECK-NEXT: STQCX killed renamable $g8p14, renamable $x7, renamable $x4, implicit-def dead $cr0
- ; CHECK-NEXT: STQCX killed renamable $g8p13, renamable $x7, renamable $x4, implicit-def dead $cr0
+ ; CHECK-NEXT: STQCX killed renamable $g8p1, renamable $x7, renamable $x4, implicit-def dead $cr0
; CHECK-NEXT: STQCX killed renamable $g8p15, renamable $x7, renamable $x4, implicit-def dead $cr0
; CHECK-NEXT: STQCX killed renamable $g8p7, renamable $x7, renamable $x4, implicit-def dead $cr0
; CHECK-NEXT: STQCX killed renamable $g8p8, renamable $x7, renamable $x4, implicit-def dead $cr0
@@ -139,7 +139,8 @@ body: |
; CHECK-NEXT: $x8 = LD -192, $x1
; CHECK-NEXT: $x9 = LD -184, $x1
; CHECK-NEXT: STQCX killed renamable $g8p4, renamable $x7, renamable $x4, implicit-def dead $cr0
- ; CHECK-NEXT: STQCX renamable $g8p1, killed renamable $x7, killed renamable $x4, implicit-def dead $cr0
+ ; CHECK-NEXT: STQCX renamable $g8p14, killed renamable $x7, killed renamable $x4, implicit-def dead $cr0
+ ; CHECK-NEXT: $x3 = OR8 $x29, killed $x29
; CHECK-NEXT: $x8 = LD -176, $x1
; CHECK-NEXT: $x9 = LD -168, $x1
; CHECK-NEXT: STQCX killed renamable $g8p4, $x5, $x6, implicit-def dead $cr0
>From cc44151c5a368f80fbd17f39777f7407a2117ea0 Mon Sep 17 00:00:00 2001
From: Nikita Popov <npopov at redhat.com>
Date: Wed, 25 Mar 2026 10:11:51 +0100
Subject: [PATCH 2/2] Use IntrInaccessibleMemOrArgMemOnly
---
llvm/include/llvm/IR/IntrinsicsPowerPC.td | 20 ++++++++++++--------
1 file changed, 12 insertions(+), 8 deletions(-)
diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
index 767b9d033f954..03e9669a137ae 100644
--- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -1918,25 +1918,29 @@ let TargetPrefix = "ppc" in {
def int_ppc_iospace_eieio : ClangBuiltin<"__builtin_ppc_iospace_eieio">,
Intrinsic<[],[],[]>;
def int_ppc_lbarx :
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], []>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrInaccessibleMemOrArgMemOnly]>;
def int_ppc_lharx :
- Intrinsic<[llvm_i32_ty],[llvm_ptr_ty], []>;
+ Intrinsic<[llvm_i32_ty],[llvm_ptr_ty], [IntrInaccessibleMemOrArgMemOnly]>;
def int_ppc_lwarx :
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], []>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrInaccessibleMemOrArgMemOnly]>;
def int_ppc_ldarx :
- Intrinsic<[llvm_i64_ty],[llvm_ptr_ty], []>;
+ Intrinsic<[llvm_i64_ty],[llvm_ptr_ty], [IntrInaccessibleMemOrArgMemOnly]>;
def int_ppc_stdcx :
ClangBuiltin<"__builtin_ppc_stdcx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i64_ty],
+ [IntrInaccessibleMemOrArgMemOnly, IntrNoDuplicate]>;
def int_ppc_stwcx :
ClangBuiltin<"__builtin_ppc_stwcx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
+ [IntrInaccessibleMemOrArgMemOnly, IntrNoDuplicate]>;
def int_ppc_sthcx :
- Intrinsic<[llvm_i32_ty], [ llvm_ptr_ty, llvm_i32_ty], [IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [ llvm_ptr_ty, llvm_i32_ty],
+ [IntrInaccessibleMemOrArgMemOnly, IntrNoDuplicate]>;
def int_ppc_stbcx :
ClangBuiltin<"__builtin_ppc_stbcx">,
- Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrNoDuplicate]>;
+ Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty],
+ [IntrInaccessibleMemOrArgMemOnly, IntrNoDuplicate]>;
def int_ppc_dcbtstt : ClangBuiltin<"__builtin_ppc_dcbtstt">,
Intrinsic<[], [llvm_ptr_ty],
[IntrArgMemOnly, NoCapture<ArgIndex<0>>]>;
More information about the llvm-commits
mailing list