[llvm] 63cb3e5 - [ObjCARC] Don't sink objc_retain past atomic writes (#184113)

via llvm-commits llvm-commits at lists.llvm.org
Mon Mar 30 06:47:36 PDT 2026


Author: Marina Taylor
Date: 2026-03-30T14:47:31+01:00
New Revision: 63cb3e55e7f1d0bc7609f2fcbad0516e9eff32b7

URL: https://github.com/llvm/llvm-project/commit/63cb3e55e7f1d0bc7609f2fcbad0516e9eff32b7
DIFF: https://github.com/llvm/llvm-project/commit/63cb3e55e7f1d0bc7609f2fcbad0516e9eff32b7.diff

LOG: [ObjCARC] Don't sink objc_retain past atomic writes (#184113)

The atomic may cause another thread to objc_release the pointer, so
consider these instructions as potentially decrementing refcounts.

This patch is a synthesis of several AI models' outputs, as well as work
by David Kilzer.

Co-authored-by: David Kilzer <ddkilzer at apple.com>
Assisted-by: claude

rdar://152185192

Added: 
    llvm/test/Transforms/ObjCARC/sink-past-atomic.ll

Modified: 
    llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp
index b4cc00033e720..ae9f9ad0d3bac 100644
--- a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp
+++ b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp
@@ -67,7 +67,15 @@ bool llvm::objcarc::CanDecrementRefCount(const Instruction *Inst,
                                          const Value *Ptr,
                                          ProvenanceAnalysis &PA,
                                          ARCInstKind Class) {
-  // First perform a quick check if Class can not touch ref counts.
+  // Atomic stores, RMW, and CmpXchg may make a pointer visible to another
+  // thread, which could release it. Treat such instructions as potentially
+  // decrementing refcounts.
+  if (const auto *SI = dyn_cast<StoreInst>(Inst); SI && SI->isAtomic())
+    return true;
+  if (isa<AtomicRMWInst>(Inst) || isa<AtomicCmpXchgInst>(Inst))
+    return true;
+
+  // Perform a quick check if Class can not touch ref counts.
   if (!CanDecrementRefCount(Class))
     return false;
 

diff  --git a/llvm/test/Transforms/ObjCARC/sink-past-atomic.ll b/llvm/test/Transforms/ObjCARC/sink-past-atomic.ll
new file mode 100644
index 0000000000000..6cf285c801ed5
--- /dev/null
+++ b/llvm/test/Transforms/ObjCARC/sink-past-atomic.ll
@@ -0,0 +1,49 @@
+; RUN: opt -passes=objc-arc -S < %s | FileCheck %s
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+
+declare ptr @llvm.objc.retain(ptr)
+declare void @llvm.objc.release(ptr)
+
+; Retain must not sink past atomicrmw.
+define void @test_atomicrmw(ptr %obj, ptr %atomic_slot) {
+; CHECK-LABEL: @test_atomicrmw
+; CHECK: call ptr @llvm.objc.retain
+; CHECK: atomicrmw
+entry:
+  %obj_as_int = ptrtoint ptr %obj to i64
+  %retained = call ptr @llvm.objc.retain(ptr %obj)
+  %old_value = atomicrmw xchg ptr %atomic_slot, i64 %obj_as_int monotonic, align 8
+  %old_obj = inttoptr i64 %old_value to ptr
+  call void @llvm.objc.release(ptr %old_obj)
+  call void @llvm.objc.release(ptr %obj)
+  ret void
+}
+
+; Retain must not sink past cmpxchg.
+define void @test_cmpxchg(ptr %obj, ptr %atomic_slot, i64 %expected) {
+; CHECK-LABEL: @test_cmpxchg
+; CHECK: call ptr @llvm.objc.retain
+; CHECK: cmpxchg
+entry:
+  %obj_as_int = ptrtoint ptr %obj to i64
+  %retained = call ptr @llvm.objc.retain(ptr %obj)
+  %res = cmpxchg ptr %atomic_slot, i64 %expected, i64 %obj_as_int monotonic monotonic, align 8
+  %old_int = extractvalue { i64, i1 } %res, 0
+  %old_obj = inttoptr i64 %old_int to ptr
+  call void @llvm.objc.release(ptr %old_obj)
+  call void @llvm.objc.release(ptr %obj)
+  ret void
+}
+
+; Retain must not sink past an atomic store.
+define void @test_atomic_store(ptr %obj, ptr %slot) {
+; CHECK-LABEL: @test_atomic_store
+; CHECK: call ptr @llvm.objc.retain
+; CHECK: store atomic
+entry:
+  %retained = call ptr @llvm.objc.retain(ptr %obj)
+  store atomic ptr %obj, ptr %slot monotonic, align 8
+  call void @llvm.objc.release(ptr %obj)
+  ret void
+}


        


More information about the llvm-commits mailing list