Skip to content

Conversation

Lancern
Copy link
Member

@Lancern Lancern commented Aug 24, 2025

This patch adds support for __atomic_load_n and __atomic_store_n that were missed by #153814.

@llvmbot llvmbot added clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project labels Aug 24, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 24, 2025

@llvm/pr-subscribers-clangir

@llvm/pr-subscribers-clang

Author: Sirui Mu (Lancern)

Changes

This patch adds support for __atomic_load_n and __atomic_store_n that were missed by #153814.


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

2 Files Affected:

  • (modified) clang/lib/CIR/CodeGen/CIRGenAtomic.cpp (+8-4)
  • (modified) clang/test/CIR/CodeGen/atomic.c (+53)
diff --git a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
index 80aacb946e7c7..2341483a93652 100644
--- a/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenAtomic.cpp
@@ -265,6 +265,7 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
     llvm_unreachable("already handled!");
 
   case AtomicExpr::AO__c11_atomic_load:
+  case AtomicExpr::AO__atomic_load_n:
   case AtomicExpr::AO__atomic_load: {
     cir::LoadOp load =
         builder.createLoad(loc, ptr, /*isVolatile=*/expr->isVolatile());
@@ -278,6 +279,7 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
   }
 
   case AtomicExpr::AO__c11_atomic_store:
