-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[LLVM] Add a C API for creating instructions with custom syncscopes. #104775
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
Changes from all commits
a86400d
0b9f075
0028d86
ce5db1e
b4ad3c6
41aa204
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ | |
#include "llvm/IR/GlobalVariable.h" | ||
#include "llvm/IR/IRBuilder.h" | ||
#include "llvm/IR/InlineAsm.h" | ||
#include "llvm/IR/Instructions.h" | ||
#include "llvm/IR/IntrinsicInst.h" | ||
#include "llvm/IR/LLVMContext.h" | ||
#include "llvm/IR/LegacyPassManager.h" | ||
|
@@ -146,6 +147,10 @@ unsigned LLVMGetMDKindID(const char *Name, unsigned SLen) { | |
return LLVMGetMDKindIDInContext(LLVMGetGlobalContext(), Name, SLen); | ||
} | ||
|
||
unsigned LLVMGetSyncScopeID(LLVMContextRef C, const char *Name, size_t SLen) { | ||
return unwrap(C)->getOrInsertSyncScopeID(StringRef(Name, SLen)); | ||
} | ||
|
||
unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen) { | ||
return Attribute::getAttrKindFromName(StringRef(Name, SLen)); | ||
} | ||
|
@@ -3949,8 +3954,6 @@ static LLVMAtomicRMWBinOp mapToLLVMRMWBinOp(AtomicRMWInst::BinOp BinOp) { | |
llvm_unreachable("Invalid AtomicRMWBinOp value!"); | ||
} | ||
|
||
// TODO: Should this and other atomic instructions support building with | ||
// "syncscope"? | ||
LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering, | ||
LLVMBool isSingleThread, const char *Name) { | ||
return wrap( | ||
|
@@ -3960,6 +3963,13 @@ LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering, | |
Name)); | ||
} | ||
|
||
LLVMValueRef LLVMBuildFenceSyncScope(LLVMBuilderRef B, | ||
LLVMAtomicOrdering Ordering, unsigned SSID, | ||
const char *Name) { | ||
return wrap( | ||
unwrap(B)->CreateFence(mapFromLLVMOrdering(Ordering), SSID, Name)); | ||
} | ||
|
||
LLVMValueRef LLVMBuildGEP2(LLVMBuilderRef B, LLVMTypeRef Ty, | ||
LLVMValueRef Pointer, LLVMValueRef *Indices, | ||
unsigned NumIndices, const char *Name) { | ||
|
@@ -4309,6 +4319,17 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op, | |
singleThread ? SyncScope::SingleThread : SyncScope::System)); | ||
} | ||
|
||
LLVMValueRef LLVMBuildAtomicRMWSyncScope(LLVMBuilderRef B, | ||
LLVMAtomicRMWBinOp op, | ||
LLVMValueRef PTR, LLVMValueRef Val, | ||
LLVMAtomicOrdering ordering, | ||
unsigned SSID) { | ||
AtomicRMWInst::BinOp intop = mapFromLLVMRMWBinOp(op); | ||
return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val), | ||
MaybeAlign(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well not repeat past mistakes and also require an alignment argument for the new functions? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, it seems weird to me to have a minor variant of an API taking different arguments like that. It'd be kinda awkward to wrap in LLVM.jl, where we support multiple versions of LLVM. Wouldn't it be better to keep the APIs similar and defer to |
||
mapFromLLVMOrdering(ordering), SSID)); | ||
} | ||
|
||
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr, | ||
LLVMValueRef Cmp, LLVMValueRef New, | ||
LLVMAtomicOrdering SuccessOrdering, | ||
|
@@ -4322,6 +4343,17 @@ LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr, | |
singleThread ? SyncScope::SingleThread : SyncScope::System)); | ||
} | ||
|
||
LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(LLVMBuilderRef B, LLVMValueRef Ptr, | ||
LLVMValueRef Cmp, LLVMValueRef New, | ||
LLVMAtomicOrdering SuccessOrdering, | ||
LLVMAtomicOrdering FailureOrdering, | ||
unsigned SSID) { | ||
return wrap(unwrap(B)->CreateAtomicCmpXchg( | ||
unwrap(Ptr), unwrap(Cmp), unwrap(New), MaybeAlign(), | ||
mapFromLLVMOrdering(SuccessOrdering), | ||
mapFromLLVMOrdering(FailureOrdering), SSID)); | ||
} | ||
|
||
unsigned LLVMGetNumMaskElements(LLVMValueRef SVInst) { | ||
Value *P = unwrap(SVInst); | ||
ShuffleVectorInst *I = cast<ShuffleVectorInst>(P); | ||
|
@@ -4336,34 +4368,39 @@ int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) { | |
|
||
int LLVMGetUndefMaskElem(void) { return PoisonMaskElem; } | ||
|
||
LLVMBool LLVMIsAtomic(LLVMValueRef Inst) { | ||
return unwrap<Instruction>(Inst)->isAtomic(); | ||
} | ||
|
||
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) { | ||
Value *P = unwrap(AtomicInst); | ||
// Backwards compatibility: return false for non-atomic instructions | ||
Instruction *I = unwrap<Instruction>(AtomicInst); | ||
if (!I->isAtomic()) | ||
return 0; | ||
|
||
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P)) | ||
return I->getSyncScopeID() == SyncScope::SingleThread; | ||
else if (FenceInst *FI = dyn_cast<FenceInst>(P)) | ||
return FI->getSyncScopeID() == SyncScope::SingleThread; | ||
else if (StoreInst *SI = dyn_cast<StoreInst>(P)) | ||
return SI->getSyncScopeID() == SyncScope::SingleThread; | ||
else if (LoadInst *LI = dyn_cast<LoadInst>(P)) | ||
return LI->getSyncScopeID() == SyncScope::SingleThread; | ||
return cast<AtomicCmpXchgInst>(P)->getSyncScopeID() == | ||
SyncScope::SingleThread; | ||
return *getAtomicSyncScopeID(I) == SyncScope::SingleThread; | ||
} | ||
|
||
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) { | ||
Value *P = unwrap(AtomicInst); | ||
// Backwards compatibility: ignore non-atomic instructions | ||
Instruction *I = unwrap<Instruction>(AtomicInst); | ||
if (!I->isAtomic()) | ||
return; | ||
|
||
SyncScope::ID SSID = NewValue ? SyncScope::SingleThread : SyncScope::System; | ||
setAtomicSyncScopeID(I, SSID); | ||
} | ||
|
||
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P)) | ||
return I->setSyncScopeID(SSID); | ||
else if (FenceInst *FI = dyn_cast<FenceInst>(P)) | ||
return FI->setSyncScopeID(SSID); | ||
else if (StoreInst *SI = dyn_cast<StoreInst>(P)) | ||
return SI->setSyncScopeID(SSID); | ||
else if (LoadInst *LI = dyn_cast<LoadInst>(P)) | ||
return LI->setSyncScopeID(SSID); | ||
return cast<AtomicCmpXchgInst>(P)->setSyncScopeID(SSID); | ||
unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst) { | ||
Instruction *I = unwrap<Instruction>(AtomicInst); | ||
assert(I->isAtomic() && "Expected an atomic instruction"); | ||
return *getAtomicSyncScopeID(I); | ||
} | ||
|
||
void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID) { | ||
Instruction *I = unwrap<Instruction>(AtomicInst); | ||
assert(I->isAtomic() && "Expected an atomic instruction"); | ||
setAtomicSyncScopeID(I, SSID); | ||
} | ||
|
||
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst) { | ||
|
Uh oh!
There was an error while loading. Please reload this page.