Skip to content

Commit a86400d

Browse files
committed
[LLVM] Add a C API for creating instructions with custom syncscopes.
1 parent 00def06 commit a86400d

File tree

4 files changed

+144
-18
lines changed

4 files changed

+144
-18
lines changed

llvm/docs/ReleaseNotes.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,16 @@ Changes to the C API
163163
* It is now also possible to run the new pass manager on a single function, by calling
164164
``LLVMRunPassesOnFunction`` instead of ``LLVMRunPasses``.
165165

166+
* Support for creating instructions with custom synchronization scopes has been added:
167+
168+
* ``LLVMGetSyncScopeID`` and ``LLVMGetSyncScopeIDInContext`` to map a synchronization
169+
scope name to an ID, and ``LLVMGetSyncScopeName`` to map an ID back to a name.
170+
* ``LLVMBuildFenceSyncScope``, ``LLVMBuildAtomicRMWSyncScope`` and
171+
``LLVMBuildAtomicCmpXchgSyncScope`` versions of the existing builder functions
172+
with an additional synchronization scope ID parameter.
173+
* ``LLVMGetAtomicSyncScopeID`` and ``LLVMSetAtomicSyncScopeID`` to get and set the
174+
synchronization scope of any atomic instruction.
175+
166176
Changes to the CodeGen infrastructure
167177
-------------------------------------
168178

llvm/include/llvm-c/Core.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,26 @@ unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char *Name,
646646
unsigned SLen);
647647
unsigned LLVMGetMDKindID(const char *Name, unsigned SLen);
648648

649+
/**
650+
* Maps a synchronization scope name to a ID unique within this context.
651+
*/
652+
unsigned LLVMGetSyncScopeIDInContext(LLVMContextRef C, const char *Name,
653+
unsigned SLen);
654+
655+
/**
656+
* Maps a synchronization scope name to a unique ID.
657+
*
658+
* This is equivalent to calling LLVMGetSyncScopeIDInContext with
659+
* LLVMGetGlobalContext() as the context parameter.
660+
*/
661+
unsigned LLVMGetSyncScopeID(const char *Name, unsigned SLen);
662+
663+
/**
664+
* Maps a synchronization scope ID to its name.
665+
*/
666+
const char *LLVMGetSyncScopeName(LLVMContextRef C, unsigned ID,
667+
unsigned *Length);
668+
649669
/**
650670
* Return an unique id given the name of a enum attribute,
651671
* or 0 if no attribute by that name exists.
@@ -4578,15 +4598,28 @@ LLVMValueRef LLVMBuildPtrDiff2(LLVMBuilderRef, LLVMTypeRef ElemTy,
45784598
const char *Name);
45794599
LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering ordering,
45804600
LLVMBool singleThread, const char *Name);
4601+
LLVMValueRef LLVMBuildFenceSyncScope(LLVMBuilderRef B,
4602+
LLVMAtomicOrdering ordering, unsigned SSID,
4603+
const char *Name);
45814604
LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, LLVMAtomicRMWBinOp op,
45824605
LLVMValueRef PTR, LLVMValueRef Val,
45834606
LLVMAtomicOrdering ordering,
45844607
LLVMBool singleThread);
4608+
LLVMValueRef LLVMBuildAtomicRMWSyncScope(LLVMBuilderRef B,
4609+
LLVMAtomicRMWBinOp op,
4610+
LLVMValueRef PTR, LLVMValueRef Val,
4611+
LLVMAtomicOrdering ordering,
4612+
unsigned SSID);
45854613
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
45864614
LLVMValueRef Cmp, LLVMValueRef New,
45874615
LLVMAtomicOrdering SuccessOrdering,
45884616
LLVMAtomicOrdering FailureOrdering,
45894617
LLVMBool SingleThread);
4618+
LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(LLVMBuilderRef B, LLVMValueRef Ptr,
4619+
LLVMValueRef Cmp, LLVMValueRef New,
4620+
LLVMAtomicOrdering SuccessOrdering,
4621+
LLVMAtomicOrdering FailureOrdering,
4622+
unsigned SSID);
45904623

45914624
/**
45924625
* Get the number of elements in the mask of a ShuffleVector instruction.
@@ -4611,6 +4644,16 @@ int LLVMGetMaskValue(LLVMValueRef ShuffleVectorInst, unsigned Elt);
46114644
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst);
46124645
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread);
46134646

4647+
/**
4648+
* Returns the synchronization scope ID of an atomic instruction
4649+
*/
4650+
unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst);
4651+
4652+
/**
4653+
* Sets the synchronization scope ID of an atomic instruction.
4654+
*/
4655+
void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID);
4656+
46144657
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst);
46154658
void LLVMSetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst,
46164659
LLVMAtomicOrdering Ordering);

