[llvm] [LLVM-C] Upstream `LLVMBuildAtomicLoad/Store` from rustc (PR #162450)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 8 03:17:19 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-ir

Author: None (AMS21)

<details>
<summary>Changes</summary>

Adds `LLVMBuildAtomicLoad` and `LLVMBuildAtomicStore` functions originally from rustc. [rustc LLVMRustBuildAtomicLoad](https://github.com/rust-lang/rust/blob/5767910cbcc9d199bf261a468574d45aa3857599/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp#L627), [rustc LLVMRustBuildAtomicStore](https://github.com/rust-lang/rust/blob/5767910cbcc9d199bf261a468574d45aa3857599/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp#L635)

Unlike the original I add the option to specify whether the operation is single-threaded similar to how  other `LLVMBuildAtomic` functions do in LLVM-C.

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


4 Files Affected:

- (modified) llvm/docs/ReleaseNotes.md (+1) 
- (modified) llvm/include/llvm-c/Core.h (+28) 
- (modified) llvm/lib/IR/Core.cpp (+20) 
- (modified) llvm/unittests/IR/InstructionsTest.cpp (+43) 


``````````diff
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 79d93d08b8398..362f9dff7f4a4 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -147,6 +147,7 @@ Changes to the C API
 --------------------
 
 * Add `LLVMGetOrInsertFunction` to get or insert a function, replacing the combination of `LLVMGetNamedFunction` and `LLVMAddFunction`.
+* Add `LLVMBuildAtomicLoad` and `LLVMBuildAtomicStore` to build atomic load and store instructions by specifying the ordering and whether the operation is single-threaded.
 
 Changes to the CodeGen infrastructure
 -------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 3d22f85911e78..b0f7b4c40b793 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -4905,6 +4905,34 @@ LLVM_C_ABI LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(
     LLVMAtomicOrdering SuccessOrdering, LLVMAtomicOrdering FailureOrdering,
     unsigned SSID);
 
+/**
+ * Builds an atomic load instruction.
+ *
+ * This is similar to LLVMBuildLoad2, but allows specifying the atomic
+ * ordering and whether the operation is single-threaded.
+ *
+ * @see llvm::IRBuilder::CreateLoad()
+ * @see llvm::LoadInst::setAtomic()
+ */
+LLVM_C_ABI LLVMValueRef LLVMBuildAtomicLoad(
+    LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source, const char *Name,
+    LLVMAtomicOrdering Order, LLVMBool SingleThread);
+
+/**
+ * Builds an atomic store instruction.
+ *
+ * This is similar to LLVMBuildStore, but allows specifying the atomic
+ * ordering and whether the operation is single-threaded.
+ *
+ * @see llvm::IRBuilder::CreateStore()
+ * @see llvm::StoreInst::setAtomic()
+ */
+LLVM_C_ABI LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
+                                                 LLVMValueRef V,
+                                                 LLVMValueRef Target,
+                                                 LLVMAtomicOrdering Order,
+                                                 LLVMBool SingleThread);
+
 /**
  * Get the number of elements in the mask of a ShuffleVector instruction.
  */
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 3f1cc1e4e6d0e..7fcc7ae63f1fb 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -4440,6 +4440,26 @@ LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(LLVMBuilderRef B, LLVMValueRef Ptr,
       mapFromLLVMOrdering(FailureOrdering), SSID));
 }
 
+LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty,
+                                 LLVMValueRef Source, const char *Name,
+                                 LLVMAtomicOrdering Order,
+                                 LLVMBool SingleThread) {
+  LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), unwrap(Source), Name);
+  LI->setAtomic(mapFromLLVMOrdering(Order),
+                SingleThread ? SyncScope::SingleThread : SyncScope::System);
+  return wrap(LI);
+}
+
+LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B, LLVMValueRef V,
+                                      LLVMValueRef Target,
+                                      LLVMAtomicOrdering Order,
+                                      LLVMBool SingleThread) {
+  StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
+  SI->setAtomic(mapFromLLVMOrdering(Order),
+                SingleThread ? SyncScope::SingleThread : SyncScope::System);
+  return wrap(SI);
+}
+
 unsigned LLVMGetNumMaskElements(LLVMValueRef SVInst) {
   Value *P = unwrap(SVInst);
   ShuffleVectorInst *I = cast<ShuffleVectorInst>(P);
diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index fe9e7e8228490..1d030309a9a25 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -1933,5 +1933,48 @@ TEST(InstructionsTest, StripAndAccumulateConstantOffset) {
   EXPECT_TRUE(Offset.isZero());
 }
 
+TEST(FunctionTest, BuildAtomicStoreAndLoad) {
+  LLVMContext Ctx;
+  Module M("test", Ctx);
+  Type *Int32Ty = Type::getInt32Ty(Ctx);
+  FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), false);
+  Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, "F", &M);
+  BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
+  IRBuilder<> Builder(BB);
+
+  AllocaInst *Target = Builder.CreateAlloca(Int32Ty);
+  Constant *V = ConstantInt::get(Int32Ty, 42);
+
+  // Atomic store
+  StoreInst *Store = cast<StoreInst>(
+      unwrap(LLVMBuildAtomicStore(wrap(&Builder), wrap(V), wrap(Target),
+                                  LLVMAtomicOrderingRelease, false)));
+  EXPECT_TRUE(Store->isAtomic());
+  EXPECT_EQ(Store->getOrdering(), AtomicOrdering::Release);
+  EXPECT_EQ(Store->getSyncScopeID(), SyncScope::System);
+
+  Store = cast<StoreInst>(unwrap(
+      LLVMBuildAtomicStore(wrap(&Builder), wrap(V), wrap(Target),
+                           LLVMAtomicOrderingSequentiallyConsistent, true)));
+  EXPECT_TRUE(Store->isAtomic());
+  EXPECT_EQ(Store->getOrdering(), AtomicOrdering::SequentiallyConsistent);
+  EXPECT_EQ(Store->getSyncScopeID(), SyncScope::SingleThread);
+
+  // Atomic load
+  LoadInst *Load = cast<LoadInst>(
+      unwrap(LLVMBuildAtomicLoad(wrap(&Builder), wrap(Int32Ty), wrap(Target),
+                                 "aload", LLVMAtomicOrderingAcquire, false)));
+  EXPECT_TRUE(Load->isAtomic());
+  EXPECT_EQ(Load->getOrdering(), AtomicOrdering::Acquire);
+  EXPECT_EQ(Load->getSyncScopeID(), SyncScope::System);
+
+  Load = cast<LoadInst>(unwrap(
+      LLVMBuildAtomicLoad(wrap(&Builder), wrap(Int32Ty), wrap(Target), "aload",
+                          LLVMAtomicOrderingSequentiallyConsistent, true)));
+  EXPECT_TRUE(Load->isAtomic());
+  EXPECT_EQ(Load->getOrdering(), AtomicOrdering::SequentiallyConsistent);
+  EXPECT_EQ(Load->getSyncScopeID(), SyncScope::SingleThread);
+}
+
 } // end anonymous namespace
 } // end namespace llvm

``````````

</details>


https://github.com/llvm/llvm-project/pull/162450


More information about the llvm-commits mailing list