[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