llvm/lib/IR/Core.cpp

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,24 @@ unsigned LLVMGetMDKindID(const char *Name, unsigned SLen) {
146146
return LLVMGetMDKindIDInContext(LLVMGetGlobalContext(), Name, SLen);
147147
}
148148

149+
unsigned LLVMGetSyncScopeIDInContext(LLVMContextRef C, const char *Name,
150+
unsigned SLen) {
151+
return unwrap(C)->getOrInsertSyncScopeID(StringRef(Name, SLen));
152+
}
153+
154+
unsigned LLVMGetSyncScopeID(const char *Name, unsigned SLen) {
155+
return LLVMGetSyncScopeIDInContext(LLVMGetGlobalContext(), Name, SLen);
156+
}
157+
158+
const char *LLVMGetSyncScopeName(LLVMContextRef C, unsigned ID,
159+
unsigned *Length) {
160+
SmallVector<StringRef> SSNs;
161+
unwrap(C)->getSyncScopeNames(SSNs);
162+
StringRef Name = SSNs[ID].empty() ? "system" : SSNs[ID];
163+
*Length = Name.size();
164+
return Name.data();
165+
}
166+
149167
unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen) {
150168
return Attribute::getAttrKindFromName(StringRef(Name, SLen));
151169
}
@@ -3949,8 +3967,6 @@ static LLVMAtomicRMWBinOp mapToLLVMRMWBinOp(AtomicRMWInst::BinOp BinOp) {
39493967
llvm_unreachable("Invalid AtomicRMWBinOp value!");
39503968
}
39513969

3952-
// TODO: Should this and other atomic instructions support building with
3953-
// "syncscope"?
39543970
LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering,
39553971
LLVMBool isSingleThread, const char *Name) {
39563972
return wrap(
@@ -3960,6 +3976,13 @@ LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering,
39603976
Name));
39613977
}
39623978

3979+
LLVMValueRef LLVMBuildFenceSyncScope(LLVMBuilderRef B,
3980+
LLVMAtomicOrdering Ordering, unsigned SSID,
3981+
const char *Name) {
3982+
return wrap(
3983+
unwrap(B)->CreateFence(mapFromLLVMOrdering(Ordering), SSID, Name));
3984+
}
3985+
39633986
LLVMValueRef LLVMBuildGEP2(LLVMBuilderRef B, LLVMTypeRef Ty,
39643987
LLVMValueRef Pointer, LLVMValueRef *Indices,
39653988
unsigned NumIndices, const char *Name) {
@@ -4309,6 +4332,22 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
43094332
singleThread ? SyncScope::SingleThread : SyncScope::System));
43104333
}
43114334

4335+
LLVMValueRef LLVMBuildAtomicRMWSyncScope(LLVMBuilderRef B,
4336+
LLVMAtomicRMWBinOp op,
4337+
LLVMValueRef PTR, LLVMValueRef Val,
4338+
LLVMAtomicOrdering ordering,
4339+
unsigned SSID) {
4340+
AtomicRMWInst::BinOp intop = mapFromLLVMRMWBinOp(op);
4341+
4342+
SmallVector<StringRef> SSNs;
4343+
unwrap(B)->getContext().getSyncScopeNames(SSNs);
4344+
assert(SSID < SSNs.size() && "Invalid SyncScopeID");
4345+
4346+
return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
4347+
MaybeAlign(),
4348+
mapFromLLVMOrdering(ordering), SSID));
4349+
}
4350+
43124351
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
43134352
LLVMValueRef Cmp, LLVMValueRef New,
43144353
LLVMAtomicOrdering SuccessOrdering,
@@ -4322,6 +4361,17 @@ LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
43224361
singleThread ? SyncScope::SingleThread : SyncScope::System));
43234362
}
43244363

