[llvm] eb7d535 - [LLVM] Add a C API for creating instructions with custom syncscopes. (#104775)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 20 05:12:38 PDT 2024
Author: Tim Besard
Date: 2024-08-20T14:12:35+02:00
New Revision: eb7d535199d7fc3de763276093b97141a041d3d6
URL: https://github.com/llvm/llvm-project/commit/eb7d535199d7fc3de763276093b97141a041d3d6
DIFF: https://github.com/llvm/llvm-project/commit/eb7d535199d7fc3de763276093b97141a041d3d6.diff
LOG: [LLVM] Add a C API for creating instructions with custom syncscopes. (#104775)
Another upstreaming of C API extensions we have in Julia/LLVM.jl.
Although [we went](https://github.com/maleadt/LLVM.jl/pull/431) with a
string-based API there, here I'm proposing something that's similar to
existing metadata/attribute APIs:
- explicit functions to map syncscope names to IDs, and back
- `LLVM*SyncScope` versions of builder APIs that already take a
`SingleThread` argument: atomic rmw, atomic xchg, fence
- `LLVMGetAtomicSyncScopeID` and `LLVMSetAtomicSyncScopeID` for other
atomic instructions
- testing through `llvm-c-test`'s `--echo` functionality
Added:
Modified:
llvm/docs/ReleaseNotes.rst
llvm/include/llvm-c/Core.h
llvm/include/llvm/IR/Instructions.h
llvm/lib/IR/Core.cpp
llvm/test/Bindings/llvm-c/echo.ll
llvm/tools/llvm-c-test/attributes.c
llvm/tools/llvm-c-test/echo.cpp
llvm/tools/llvm-c-test/llvm-c-test.h
llvm/tools/llvm-c-test/module.c
llvm/unittests/IR/InstructionsTest.cpp
Removed:
################################################################################
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 7405023f9f27ed..005c59e00fb128 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -169,6 +169,19 @@ 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`` 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.
+ * ``LLVMGetAtomicSyncScopeID`` and ``LLVMSetAtomicSyncScopeID`` to get and set the
+ synchronization scope of any atomic instruction.
+ * ``LLVMIsAtomic`` to check if an instruction is atomic, for use with the above functions.
+ Because of backwards compatibility, ``LLVMIsAtomicSingleThread`` and
+ ``LLVMSetAtomicSingleThread`` continue to work with any instruction type.
+
+
Changes to the CodeGen infrastructure
-------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index 6c45af41631e7e..a0786efb51fdb2 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -646,6 +646,11 @@ 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 LLVMGetSyncScopeID(LLVMContextRef C, const char *Name, size_t SLen);
+
/**
* Return an unique id given the name of a enum attribute,
* or 0 if no attribute by that name exists.
@@ -4592,15 +4597,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.
@@ -4625,6 +4643,22 @@ int LLVMGetMaskValue(LLVMValueRef ShuffleVectorInst, unsigned Elt);
LLVMBool LLVMIsAtomicSingleThread(LLVMValueRef AtomicInst);
void LLVMSetAtomicSingleThread(LLVMValueRef AtomicInst, LLVMBool SingleThread);
+/**
+ * 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);
+
+/**
+ * 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/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h
index 968737a843e292..dbd7d49a3e7672 100644
--- a/llvm/include/llvm/IR/Instructions.h
+++ b/llvm/include/llvm/IR/Instructions.h
@@ -4942,6 +4942,23 @@ 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.
+inline void setAtomicSyncScopeID(Instruction *I, SyncScope::ID SSID) {
+ assert(I->isAtomic());
+ 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 fc5c6222fc7880..7665385025bd91 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,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));
}
@@ -3957,8 +3962,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(
@@ -3968,6 +3971,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) {
@@ -4317,6 +4327,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(),
+ mapFromLLVMOrdering(ordering), SSID));
+}
+
LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B, LLVMValueRef Ptr,
LLVMValueRef Cmp, LLVMValueRef New,
LLVMAtomicOrdering SuccessOrdering,
@@ -4330,6 +4351,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);
@@ -4344,34 +4376,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) {
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
}
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..4173e49e60a046 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,8 @@ struct FunCloner {
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
- LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
+ if (LLVMIsAtomic(Src))
+ LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
break;
}
case LLVMStore: {
@@ -764,7 +766,8 @@ struct FunCloner {
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
- LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
+ if (LLVMIsAtomic(Src))
+ LLVMSetAtomicSyncScopeID(Dst, LLVMGetAtomicSyncScopeID(Src));
break;
}
case LLVMGetElementPtr: {
@@ -785,8 +788,8 @@ struct FunCloner {
LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 1));
LLVMAtomicRMWBinOp BinOp = LLVMGetAtomicRMWBinOp(Src);
LLVMAtomicOrdering Ord = LLVMGetOrdering(Src);
- LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
- Dst = LLVMBuildAtomicRMW(Builder, BinOp, Ptr, Val, Ord, SingleThread);
+ Dst = LLVMBuildAtomicRMWSyncScope(Builder, BinOp, Ptr, Val, Ord,
+ LLVMGetAtomicSyncScopeID(Src));
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
LLVMSetValueName2(Dst, Name, NameLen);
@@ -798,10 +801,8 @@ struct FunCloner {
LLVMValueRef New = CloneValue(LLVMGetOperand(Src, 2));
LLVMAtomicOrdering Succ = LLVMGetCmpXchgSuccessOrdering(Src);
LLVMAtomicOrdering Fail = LLVMGetCmpXchgFailureOrdering(Src);
- LLVMBool SingleThread = LLVMIsAtomicSingleThread(Src);
-
- Dst = LLVMBuildAtomicCmpXchg(Builder, Ptr, Cmp, New, Succ, Fail,
- SingleThread);
+ Dst = LLVMBuildAtomicCmpXchgSyncScope(
+ Builder, Ptr, Cmp, New, Succ, Fail, LLVMGetAtomicSyncScopeID(Src));
LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
LLVMSetWeak(Dst, LLVMGetWeak(Src));
@@ -992,8 +993,8 @@ struct FunCloner {
}
case LLVMFence: {
LLVMAtomicOrdering Ordering = LLVMGetOrdering(Src);
- LLVMBool IsSingleThreaded = LLVMIsAtomicSingleThread(Src);
- Dst = LLVMBuildFence(Builder, Ordering, IsSingleThreaded, Name);
+ Dst = LLVMBuildFenceSyncScope(Builder, Ordering,
+ LLVMGetAtomicSyncScopeID(Src), Name);
break;
}
case LLVMZExt: {
@@ -1059,7 +1060,6 @@ struct FunCloner {
if (LLVMCanValueUseFastMathFlags(Src))
LLVMSetFastMathFlags(Dst, LLVMGetFastMathFlags(Src));
- auto Ctx = LLVMGetModuleContext(M);
size_t NumMetadataEntries;
auto *AllMetadata =
LLVMInstructionGetAllMetadataOtherThanDebugLoc(Src,
@@ -1609,12 +1609,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);
diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp
index 44b25035dde2c5..529edc88ebc331 100644
--- a/llvm/unittests/IR/InstructionsTest.cpp
+++ b/llvm/unittests/IR/InstructionsTest.cpp
@@ -1159,7 +1159,8 @@ TEST(InstructionsTest, ShuffleMaskQueries) {
EXPECT_TRUE(
ShuffleVectorInst::isTransposeMask(ConstantVector::get({C1, C3}), 2));
- // Nothing special about the values here - just re-using inputs to reduce code.
+ // Nothing special about the values here - just re-using inputs to reduce
+ // code.
Constant *V0 = ConstantVector::get({C0, C1, C2, C3});
Constant *V1 = ConstantVector::get({C3, C2, C1, C0});
@@ -1216,7 +1217,7 @@ TEST(InstructionsTest, ShuffleMaskQueries) {
EXPECT_FALSE(Id6->isIdentityWithExtract());
EXPECT_FALSE(Id6->isConcat());
delete Id6;
-
+
// Result has more elements than operands, but extra elements are not undef.
ShuffleVectorInst *Id7 = new ShuffleVectorInst(V0, V1,
ConstantVector::get({C0, C1, C2, C3, CU, C1}));
@@ -1225,7 +1226,7 @@ TEST(InstructionsTest, ShuffleMaskQueries) {
EXPECT_FALSE(Id7->isIdentityWithExtract());
EXPECT_FALSE(Id7->isConcat());
delete Id7;
-
+
// Result has more elements than operands; choose from Op0 and Op1 is not identity.
ShuffleVectorInst *Id8 = new ShuffleVectorInst(V0, V1,
ConstantVector::get({C4, CU, C2, C3, CU, CU}));
@@ -1814,5 +1815,50 @@ TEST(InstructionsTest, InsertAtEnd) {
EXPECT_EQ(Ret->getNextNode(), I);
}
+TEST(InstructionsTest, AtomicSyncscope) {
+ LLVMContext Ctx;
+
+ Module M("Mod", Ctx);
+ FunctionType *FT = FunctionType::get(Type::getVoidTy(Ctx), {}, false);
+ Function *F = Function::Create(FT, Function::ExternalLinkage, "Fun", M);
+ BasicBlock *BB = BasicBlock::Create(Ctx, "Entry", F);
+ IRBuilder<> Builder(BB);
+
+ // SyncScope-variants of LLVM C IRBuilder APIs are tested by llvm-c-test,
+ // so cover the old versions (with a SingleThreaded argument) here.
+ Value *Ptr = ConstantPointerNull::get(Builder.getPtrTy());
+ Value *Val = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
+
+ // fence
+ LLVMValueRef Fence = LLVMBuildFence(
+ wrap(&Builder), LLVMAtomicOrderingSequentiallyConsistent, 0, "");
+ EXPECT_FALSE(LLVMIsAtomicSingleThread(Fence));
+ Fence = LLVMBuildFence(wrap(&Builder),
+ LLVMAtomicOrderingSequentiallyConsistent, 1, "");
+ EXPECT_TRUE(LLVMIsAtomicSingleThread(Fence));
+
+ // atomicrmw
+ LLVMValueRef AtomicRMW = LLVMBuildAtomicRMW(
+ wrap(&Builder), LLVMAtomicRMWBinOpXchg, wrap(Ptr), wrap(Val),
+ LLVMAtomicOrderingSequentiallyConsistent, 0);
+ EXPECT_FALSE(LLVMIsAtomicSingleThread(AtomicRMW));
+ AtomicRMW = LLVMBuildAtomicRMW(wrap(&Builder), LLVMAtomicRMWBinOpXchg,
+ wrap(Ptr), wrap(Val),
+ LLVMAtomicOrderingSequentiallyConsistent, 1);
+ EXPECT_TRUE(LLVMIsAtomicSingleThread(AtomicRMW));
+
+ // cmpxchg
+ LLVMValueRef CmpXchg =
+ LLVMBuildAtomicCmpXchg(wrap(&Builder), wrap(Ptr), wrap(Val), wrap(Val),
+ LLVMAtomicOrderingSequentiallyConsistent,
+ LLVMAtomicOrderingSequentiallyConsistent, 0);
+ EXPECT_FALSE(LLVMIsAtomicSingleThread(CmpXchg));
+ CmpXchg =
+ LLVMBuildAtomicCmpXchg(wrap(&Builder), wrap(Ptr), wrap(Val), wrap(Val),
+ LLVMAtomicOrderingSequentiallyConsistent,
+ LLVMAtomicOrderingSequentiallyConsistent, 1);
+ EXPECT_TRUE(LLVMIsAtomicSingleThread(CmpXchg));
+}
+
} // end anonymous namespace
} // end namespace llvm
More information about the llvm-commits
mailing list