[llvm] [LLVM] Add a C API for creating instructions with custom syncscopes. (PR #104775)
Tim Besard via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 20 00:59:57 PDT 2024
https://github.com/maleadt updated https://github.com/llvm/llvm-project/pull/104775
>From a86400d00a236670634fd171d80a0c5a41f39c8c Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Mon, 19 Aug 2024 14:45:08 +0200
Subject: [PATCH 1/4] [LLVM] Add a C API for creating instructions with custom
syncscopes.
---
llvm/docs/ReleaseNotes.rst | 10 ++++
llvm/include/llvm-c/Core.h | 43 +++++++++++++++
llvm/lib/IR/Core.cpp | 91 ++++++++++++++++++++++++++-----
llvm/test/Bindings/llvm-c/echo.ll | 18 ++++--
4 files changed, 144 insertions(+), 18 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index d40bb2682f9ad8..3ab9e109704461 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -163,6 +163,16 @@ Changes to the C API
* It is now also possible to run the new pass manager on a single function, by calling
``LLVMRunPassesOnFunction`` instead of ``LLVMRunPasses``.
+* Support for creating instructions with custom synchronization scopes has been added:
+
+ * ``LLVMGetSyncScopeID`` and ``LLVMGetSyncScopeIDInContext`` to map a synchronization
+ scope name to an ID, and ``LLVMGetSyncScopeName`` to map an ID back to a name.
+ * ``LLVMBuildFenceSyncScope``, ``LLVMBuildAtomicRMWSyncScope`` and
+ ``LLVMBuildAtomicCmpXchgSyncScope`` versions of the existing builder functions
+ with an additional synchronization scope ID parameter.
+ * ``LLVMGetAtomicSyncScopeID`` and ``LLVMSetAtomicSyncScopeID`` to get and set the
+ synchronization scope of any atomic instruction.
+
Changes to the CodeGen infrastructure
-------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 7d2e7c95520761..6c8b497c15dd70 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -646,6 +646,26 @@ unsigned LLVMGetMDKindIDInContext(LLVMContextRef C, const char *Name,
unsigned SLen);
unsigned LLVMGetMDKindID(const char *Name, unsigned SLen);
+/**
+ * Maps a synchronization scope name to a ID unique within this context.
+ */
+unsigned LLVMGetSyncScopeIDInContext(LLVMContextRef C, const char *Name,
+ unsigned SLen);
+
+/**
+ * Maps a synchronization scope name to a unique ID.
+ *
+ * This is equivalent to calling LLVMGetSyncScopeIDInContext with
+ * LLVMGetGlobalContext() as the context parameter.
+ */
+unsigned LLVMGetSyncScopeID(const char *Name, unsigned SLen);
+
+/**
+ * Maps a synchronization scope ID to its name.
+ */
+const char *LLVMGetSyncScopeName(LLVMContextRef C, unsigned ID,
+ unsigned *Length);
+
/**
* Return an unique id given the name of a enum attribute,
* or 0 if no attribute by that name exists.
@@ -4578,15 +4598,28 @@ LLVMValueRef LLVMBuildPtrDiff2(LLVMBuilderRef, LLVMTypeRef ElemTy,
const char *Name);
LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering ordering,
LLVMBool singleThread, const char *Name);
+LLVMValueRef LLVMBuildFenceSyncScope(LLVMBuilderRef B,
+ LLVMAtomicOrdering ordering, unsigned SSID,
+ const char *Name);
LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B, LLVMAtomicRMWBinOp op,
LLVMValueRef PTR, LLVMValueRef Val,
LLVMAtomicOrdering ordering,
LLVMBool singleThread);
+LLVMValueRef LLVMBuildAtomicRMWSyncScope(LLVMBuilderRef B,
+ LLVMAtomicRMWBinOp op,
+ LLVMValueRef PTR, LLVMValueRef Val,
+ LLVMAtomicOrdering ordering,
+ unsigned SSID);
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
LLVMValueRef Cmp, LLVMValueRef New,
LLVMAtomicOrdering SuccessOrdering,
LLVMAtomicOrdering FailureOrdering,
LLVMBool SingleThread);
+LLVMValueRef LLVMBuildAtomicCmpXchgSyncScope(LLVMBuilderRef B, LLVMValueRef Ptr,
+ LLVMValueRef Cmp, LLVMValueRef New,
+ LLVMAtomicOrdering SuccessOrdering,
+ LLVMAtomicOrdering FailureOrdering,
+ unsigned SSID);
/**
* Get the number of elements in the mask of a ShuffleVector instruction.
@@ -4611,6 +4644,16 @@ int LLVMGetMaskValue(LLVMValueRef ShuffleVectorInst, unsigned Elt);
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst);
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread);
+/**
+ * Returns the synchronization scope ID of an atomic instruction
+ */
+unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst);
+
+/**
+ * Sets the synchronization scope ID of an atomic instruction.
+ */
+void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID);
+
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst);
void LLVMSetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst,
LLVMAtomicOrdering Ordering);
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index dcad76ee8491dd..c8362a236d8e6d 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -146,6 +146,24 @@ unsigned LLVMGetMDKindID(const char *Name, unsigned SLen) {
return LLVMGetMDKindIDInContext(LLVMGetGlobalContext(), Name, SLen);
}
+unsigned LLVMGetSyncScopeIDInContext(LLVMContextRef C, const char *Name,
+ unsigned SLen) {
+ return unwrap(C)->getOrInsertSyncScopeID(StringRef(Name, SLen));
+}
+
+unsigned LLVMGetSyncScopeID(const char *Name, unsigned SLen) {
+ return LLVMGetSyncScopeIDInContext(LLVMGetGlobalContext(), Name, SLen);
+}
+
+const char *LLVMGetSyncScopeName(LLVMContextRef C, unsigned ID,
+ unsigned *Length) {
+ SmallVector<StringRef> SSNs;
+ unwrap(C)->getSyncScopeNames(SSNs);
+ StringRef Name = SSNs[ID].empty() ? "system" : SSNs[ID];
+ *Length = Name.size();
+ return Name.data();
+}
+
unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen) {
return Attribute::getAttrKindFromName(StringRef(Name, SLen));
}
@@ -3949,8 +3967,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 +3976,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 +4332,22 @@ 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);
+
+ SmallVector<StringRef> SSNs;
+ unwrap(B)->getContext().getSyncScopeNames(SSNs);
+ assert(SSID < SSNs.size() && "Invalid SyncScopeID");
+
+ return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
+ MaybeAlign(),
+ mapFromLLVMOrdering(ordering), SSID));
+}
+
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
LLVMValueRef Cmp, LLVMValueRef New,
LLVMAtomicOrdering SuccessOrdering,
@@ -4322,6 +4361,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,25 +4386,29 @@ int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) {
int LLVMGetUndefMaskElem(void) { return PoisonMaskElem; }
-LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
- Value *P = unwrap(AtomicInst);
-
+static unsigned getAtomicSyncScopeID(Value *P) {
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
- return I->getSyncScopeID() == SyncScope::SingleThread;
+ return I->getSyncScopeID();
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
- return FI->getSyncScopeID() == SyncScope::SingleThread;
+ return FI->getSyncScopeID();
else if (StoreInst *SI = dyn_cast<StoreInst>(P))
- return SI->getSyncScopeID() == SyncScope::SingleThread;
+ return SI->getSyncScopeID();
else if (LoadInst *LI = dyn_cast<LoadInst>(P))
- return LI->getSyncScopeID() == SyncScope::SingleThread;
- return cast<AtomicCmpXchgInst>(P)->getSyncScopeID() ==
- SyncScope::SingleThread;
+ return LI->getSyncScopeID();
+ return cast<AtomicCmpXchgInst>(P)->getSyncScopeID();
}
-void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
+LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
Value *P = unwrap(AtomicInst);
- SyncScope::ID SSID = NewValue ? SyncScope::SingleThread : SyncScope::System;
+ return getAtomicSyncScopeID(P) == SyncScope::SingleThread;
+}
+
+unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst) {
+ Value *P = unwrap(AtomicInst);
+ return getAtomicSyncScopeID(P);
+}
+static void setAtomicSyncScopeID(Value *P, unsigned SSID) {
if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
return I->setSyncScopeID(SSID);
else if (FenceInst *FI = dyn_cast<FenceInst>(P))
@@ -4366,6 +4420,17 @@ void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
return cast<AtomicCmpXchgInst>(P)->setSyncScopeID(SSID);
}
+void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
+ Value *P = unwrap(AtomicInst);
+ SyncScope::ID SSID = NewValue ? SyncScope::SingleThread : SyncScope::System;
+ setAtomicSyncScopeID(P, SSID);
+}
+
+void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID) {
+ Value *P = unwrap(AtomicInst);
+ setAtomicSyncScopeID(P, SSID);
+}
+
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst) {
Value *P = unwrap(CmpXchgInst);
return mapToLLVMOrdering(cast<AtomicCmpXchgInst>(P)->getSuccessOrdering());
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index 45e3d0357ebdf2..c4b932034b501a 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -216,15 +216,23 @@ define void @memops(ptr %ptr) {
%b = load volatile i8, ptr %ptr
%c = load i8, ptr %ptr, align 8
%d = load atomic i8, ptr %ptr acquire, align 32
+ %e = load atomic i8, ptr %ptr syncscope("singlethread") acquire, align 32
store i8 0, ptr %ptr
store volatile i8 0, ptr %ptr
store i8 0, ptr %ptr, align 8
store atomic i8 0, ptr %ptr release, align 32
- %e = atomicrmw add ptr %ptr, i8 0 monotonic, align 1
- %f = atomicrmw volatile xchg ptr %ptr, i8 0 acq_rel, align 8
- %g = cmpxchg ptr %ptr, i8 1, i8 2 seq_cst acquire, align 1
- %h = cmpxchg weak ptr %ptr, i8 1, i8 2 seq_cst acquire, align 8
- %i = cmpxchg volatile ptr %ptr, i8 1, i8 2 monotonic monotonic, align 16
+ store atomic i8 0, ptr %ptr syncscope("singlethread") release, align 32
+ %f = atomicrmw add ptr %ptr, i8 0 monotonic, align 1
+ %g = atomicrmw volatile xchg ptr %ptr, i8 0 acq_rel, align 8
+ %h = atomicrmw volatile xchg ptr %ptr, i8 0 syncscope("singlethread") acq_rel, align 8
+ %i = atomicrmw volatile xchg ptr %ptr, i8 0 syncscope("agent") acq_rel, align 8
+ %j = cmpxchg ptr %ptr, i8 1, i8 2 seq_cst acquire, align 1
+ %k = cmpxchg weak ptr %ptr, i8 1, i8 2 seq_cst acquire, align 8
+ %l = cmpxchg volatile ptr %ptr, i8 1, i8 2 monotonic monotonic, align 16
+ %m = cmpxchg volatile ptr %ptr, i8 1, i8 2 syncscope("singlethread") monotonic monotonic, align 16
+ %n = cmpxchg volatile ptr %ptr, i8 1, i8 2 syncscope("agent") monotonic monotonic, align 16
+ fence syncscope("singlethread") acquire
+ fence syncscope("agent") acquire
ret void
}
>From 0b9f0753083861ae72956ebef88f1b5e22774f0c Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Mon, 19 Aug 2024 14:45:51 +0200
Subject: [PATCH 2/4] Fix llvm-c-text to use the same context when cloning
instructions.
---
llvm/tools/llvm-c-test/attributes.c | 4 +--
llvm/tools/llvm-c-test/echo.cpp | 40 +++++++++++++++++++++-------
llvm/tools/llvm-c-test/llvm-c-test.h | 2 +-
llvm/tools/llvm-c-test/module.c | 17 ++++++------
4 files changed, 41 insertions(+), 22 deletions(-)
diff --git a/llvm/tools/llvm-c-test/attributes.c b/llvm/tools/llvm-c-test/attributes.c
index 487769f94dbcba..088684cd3ed362 100644
--- a/llvm/tools/llvm-c-test/attributes.c
+++ b/llvm/tools/llvm-c-test/attributes.c
@@ -20,7 +20,7 @@
int llvm_test_function_attributes(void) {
LLVMEnablePrettyStackTrace();
- LLVMModuleRef M = llvm_load_module(false, true);
+ LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, true);
LLVMValueRef F = LLVMGetFirstFunction(M);
while (F) {
@@ -49,7 +49,7 @@ int llvm_test_function_attributes(void) {
int llvm_test_callsite_attributes(void) {
LLVMEnablePrettyStackTrace();
- LLVMModuleRef M = llvm_load_module(false, true);
+ LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, true);
LLVMValueRef F = LLVMGetFirstFunction(M);
while (F) {
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index 1e78637bf47ca3..696c6d6aa2fe0d 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -520,6 +520,7 @@ struct FunCloner {
check_value_kind(Src, LLVMInstructionValueKind);
if (!LLVMIsAInstruction(Src))
report_fatal_error("Expected an instruction");
+ LLVMContextRef Ctx = LLVMGetTypeContext(LLVMTypeOf(Src));
size_t NameLen;
const char *Name = LLVMGetValueName2(Src, &NameLen);
@@ -754,7 +755,11 @@ struct FunCloner {
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
- LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
+ LLVMBool IsAtomicSingleThread = LLVMIsAtomicSingleThread(Src);
+ if (IsAtomicSingleThread)
+ LLVMSetAtomicSingleThread(Dst, IsAtomicSingleThread);
+ else
+ LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
break;
}
case LLVMStore: {
@@ -764,7 +769,11 @@ struct FunCloner {
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
- LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
+ LLVMBool IsAtomicSingleThread = LLVMIsAtomicSingleThread(Src);
+ if (IsAtomicSingleThread)
+ LLVMSetAtomicSingleThread(Dst, IsAtomicSingleThread);
+ else
+ LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
break;
}
case LLVMGetElementPtr: {
@@ -786,7 +795,11 @@ struct FunCloner {
LLVMAtomicRMWBinOp BinOp = LLVMGetAtomicRMWBinOp(Src);
LLVMAtomicOrdering Ord = LLVMGetOrdering(Src);
LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
- Dst = LLVMBuildAtomicRMW(Builder, BinOp, Ptr, Val, Ord, SingleThread);
+ if (SingleThread)
+ Dst = LLVMBuildAtomicRMW(Builder, BinOp, Ptr, Val, Ord, SingleThread);
+ else
+ Dst = LLVMBuildAtomicRMWSyncScope(Builder, BinOp, Ptr, Val, Ord,
+ LLVMGetAtomicSyncScopeID(Src));
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
LLVMSetValueName2(Dst, Name, NameLen);
@@ -799,9 +812,13 @@ struct FunCloner {
LLVMAtomicOrdering Succ = LLVMGetCmpXchgSuccessOrdering(Src);
LLVMAtomicOrdering Fail = LLVMGetCmpXchgFailureOrdering(Src);
LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
-
- Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail,
- SingleThread);
+ if (SingleThread)
+ Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail,
+ SingleThread);
+ else
+ Dst = LLVMBuildAtomicCmpXchgSyncScope(Builder, Ptr, Cmp, New, Succ,
+ Fail,
+ LLVMGetAtomicSyncScopeID(Src));
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
LLVMSetWeak(Dst, LLVMGetWeak(Src));
@@ -993,7 +1010,11 @@ struct FunCloner {
case LLVMFence: {
LLVMAtomicOrdering Ordering = LLVMGetOrdering(Src);
LLVMBool IsSingleThreaded = LLVMIsAtomicSingleThread(Src);
- Dst = LLVMBuildFence(Builder, Ordering, IsSingleThreaded, Name);
+ if (IsSingleThreaded)
+ Dst = LLVMBuildFence(Builder, Ordering, IsSingleThreaded, Name);
+ else
+ Dst = LLVMBuildFenceSyncScope(Builder, Ordering,
+ LLVMGetAtomicSyncScopeID(Src), Name);
break;
}
case LLVMZExt: {
@@ -1059,7 +1080,6 @@ struct FunCloner {
if (LLVMCanValueUseFastMathFlags(Src))
LLVMSetFastMathFlags(Dst, LLVMGetFastMathFlags(Src));
- auto Ctx = LLVMGetModuleContext(M);
size_t NumMetadataEntries;
auto *AllMetadata =
LLVMInstructionGetAllMetadataOtherThanDebugLoc(Src,
@@ -1609,12 +1629,12 @@ static void clone_symbols(LLVMModuleRef Src, LLVMModuleRef M) {
int llvm_echo(void) {
LLVMEnablePrettyStackTrace();
- LLVMModuleRef Src = llvm_load_module(false, true);
+ LLVMContextRef Ctx = LLVMContextCreate();
+ LLVMModuleRef Src = llvm_load_module(Ctx, false, true);
size_t SourceFileLen;
const char *SourceFileName = LLVMGetSourceFileName(Src, &SourceFileLen);
size_t ModuleIdentLen;
const char *ModuleName = LLVMGetModuleIdentifier(Src, &ModuleIdentLen);
- LLVMContextRef Ctx = LLVMContextCreate();
LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleName, Ctx);
LLVMSetSourceFileName(M, SourceFileName, SourceFileLen);
diff --git a/llvm/tools/llvm-c-test/llvm-c-test.h b/llvm/tools/llvm-c-test/llvm-c-test.h
index 00566660257e07..1da6596cd5a8f2 100644
--- a/llvm/tools/llvm-c-test/llvm-c-test.h
+++ b/llvm/tools/llvm-c-test/llvm-c-test.h
@@ -24,7 +24,7 @@ extern "C" {
void llvm_tokenize_stdin(void (*cb)(char **tokens, int ntokens));
// module.c
-LLVMModuleRef llvm_load_module(bool Lazy, bool New);
+LLVMModuleRef llvm_load_module(LLVMContextRef C, bool Lazy, bool New);
int llvm_module_dump(bool Lazy, bool New);
int llvm_module_list_functions(void);
int llvm_module_list_globals(void);
diff --git a/llvm/tools/llvm-c-test/module.c b/llvm/tools/llvm-c-test/module.c
index 9fc86cfe5404b3..9698f0983d5b63 100644
--- a/llvm/tools/llvm-c-test/module.c
+++ b/llvm/tools/llvm-c-test/module.c
@@ -24,7 +24,7 @@ static void diagnosticHandler(LLVMDiagnosticInfoRef DI, void *C) {
exit(1);
}
-LLVMModuleRef llvm_load_module(bool Lazy, bool New) {
+LLVMModuleRef llvm_load_module(LLVMContextRef C, bool Lazy, bool New) {
LLVMMemoryBufferRef MB;
LLVMModuleRef M;
char *msg = NULL;
@@ -36,17 +36,16 @@ LLVMModuleRef llvm_load_module(bool Lazy, bool New) {
LLVMBool Ret;
if (New) {
- LLVMContextRef C = LLVMGetGlobalContext();
LLVMContextSetDiagnosticHandler(C, diagnosticHandler, NULL);
if (Lazy)
- Ret = LLVMGetBitcodeModule2(MB, &M);
+ Ret = LLVMGetBitcodeModuleInContext2(C, MB, &M);
else
- Ret = LLVMParseBitcode2(MB, &M);
+ Ret = LLVMParseBitcodeInContext2(C, MB, &M);
} else {
if (Lazy)
- Ret = LLVMGetBitcodeModule(MB, &M, &msg);
+ Ret = LLVMGetBitcodeModuleInContext(C, MB, &M, &msg);
else
- Ret = LLVMParseBitcode(MB, &M, &msg);
+ Ret = LLVMParseBitcodeInContext(C, MB, &M, &msg);
}
if (Ret) {
@@ -62,7 +61,7 @@ LLVMModuleRef llvm_load_module(bool Lazy, bool New) {
}
int llvm_module_dump(bool Lazy, bool New) {
- LLVMModuleRef M = llvm_load_module(Lazy, New);
+ LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), Lazy, New);
char *irstr = LLVMPrintModuleToString(M);
puts(irstr);
@@ -74,7 +73,7 @@ int llvm_module_dump(bool Lazy, bool New) {
}
int llvm_module_list_functions(void) {
- LLVMModuleRef M = llvm_load_module(false, false);
+ LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, false);
LLVMValueRef f;
f = LLVMGetFirstFunction(M);
@@ -115,7 +114,7 @@ int llvm_module_list_functions(void) {
}
int llvm_module_list_globals(void) {
- LLVMModuleRef M = llvm_load_module(false, false);
+ LLVMModuleRef M = llvm_load_module(LLVMGetGlobalContext(), false, false);
LLVMValueRef g;
g = LLVMGetFirstGlobal(M);
>From 0028d86595b6fb23c9cbdd603dfef78437a3f5c8 Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Mon, 19 Aug 2024 16:43:02 +0200
Subject: [PATCH 3/4] Address review comments.
---
llvm/docs/ReleaseNotes.rst | 3 +-
llvm/include/llvm-c/Core.h | 17 +--------
llvm/include/llvm/IR/Instructions.h | 19 ++++++++++
llvm/lib/IR/Core.cpp | 59 ++++-------------------------
4 files changed, 28 insertions(+), 70 deletions(-)
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 3ab9e109704461..145b30b1668ea4 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -165,8 +165,7 @@ Changes to the C API
* Support for creating instructions with custom synchronization scopes has been added:
- * ``LLVMGetSyncScopeID`` and ``LLVMGetSyncScopeIDInContext`` to map a synchronization
- scope name to an ID, and ``LLVMGetSyncScopeName`` to map an ID back to a name.
+ * ``LLVMGetSyncScopeID`` to map a synchronization scope name to an ID
* ``LLVMBuildFenceSyncScope``, ``LLVMBuildAtomicRMWSyncScope`` and
``LLVMBuildAtomicCmpXchgSyncScope`` versions of the existing builder functions
with an additional synchronization scope ID parameter.
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 6c8b497c15dd70..c7a75ceb244a69 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -649,22 +649,7 @@ unsigned LLVMGetMDKindID(const char *Name, unsigned SLen);
/**
* Maps a synchronization scope name to a ID unique within this context.
*/
-unsigned LLVMGetSyncScopeIDInContext(LLVMContextRef C, const char *Name,
- unsigned SLen);
-
-/**
- * Maps a synchronization scope name to a unique ID.
- *
- * This is equivalent to calling LLVMGetSyncScopeIDInContext with
- * LLVMGetGlobalContext() as the context parameter.
- */
-unsigned LLVMGetSyncScopeID(const char *Name, unsigned SLen);
-
-/**
- * Maps a synchronization scope ID to its name.
- */
-const char *LLVMGetSyncScopeName(LLVMContextRef C, unsigned ID,
- unsigned *Length);
+unsigned LLVMGetSyncScopeID(LLVMContextRef C, const char *Name, size_t SLen);
/**
* Return an unique id given the name of a enum attribute,
diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 968737a843e292..5640a80c22d49f 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -4942,6 +4942,25 @@ inline std::optional<SyncScope::ID> getAtomicSyncScopeID(const Instruction *I) {
llvm_unreachable("unhandled atomic operation");
}
+/// A helper function that sets an atomic operation's sync scope.
+/// Does nothing if it is not an atomic operation.
+inline void setAtomicSyncScopeID(Instruction *I, SyncScope::ID SSID) {
+ if (!I->isAtomic())
+ return;
+ if (auto *AI = dyn_cast<LoadInst>(I))
+ AI->setSyncScopeID(SSID);
+ else if (auto *AI = dyn_cast<StoreInst>(I))
+ AI->setSyncScopeID(SSID);
+ else if (auto *AI = dyn_cast<FenceInst>(I))
+ AI->setSyncScopeID(SSID);
+ else if (auto *AI = dyn_cast<AtomicCmpXchgInst>(I))
+ AI->setSyncScopeID(SSID);
+ else if (auto *AI = dyn_cast<AtomicRMWInst>(I))
+ AI->setSyncScopeID(SSID);
+ else
+ llvm_unreachable("unhandled atomic operation");
+}
+
//===----------------------------------------------------------------------===//
// FreezeInst Class
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index c8362a236d8e6d..18cc0354947384 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -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,24 +147,10 @@ unsigned LLVMGetMDKindID(const char *Name, unsigned SLen) {
return LLVMGetMDKindIDInContext(LLVMGetGlobalContext(), Name, SLen);
}
-unsigned LLVMGetSyncScopeIDInContext(LLVMContextRef C, const char *Name,
- unsigned SLen) {
+unsigned LLVMGetSyncScopeID(LLVMContextRef C, const char *Name, size_t SLen) {
return unwrap(C)->getOrInsertSyncScopeID(StringRef(Name, SLen));
}
-unsigned LLVMGetSyncScopeID(const char *Name, unsigned SLen) {
- return LLVMGetSyncScopeIDInContext(LLVMGetGlobalContext(), Name, SLen);
-}
-
-const char *LLVMGetSyncScopeName(LLVMContextRef C, unsigned ID,
- unsigned *Length) {
- SmallVector<StringRef> SSNs;
- unwrap(C)->getSyncScopeNames(SSNs);
- StringRef Name = SSNs[ID].empty() ? "system" : SSNs[ID];
- *Length = Name.size();
- return Name.data();
-}
-
unsigned LLVMGetEnumAttributeKindForName(const char *Name, size_t SLen) {
return Attribute::getAttrKindFromName(StringRef(Name, SLen));
}
@@ -4338,11 +4325,6 @@ LLVMValueRef LLVMBuildAtomicRMWSyncScope(LLVMBuilderRef B,
LLVMAtomicOrdering ordering,
unsigned SSID) {
AtomicRMWInst::BinOp intop = mapFromLLVMRMWBinOp(op);
-
- SmallVector<StringRef> SSNs;
- unwrap(B)->getContext().getSyncScopeNames(SSNs);
- assert(SSID < SSNs.size() && "Invalid SyncScopeID");
-
return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
MaybeAlign(),
mapFromLLVMOrdering(ordering), SSID));
@@ -4386,49 +4368,22 @@ int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) {
int LLVMGetUndefMaskElem(void) { return PoisonMaskElem; }
-static unsigned getAtomicSyncScopeID(Value *P) {
- if (AtomicRMWInst *I = dyn_cast<AtomicRMWInst>(P))
- return I->getSyncScopeID();
- else if (FenceInst *FI = dyn_cast<FenceInst>(P))
- return FI->getSyncScopeID();
- else if (StoreInst *SI = dyn_cast<StoreInst>(P))
- return SI->getSyncScopeID();
- else if (LoadInst *LI = dyn_cast<LoadInst>(P))
- return LI->getSyncScopeID();
- return cast<AtomicCmpXchgInst>(P)->getSyncScopeID();
-}
-
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
- Value *P = unwrap(AtomicInst);
- return getAtomicSyncScopeID(P) == SyncScope::SingleThread;
+ return getAtomicSyncScopeID(unwrap<Instruction>(AtomicInst)).value() ==
+ SyncScope::SingleThread;
}
unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst) {
- Value *P = unwrap(AtomicInst);
- return getAtomicSyncScopeID(P);
-}
-
-static void setAtomicSyncScopeID(Value *P, unsigned 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);
+ return getAtomicSyncScopeID(unwrap<Instruction>(AtomicInst)).value();
}
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
- Value *P = unwrap(AtomicInst);
SyncScope::ID SSID = NewValue ? SyncScope::SingleThread : SyncScope::System;
- setAtomicSyncScopeID(P, SSID);
+ setAtomicSyncScopeID(unwrap<Instruction>(AtomicInst), SSID);
}
void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID) {
- Value *P = unwrap(AtomicInst);
- setAtomicSyncScopeID(P, SSID);
+ setAtomicSyncScopeID(unwrap<Instruction>(AtomicInst), SSID);
}
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst) {
>From ce5db1ec82a78e57caab172068dcf5e7ae5f486f Mon Sep 17 00:00:00 2001
From: Tim Besard <tim.besard at gmail.com>
Date: Mon, 19 Aug 2024 20:45:39 +0200
Subject: [PATCH 4/4] Make LLVMIsAtomicSingleThread work on non-atomic
instructions.
Add LLVMIsAtomic so that users can guard uses of LLVMGetAtomicSyncScopeID.
---
llvm/include/llvm-c/Core.h | 8 +++++++-
llvm/lib/IR/Core.cpp | 23 +++++++++++++++++------
llvm/tools/llvm-c-test/echo.cpp | 24 ++++++++++++++----------
3 files changed, 38 insertions(+), 17 deletions(-)
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index c7a75ceb244a69..f375145d9d1d09 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -4630,7 +4630,13 @@ LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst);
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread);
/**
- * Returns the synchronization scope ID of an atomic instruction
+ * Returns whether an instruction is an atomic instruction, e.g., atomicrmw,
+ * cmpxchg, fence, or loads and stores with atomic ordering.
+ */
+LLVMBool LLVMIsAtomic(LLVMValueRef Inst);
+
+/**
+ * Returns the synchronization scope ID of an atomic instruction.
*/
unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst);
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 18cc0354947384..5b4756ee64e476 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -4368,13 +4368,16 @@ int LLVMGetMaskValue(LLVMValueRef SVInst, unsigned Elt) {
int LLVMGetUndefMaskElem(void) { return PoisonMaskElem; }
-LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
- return getAtomicSyncScopeID(unwrap<Instruction>(AtomicInst)).value() ==
- SyncScope::SingleThread;
+LLVMBool LLVMIsAtomic(LLVMValueRef Inst) {
+ return unwrap<Instruction>(Inst)->isAtomic();
}
-unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst) {
- return getAtomicSyncScopeID(unwrap<Instruction>(AtomicInst)).value();
+LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst) {
+ // Backwards compatibility: return false for non-atomic instructions
+ Instruction *I = unwrap<Instruction>(AtomicInst);
+ if (!I->isAtomic())
+ return 0;
+ return getAtomicSyncScopeID(I).value() == SyncScope::SingleThread;
}
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
@@ -4382,8 +4385,16 @@ void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool NewValue) {
setAtomicSyncScopeID(unwrap<Instruction>(AtomicInst), SSID);
}
+unsigned LLVMGetAtomicSyncScopeID(LLVMValueRef AtomicInst) {
+ Instruction *I = unwrap<Instruction>(AtomicInst);
+ assert(I->isAtomic() && "Expected an atomic instruction");
+ return getAtomicSyncScopeID(I).value();
+}
+
void LLVMSetAtomicSyncScopeID(LLVMValueRef AtomicInst, unsigned SSID) {
- setAtomicSyncScopeID(unwrap<Instruction>(AtomicInst), SSID);
+ Instruction *I = unwrap<Instruction>(AtomicInst);
+ assert(I->isAtomic() && "Expected an atomic instruction");
+ setAtomicSyncScopeID(I, SSID);
}
LLVMAtomicOrdering LLVMGetCmpXchgSuccessOrdering(LLVMValueRef CmpXchgInst) {
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index 696c6d6aa2fe0d..3ad1b58c50a882 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -755,11 +755,13 @@ struct FunCloner {
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
- LLVMBool IsAtomicSingleThread = LLVMIsAtomicSingleThread(Src);
- if (IsAtomicSingleThread)
- LLVMSetAtomicSingleThread(Dst, IsAtomicSingleThread);
- else
- LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
+ if (LLVMIsAtomic(Src)) {
+ LLVMBool IsAtomicSingleThread = LLVMIsAtomicSingleThread(Src);
+ if (IsAtomicSingleThread)
+ LLVMSetAtomicSingleThread(Dst, IsAtomicSingleThread);
+ else
+ LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
+ }
break;
}
case LLVMStore: {
@@ -769,11 +771,13 @@ struct FunCloner {
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
- LLVMBool IsAtomicSingleThread = LLVMIsAtomicSingleThread(Src);
- if (IsAtomicSingleThread)
- LLVMSetAtomicSingleThread(Dst, IsAtomicSingleThread);
- else
- LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
+ if (LLVMIsAtomic(Src)) {
+ LLVMBool IsAtomicSingleThread = LLVMIsAtomicSingleThread(Src);
+ if (IsAtomicSingleThread)
+ LLVMSetAtomicSingleThread(Dst, IsAtomicSingleThread);
+ else
+ LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
+ }
break;
}
case LLVMGetElementPtr: {
More information about the llvm-commits
mailing list