4364+
LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(LLVMBuilderRef B, LLVMValueRef Ptr,
4365+
LLVMValueRef Cmp, LLVMValueRef New,
4366+
LLVMAtomicOrdering SuccessOrdering,
4367+
LLVMAtomicOrdering FailureOrdering,
4368+
unsigned SSID) {
4369+
return wrap(unwrap(B)->CreateAtomicCmpXchg(
4370+
unwrap(Ptr), unwrap(Cmp), unwrap(New), MaybeAlign(),
4371+
mapFromLLVMOrdering(SuccessOrdering),
4372+
mapFromLLVMOrdering(FailureOrdering), SSID));
4373+
}
4374+
43254375
unsigned LLVMGetNumMaskElements(LLVMValueRef SVInst) {
43264376
Value *P = unwrap(SVInst);
43274377
ShuffleVectorInst *I = cast<ShuffleVectorInst>(P);
@@ -4336,25 +4386,29 @@ int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) {
43364386

43374387
int LLVMGetUndefMaskElem(void) { return PoisonMaskElem; }
43384388

4339-
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
4340-
Value *P = unwrap(AtomicInst);
4341-
4389+
static unsigned getAtomicSyncScopeID(Value *P) {
43424390
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
4343-
return I->getSyncScopeID() == SyncScope::SingleThread;
4391+
return I->getSyncScopeID();
43444392
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
4345-
return FI->getSyncScopeID() == SyncScope::SingleThread;
4393+
return FI->getSyncScopeID();
43464394
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
4347-
return SI->getSyncScopeID() == SyncScope::SingleThread;
4395+
return SI->getSyncScopeID();
43484396
else if (LoadInst *LI = dyn_cast<LoadInst>(P))
4349-
return LI->getSyncScopeID() == SyncScope::SingleThread;
4350-
return cast<AtomicCmpXchgInst>(P)->getSyncScopeID() ==
4351-
SyncScope::SingleThread;
4397+
return LI->getSyncScopeID();
4398+
return cast<AtomicCmpXchgInst>(P)->getSyncScopeID();
43524399
}
43534400

4354-
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
4401+
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
43554402
Value *P = unwrap(AtomicInst);
4356-
SyncScope::ID SSID = NewValue ? SyncScope::SingleThread : SyncScope::System;
4403+
return getAtomicSyncScopeID(P) == SyncScope::SingleThread;
4404+
}
4405+
4406+
unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst) {
4407+
Value *P = unwrap(AtomicInst);
4408+
return getAtomicSyncScopeID(P);
4409+
}
43574410

4411+
static void setAtomicSyncScopeID(Value *P, unsigned SSID) {
43584412
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
43594413
return I->setSyncScopeID(SSID);
43604414
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
@@ -4366,6 +4420,17 @@ void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
43664420
return cast<AtomicCmpXchgInst>(P)->setSyncScopeID(SSID);
43674421
}
43684422

4423+
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
4424+
Value *P = unwrap(AtomicInst);
4425+
SyncScope::ID SSID = NewValue ? SyncScope::SingleThread : SyncScope::System;
4426+
setAtomicSyncScopeID(P, SSID);
4427+
}
4428+
4429+
void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID) {
4430+
Value *P = unwrap(AtomicInst);
4431+
setAtomicSyncScopeID(P, SSID);
4432+
}
4433+
43694434
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst) {
43704435
Value *P = unwrap(CmpXchgInst);
43714436
return mapToLLVMOrdering(cast<AtomicCmpXchgInst>(P)->getSuccessOrdering());

llvm/test/Bindings/llvm-c/echo.ll

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,23 @@ define void @memops(ptr %ptr) {
216216
%b = load volatile i8, ptr %ptr
217217
%c = load i8, ptr %ptr, align 8
218218
%d = load atomic i8, ptr %ptr acquire, align 32
219+
%e = load atomic i8, ptr %ptr syncscope("singlethread") acquire, align 32
219220
store i8 0, ptr %ptr
220221
store volatile i8 0, ptr %ptr
221222
store i8 0, ptr %ptr, align 8
222223
store atomic i8 0, ptr %ptr release, align 32
223-
%e = atomicrmw add ptr %ptr, i8 0 monotonic, align 1
224-
%f = atomicrmw volatile xchg ptr %ptr, i8 0 acq_rel, align 8
225-
%g = cmpxchg ptr %ptr, i8 1, i8 2 seq_cst acquire, align 1
226-
%h = cmpxchg weak ptr %ptr, i8 1, i8 2 seq_cst acquire, align 8
227-
%i = cmpxchg volatile ptr %ptr, i8 1, i8 2 monotonic monotonic, align 16
224+
store atomic i8 0, ptr %ptr syncscope("singlethread") release, align 32
225+
%f = atomicrmw add ptr %ptr, i8 0 monotonic, align 1
226+
%g = atomicrmw volatile xchg ptr %ptr, i8 0 acq_rel, align 8
227+
%h = atomicrmw volatile xchg ptr %ptr, i8 0 syncscope("singlethread") acq_rel, align 8
228+
%i = atomicrmw volatile xchg ptr %ptr, i8 0 syncscope("agent") acq_rel, align 8
229+
%j = cmpxchg ptr %ptr, i8 1, i8 2 seq_cst acquire, align 1
230+
%k = cmpxchg weak ptr %ptr, i8 1, i8 2 seq_cst acquire, align 8
231+
%l = cmpxchg volatile ptr %ptr, i8 1, i8 2 monotonic monotonic, align 16
232+
%m = cmpxchg volatile ptr %ptr, i8 1, i8 2 syncscope("singlethread") monotonic monotonic, align 16
233+
%n = cmpxchg volatile ptr %ptr, i8 1, i8 2 syncscope("agent") monotonic monotonic, align 16
234+
fence syncscope("singlethread") acquire
235+
fence syncscope("agent") acquire
228236
ret void
229237
}
230238

0 commit comments

Comments
 (0)