+  case AtomicExpr::AO__atomic_store_n:
   case AtomicExpr::AO__atomic_store: {
     cir::LoadOp loadVal1 = builder.createLoad(loc, val1);
 
@@ -305,13 +307,11 @@ static void emitAtomicOp(CIRGenFunction &cgf, AtomicExpr *expr, Address dest,
 
   case AtomicExpr::AO__opencl_atomic_load:
   case AtomicExpr::AO__hip_atomic_load:
-  case AtomicExpr::AO__atomic_load_n:
   case AtomicExpr::AO__scoped_atomic_load_n:
   case AtomicExpr::AO__scoped_atomic_load:
 
   case AtomicExpr::AO__opencl_atomic_store:
   case AtomicExpr::AO__hip_atomic_store:
-  case AtomicExpr::AO__atomic_store_n:
   case AtomicExpr::AO__scoped_atomic_store:
   case AtomicExpr::AO__scoped_atomic_store_n:
 
@@ -450,6 +450,7 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
   case AtomicExpr::AO__c11_atomic_init:
     llvm_unreachable("already handled above with emitAtomicInit");
 
+  case AtomicExpr::AO__atomic_load_n:
   case AtomicExpr::AO__c11_atomic_load:
     break;
 
@@ -461,6 +462,7 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
     val1 = emitPointerWithAlignment(e->getVal1());
     break;
 
+  case AtomicExpr::AO__atomic_store_n:
   case AtomicExpr::AO__c11_atomic_store:
     val1 = emitValToTemp(*this, e->getVal1());
     break;
@@ -507,9 +509,11 @@ RValue CIRGenFunction::emitAtomicExpr(AtomicExpr *e) {
   }
 
   bool isStore = e->getOp() == AtomicExpr::AO__c11_atomic_store ||
-                 e->getOp() == AtomicExpr::AO__atomic_store;
+                 e->getOp() == AtomicExpr::AO__atomic_store ||
+                 e->getOp() == AtomicExpr::AO__atomic_store_n;
   bool isLoad = e->getOp() == AtomicExpr::AO__c11_atomic_load ||
-                e->getOp() == AtomicExpr::AO__atomic_load;
+                e->getOp() == AtomicExpr::AO__atomic_load ||
+                e->getOp() == AtomicExpr::AO__atomic_load_n;
 
   if (!order) {
     // We have evaluated the memory order as an integer constant in orderConst.
diff --git a/clang/test/CIR/CodeGen/atomic.c b/clang/test/CIR/CodeGen/atomic.c
index 6c37fb7cd432d..8b947f795d1d4 100644
--- a/clang/test/CIR/CodeGen/atomic.c
+++ b/clang/test/CIR/CodeGen/atomic.c
@@ -75,6 +75,35 @@ void load(int *ptr) {
 // OGCG:   %{{.+}} = load atomic i32, ptr %{{.+}} seq_cst, align 4
 // OGCG: }
 
+void load_n(int *ptr) {
+  int a;
+  a = __atomic_load_n(ptr, __ATOMIC_RELAXED);
+  a = __atomic_load_n(ptr, __ATOMIC_CONSUME);
+  a = __atomic_load_n(ptr, __ATOMIC_ACQUIRE);
+  a = __atomic_load_n(ptr, __ATOMIC_SEQ_CST);
+}
+
+// CIR-LABEL: @load_n
+// CIR:   %{{.+}} = cir.load align(4) atomic(relaxed) %{{.+}} : !cir.ptr<!s32i>, !s32i
+// CIR:   %{{.+}} = cir.load align(4) atomic(consume) %{{.+}} : !cir.ptr<!s32i>, !s32i
+// CIR:   %{{.+}} = cir.load align(4) atomic(acquire) %{{.+}} : !cir.ptr<!s32i>, !s32i
+// CIR:   %{{.+}} = cir.load align(4) atomic(seq_cst) %{{.+}} : !cir.ptr<!s32i>, !s32i
+// CIR: }
+
+// LLVM-LABEL: @load_n
+// LLVM:   %{{.+}} = load atomic i32, ptr %{{.+}} monotonic, align 4
+// LLVM:   %{{.+}} = load atomic i32, ptr %{{.+}} acquire, align 4
+// LLVM:   %{{.+}} = load atomic i32, ptr %{{.+}} acquire, align 4
+// LLVM:   %{{.+}} = load atomic i32, ptr %{{.+}} seq_cst, align 4
+// LLVM: }
+
+// OGCG-LABEL: @load_n
+// OGCG:   %{{.+}} = load atomic i32, ptr %{{.+}} monotonic, align 4
+// OGCG:   %{{.+}} = load atomic i32, ptr %{{.+}} acquire, align 4
+// OGCG:   %{{.+}} = load atomic i32, ptr %{{.+}} acquire, align 4
+// OGCG:   %{{.+}} = load atomic i32, ptr %{{.+}} seq_cst, align 4
+// OGCG: }
+
 void c11_load(_Atomic(int) *ptr) {
   __c11_atomic_load(ptr, __ATOMIC_RELAXED);
   __c11_atomic_load(ptr, __ATOMIC_CONSUME);
@@ -127,6 +156,30 @@ void store(int *ptr, int x) {
 // OGCG:   store atomic i32 %{{.+}}, ptr %{{.+}} seq_cst, align 4
 // OGCG: }
 
+void store_n(int *ptr, int x) {
+  __atomic_store_n(ptr, x, __ATOMIC_RELAXED);
+  __atomic_store_n(ptr, x, __ATOMIC_RELEASE);
+  __atomic_store_n(ptr, x, __ATOMIC_SEQ_CST);
+}
+
+// CIR-LABEL: @store_n
+// CIR:   cir.store align(4) atomic(relaxed) %{{.+}}, %{{.+}} : !s32i, !cir.ptr<!s32i>
+// CIR:   cir.store align(4) atomic(release) %{{.+}}, %{{.+}} : !s32i, !cir.ptr<!s32i>
+// CIR:   cir.store align(4) atomic(seq_cst) %{{.+}}, %{{.+}} : !s32i, !cir.ptr<!s32i>
+// CIR: }
+
+// LLVM-LABEL: @store_n
+// LLVM:   store atomic i32 %{{.+}}, ptr %{{.+}} monotonic, align 4
+// LLVM:   store atomic i32 %{{.+}}, ptr %{{.+}} release, align 4
+// LLVM:   store atomic i32 %{{.+}}, ptr %{{.+}} seq_cst, align 4
+// LLVM: }
+
+// OGCG-LABEL: @store_n
+// OGCG:   store atomic i32 %{{.+}}, ptr %{{.+}} monotonic, align 4
+// OGCG:   store atomic i32 %{{.+}}, ptr %{{.+}} release, align 4
+// OGCG:   store atomic i32 %{{.+}}, ptr %{{.+}} seq_cst, align 4
+// OGCG: }
+
 void c11_store(_Atomic(int) *ptr, int x) {
   __c11_atomic_store(ptr, x, __ATOMIC_RELAXED);
   __c11_atomic_store(ptr, x, __ATOMIC_RELEASE);

Copy link
Member

@bcardosolopes bcardosolopes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with one change needed

Copy link
Contributor

@andykaylor andykaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no additional comments beyond what @bcardosolopes has already said.

This patch adds support for `__atomic_load_n` and `__atomic_store_n` that were
missed by llvm#153814.
@Lancern Lancern force-pushed the cir/atomic-load-store branch from 0c6441a to 0b6f6f7 Compare August 27, 2025 14:18
@Lancern Lancern merged commit a2bc0ca into llvm:main Aug 27, 2025
9 checks passed
@Lancern Lancern deleted the cir/atomic-load-store branch August 27, 2025 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category ClangIR Anything related to the ClangIR project
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants