-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[LLVM-C] Upstream LLVMBuildAtomicLoad/Store
from rustc
#162450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-ir Author: None (AMS21) ChangesAdds Unlike the original I add the option to specify whether the operation is single-threaded similar to how other Full diff: https://github.com/llvm/llvm-project/pull/162450.diff 4 Files Affected:
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
|
You can test this locally with the following command:git-clang-format --diff origin/main HEAD --extensions h,cpp -- llvm/include/llvm-c/Core.h llvm/lib/IR/Core.cpp llvm/unittests/IR/InstructionsTest.cpp
View the diff from clang-format here.diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index b0f7b4c40..941875509 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -4914,9 +4914,11 @@ LLVM_C_ABI LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(
* @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);
+LLVM_C_ABI LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty,
+ LLVMValueRef Source,
+ const char *Name,
+ LLVMAtomicOrdering Order,
+ LLVMBool SingleThread);
/**
* Builds an atomic store instruction.
@@ -4927,11 +4929,10 @@ LLVM_C_ABI LLVMValueRef LLVMBuildAtomicLoad(
* @see llvm::IRBuilder::CreateStore()
* @see llvm::StoreInst::setAtomic()
*/
-LLVM_C_ABI LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
- LLVMValueRef V,
- LLVMValueRef Target,
- LLVMAtomicOrdering Order,
- LLVMBool SingleThread);
+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 7fcc7ae63..aaccdd4a4 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -4451,9 +4451,8 @@ LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty,
}
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B, LLVMValueRef V,
- LLVMValueRef Target,
- LLVMAtomicOrdering Order,
- LLVMBool SingleThread) {
+ LLVMValueRef Target, LLVMAtomicOrdering Order,
+ LLVMBool SingleThread) {
StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
SI->setAtomic(mapFromLLVMOrdering(Order),
SingleThread ? SyncScope::SingleThread : SyncScope::System);
|
Hm, do we really need these? Aren't these just combinations of LLVMBuildLoad2/LLVMBuildStore + LLVMSetOrdering (+ LLVMSetAtomicSingleThread if necessary)? The calling code already sets the alignment separately: https://github.com/rust-lang/rust/blob/5767910cbcc9d199bf261a468574d45aa3857599/compiler/rustc_codegen_llvm/src/builder.rs#L649-L650 So I don't think there is a strong reason to integrate setting the ordering into one C API call. |
Alright I guess then it would be better to refactor this on the rustc side. |
Adds
LLVMBuildAtomicLoad
andLLVMBuildAtomicStore
functions originally from rustc. rustc LLVMRustBuildAtomicLoad, rustc LLVMRustBuildAtomicStoreUnlike the original I add the option to specify whether the operation is single-threaded similar to how other
LLVMBuildAtomic
functions do in LLVM-C.