[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