Skip to content

Commit f31e6dc

Browse files
committed
[LLVM-C] Upstream LLVMBuildAtomicLoad/Store from rustc
1 parent a29d7a1 commit f31e6dc

File tree

4 files changed

+92
-0
lines changed

4 files changed

+92
-0
lines changed

llvm/docs/ReleaseNotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ Changes to the C API
147147
--------------------
148148

149149
* Add `LLVMGetOrInsertFunction` to get or insert a function, replacing the combination of `LLVMGetNamedFunction` and `LLVMAddFunction`.
150+
* Add `LLVMBuildAtomicLoad` and `LLVMBuildAtomicStore` to build atomic load and store instructions by specifying the ordering and whether the operation is single-threaded.
150151

151152
Changes to the CodeGen infrastructure
152153
-------------------------------------

llvm/include/llvm-c/Core.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4905,6 +4905,34 @@ LLVM_C_ABI LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(
49054905
LLVMAtomicOrdering SuccessOrdering, LLVMAtomicOrdering FailureOrdering,
49064906
unsigned SSID);
49074907

4908+
/**
4909+
* Builds an atomic load instruction.
4910+
*
4911+
* This is similar to LLVMBuildLoad2, but allows specifying the atomic
4912+
* ordering and whether the operation is single-threaded.
4913+
*
4914+
* @see llvm::IRBuilder::CreateLoad()
4915+
* @see llvm::LoadInst::setAtomic()
4916+
*/
4917+
LLVM_C_ABI LLVMValueRef LLVMBuildAtomicLoad(
4918+
LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Source, const char *Name,
4919+
LLVMAtomicOrdering Order, LLVMBool SingleThread);
4920+
4921+
/**
4922+
* Builds an atomic store instruction.
4923+
*
4924+
* This is similar to LLVMBuildStore, but allows specifying the atomic
4925+
* ordering and whether the operation is single-threaded.
4926+
*
4927+
* @see llvm::IRBuilder::CreateStore()
4928+
* @see llvm::StoreInst::setAtomic()
4929+
*/
4930+
LLVM_C_ABI LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B,
4931+
LLVMValueRef V,
4932+
LLVMValueRef Target,
4933+
LLVMAtomicOrdering Order,
4934+
LLVMBool SingleThread);
4935+
49084936
/**
49094937
* Get the number of elements in the mask of a ShuffleVector instruction.
49104938
*/

llvm/lib/IR/Core.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4440,6 +4440,26 @@ LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(LLVMBuilderRef B, LLVMValueRef Ptr,
44404440
mapFromLLVMOrdering(FailureOrdering), SSID));
44414441
}
44424442

4443+
LLVMValueRef LLVMBuildAtomicLoad(LLVMBuilderRef B, LLVMTypeRef Ty,
4444+
LLVMValueRef Source, const char *Name,
4445+
LLVMAtomicOrdering Order,
4446+
LLVMBool SingleThread) {
4447+
LoadInst *LI = unwrap(B)->CreateLoad(unwrap(Ty), unwrap(Source), Name);
4448+
LI->setAtomic(mapFromLLVMOrdering(Order),
4449+
SingleThread ? SyncScope::SingleThread : SyncScope::System);
4450+
return wrap(LI);
4451+
}
4452+
4453+
LLVMValueRef LLVMBuildAtomicStore(LLVMBuilderRef B, LLVMValueRef V,
4454+
LLVMValueRef Target,
4455+
LLVMAtomicOrdering Order,
4456+
LLVMBool SingleThread) {
4457+
StoreInst *SI = unwrap(B)->CreateStore(unwrap(V), unwrap(Target));
4458+
SI->setAtomic(mapFromLLVMOrdering(Order),
4459+
SingleThread ? SyncScope::SingleThread : SyncScope::System);
4460+
return wrap(SI);
4461+
}
4462+
44434463
unsigned LLVMGetNumMaskElements(LLVMValueRef SVInst) {
44444464
Value *P = unwrap(SVInst);
44454465
ShuffleVectorInst *I = cast<ShuffleVectorInst>(P);

llvm/unittests/IR/InstructionsTest.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1933,5 +1933,48 @@ TEST(InstructionsTest, StripAndAccumulateConstantOffset) {
19331933
EXPECT_TRUE(Offset.isZero());
19341934
}
19351935

1936+
TEST(FunctionTest, BuildAtomicStoreAndLoad) {
1937+
LLVMContext Ctx;
1938+
Module M("test", Ctx);
1939+
Type *Int32Ty = Type::getInt32Ty(Ctx);
1940+
FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), false);
1941+
Function *F = Function::Create(FTy, GlobalValue::ExternalLinkage, "F", &M);
1942+
BasicBlock *BB = BasicBlock::Create(Ctx, "entry", F);
1943+
IRBuilder<> Builder(BB);
1944+
1945+
AllocaInst *Target = Builder.CreateAlloca(Int32Ty);
1946+
Constant *V = ConstantInt::get(Int32Ty, 42);
1947+
1948+
// Atomic store
1949+
StoreInst *Store = cast<StoreInst>(
1950+
unwrap(LLVMBuildAtomicStore(wrap(&Builder), wrap(V), wrap(Target),
1951+
LLVMAtomicOrderingRelease, false)));
1952+
EXPECT_TRUE(Store->isAtomic());
1953+
EXPECT_EQ(Store->getOrdering(), AtomicOrdering::Release);
1954+
EXPECT_EQ(Store->getSyncScopeID(), SyncScope::System);
1955+
1956+
Store = cast<StoreInst>(unwrap(
1957+
LLVMBuildAtomicStore(wrap(&Builder), wrap(V), wrap(Target),
1958+
LLVMAtomicOrderingSequentiallyConsistent, true)));
1959+
EXPECT_TRUE(Store->isAtomic());
1960+
EXPECT_EQ(Store->getOrdering(), AtomicOrdering::SequentiallyConsistent);
1961+
EXPECT_EQ(Store->getSyncScopeID(), SyncScope::SingleThread);
1962+
1963+
// Atomic load
1964+
LoadInst *Load = cast<LoadInst>(
1965+
unwrap(LLVMBuildAtomicLoad(wrap(&Builder), wrap(Int32Ty), wrap(Target),
1966+
"aload", LLVMAtomicOrderingAcquire, false)));
1967+
EXPECT_TRUE(Load->isAtomic());
1968+
EXPECT_EQ(Load->getOrdering(), AtomicOrdering::Acquire);
1969+
EXPECT_EQ(Load->getSyncScopeID(), SyncScope::System);
1970+
1971+
Load = cast<LoadInst>(unwrap(
1972+
LLVMBuildAtomicLoad(wrap(&Builder), wrap(Int32Ty), wrap(Target), "aload",
1973+
LLVMAtomicOrderingSequentiallyConsistent, true)));
1974+
EXPECT_TRUE(Load->isAtomic());
1975+
EXPECT_EQ(Load->getOrdering(), AtomicOrdering::SequentiallyConsistent);
1976+
EXPECT_EQ(Load->getSyncScopeID(), SyncScope::SingleThread);
1977+
}
1978+
19361979
} // end anonymous namespace
19371980
} // end namespace llvm

0 commit comments

Comments
 (0)