[llvm] 86763a8 - [LLVM-C] Support operand bundles (#73914)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 11 00:47:38 PST 2023
Author: Quinton Miller
Date: 2023-12-11T09:47:33+01:00
New Revision: 86763a8cc499baa0328ea485d3823875946de023
URL: https://github.com/llvm/llvm-project/commit/86763a8cc499baa0328ea485d3823875946de023
DIFF: https://github.com/llvm/llvm-project/commit/86763a8cc499baa0328ea485d3823875946de023.diff
LOG: [LLVM-C] Support operand bundles (#73914)
Added the following functions for manipulating operand bundles, as well as
building ``call`` and ``invoke`` instructions that use operand bundles:
* LLVMBuildCallWithOperandBundles
* LLVMBuildInvokeWithOperandBundles
* LLVMCreateOperandBundle
* LLVMDisposeOperandBundle
* LLVMGetNumOperandBundles
* LLVMGetOperandBundleAtIndex
* LLVMGetNumOperandBundleArgs
* LLVMGetOperandBundleArgAtIndex
* LLVMGetOperandBundleTag
Fixes #71873.
Added:
Modified:
llvm/docs/ReleaseNotes.rst
llvm/include/llvm-c/Core.h
llvm/include/llvm-c/Types.h
llvm/lib/IR/Core.cpp
llvm/test/Bindings/llvm-c/echo.ll
llvm/tools/llvm-c-test/echo.cpp
Removed:
################################################################################
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index fcb671cf1dfa20..6b70146efe8246 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -206,6 +206,19 @@ Changes to the C API
on zext instructions, and ``LLVMGetIsDisjoint`` and ``LLVMSetIsDisjoint``
for getting/setting the new disjoint flag on or instructions.
+* Added the following functions for manipulating operand bundles, as well as
+ building ``call`` and ``invoke`` instructions that use operand bundles:
+
+ * ``LLVMBuildCallWithOperandBundles``
+ * ``LLVMBuildInvokeWithOperandBundles``
+ * ``LLVMCreateOperandBundle``
+ * ``LLVMDisposeOperandBundle``
+ * ``LLVMGetNumOperandBundles``
+ * ``LLVMGetOperandBundleAtIndex``
+ * ``LLVMGetNumOperandBundleArgs``
+ * ``LLVMGetOperandBundleArgAtIndex``
+ * ``LLVMGetOperandBundleTag``
+
Changes to the CodeGen infrastructure
-------------------------------------
diff --git a/llvm/include/llvm-c/Core.h b/llvm/include/llvm-c/Core.h
index a575ec3709fe4b..7cb809d378c957 100644
--- a/llvm/include/llvm-c/Core.h
+++ b/llvm/include/llvm-c/Core.h
@@ -3000,6 +3000,74 @@ LLVMValueRef LLVMMDNodeInContext(LLVMContextRef C, LLVMValueRef *Vals,
/** Deprecated: Use LLVMMDNodeInContext2 instead. */
LLVMValueRef LLVMMDNode(LLVMValueRef *Vals, unsigned Count);
+/**
+ * @}
+ */
+
+/**
+ * @defgroup LLVMCCoreOperandBundle Operand Bundles
+ *
+ * Functions in this group operate on LLVMOperandBundleRef instances that
+ * correspond to llvm::OperandBundleDef instances.
+ *
+ * @see llvm::OperandBundleDef
+ *
+ * @{
+ */
+
+/**
+ * Create a new operand bundle.
+ *
+ * Every invocation should be paired with LLVMDisposeOperandBundle() or memory
+ * will be leaked.
+ *
+ * @param Tag Tag name of the operand bundle
+ * @param TagLen Length of Tag
+ * @param Args Memory address of an array of bundle operands
+ * @param NumArgs Length of Args
+ */
+LLVMOperandBundleRef LLVMCreateOperandBundle(const char *Tag, size_t TagLen,
+ LLVMValueRef *Args,
+ unsigned NumArgs);
+
+/**
+ * Destroy an operand bundle.
+ *
+ * This must be called for every created operand bundle or memory will be
+ * leaked.
+ */
+void LLVMDisposeOperandBundle(LLVMOperandBundleRef Bundle);
+
+/**
+ * Obtain the tag of an operand bundle as a string.
+ *
+ * @param Bundle Operand bundle to obtain tag of.
+ * @param Len Out parameter which holds the length of the returned string.
+ * @return The tag name of Bundle.
+ * @see OperandBundleDef::getTag()
+ */
+const char *LLVMGetOperandBundleTag(LLVMOperandBundleRef Bundle, size_t *Len);
+
+/**
+ * Obtain the number of operands for an operand bundle.
+ *
+ * @param Bundle Operand bundle to obtain operand count of.
+ * @return The number of operands.
+ * @see OperandBundleDef::input_size()
+ */
+unsigned LLVMGetNumOperandBundleArgs(LLVMOperandBundleRef Bundle);
+
+/**
+ * Obtain the operand for an operand bundle at the given index.
+ *
+ * @param Bundle Operand bundle to obtain operand of.
+ * @param Index An operand index, must be less than
+ * LLVMGetNumOperandBundleArgs().
+ * @return The operand.
+ */
+LLVMValueRef LLVMGetOperandBundleArgAtIndex(LLVMOperandBundleRef Bundle,
+ unsigned Index);
+
/**
* @}
*/
@@ -3451,6 +3519,24 @@ LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef C);
*/
LLVMValueRef LLVMGetCalledValue(LLVMValueRef Instr);
+/**
+ * Obtain the number of operand bundles attached to this instruction.
+ *
+ * This only works on llvm::CallInst and llvm::InvokeInst instructions.
+ *
+ * @see llvm::CallBase::getNumOperandBundles()
+ */
+unsigned LLVMGetNumOperandBundles(LLVMValueRef C);
+
+/**
+ * Obtain the operand bundle attached to this instruction at the given index.
+ * Use LLVMDisposeOperandBundle to free the operand bundle.
+ *
+ * This only works on llvm::CallInst and llvm::InvokeInst instructions.
+ */
+LLVMOperandBundleRef LLVMGetOperandBundleAtIndex(LLVMValueRef C,
+ unsigned Index);
+
/**
* Obtain whether a call instruction is a tail call.
*
@@ -3815,6 +3901,10 @@ LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
const char *Name);
+LLVMValueRef LLVMBuildInvokeWithOperandBundles(
+ LLVMBuilderRef, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args,
+ unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
+ LLVMOperandBundleRef *Bundles, unsigned NumBundles, const char *Name);
LLVMValueRef LLVMBuildUnreachable(LLVMBuilderRef);
/* Exception Handling */
@@ -4121,6 +4211,11 @@ LLVMValueRef LLVMBuildPhi(LLVMBuilderRef, LLVMTypeRef Ty, const char *Name);
LLVMValueRef LLVMBuildCall2(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn,
LLVMValueRef *Args, unsigned NumArgs,
const char *Name);
+LLVMValueRef
+LLVMBuildCallWithOperandBundles(LLVMBuilderRef, LLVMTypeRef, LLVMValueRef Fn,
+ LLVMValueRef *Args, unsigned NumArgs,
+ LLVMOperandBundleRef *Bundles,
+ unsigned NumBundles, const char *Name);
LLVMValueRef LLVMBuildSelect(LLVMBuilderRef, LLVMValueRef If,
LLVMValueRef Then, LLVMValueRef Else,
const char *Name);
diff --git a/llvm/include/llvm-c/Types.h b/llvm/include/llvm-c/Types.h
index 4e9967372d79f5..d5474d986309fa 100644
--- a/llvm/include/llvm-c/Types.h
+++ b/llvm/include/llvm-c/Types.h
@@ -132,6 +132,11 @@ typedef struct LLVMOpaquePassManager *LLVMPassManagerRef;
* @see llvm::Use */
typedef struct LLVMOpaqueUse *LLVMUseRef;
+/**
+ * @see llvm::OperandBundleDef
+ */
+typedef struct LLVMOpaqueOperandBundle *LLVMOperandBundleRef;
+
/**
* Used to represent an attributes.
*
diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp
index 7832028bf36711..96629de8a7534e 100644
--- a/llvm/lib/IR/Core.cpp
+++ b/llvm/lib/IR/Core.cpp
@@ -43,6 +43,8 @@
using namespace llvm;
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OperandBundleDef, LLVMOperandBundleRef)
+
#define DEBUG_TYPE "ir"
void llvm::initializeCore(PassRegistry &Registry) {
@@ -2567,6 +2569,34 @@ void LLVMRemoveGlobalIFunc(LLVMValueRef IFunc) {
unwrap<GlobalIFunc>(IFunc)->removeFromParent();
}
+/*--.. Operations on operand bundles........................................--*/
+
+LLVMOperandBundleRef LLVMCreateOperandBundle(const char *Tag, size_t TagLen,
+ LLVMValueRef *Args,
+ unsigned NumArgs) {
+ return wrap(new OperandBundleDef(std::string(Tag, TagLen),
+ ArrayRef(unwrap(Args), NumArgs)));
+}
+
+void LLVMDisposeOperandBundle(LLVMOperandBundleRef Bundle) {
+ delete unwrap(Bundle);
+}
+
+const char *LLVMGetOperandBundleTag(LLVMOperandBundleRef Bundle, size_t *Len) {
+ StringRef Str = unwrap(Bundle)->getTag();
+ *Len = Str.size();
+ return Str.data();
+}
+
+unsigned LLVMGetNumOperandBundleArgs(LLVMOperandBundleRef Bundle) {
+ return unwrap(Bundle)->inputs().size();
+}
+
+LLVMValueRef LLVMGetOperandBundleArgAtIndex(LLVMOperandBundleRef Bundle,
+ unsigned Index) {
+ return wrap(unwrap(Bundle)->inputs()[Index]);
+}
+
/*--.. Operations on basic blocks ..........................................--*/
LLVMValueRef LLVMBasicBlockAsValue(LLVMBasicBlockRef BB) {
@@ -2858,6 +2888,16 @@ LLVMTypeRef LLVMGetCalledFunctionType(LLVMValueRef Instr) {
return wrap(unwrap<CallBase>(Instr)->getFunctionType());
}
+unsigned LLVMGetNumOperandBundles(LLVMValueRef C) {
+ return unwrap<CallBase>(C)->getNumOperandBundles();
+}
+
+LLVMOperandBundleRef LLVMGetOperandBundleAtIndex(LLVMValueRef C,
+ unsigned Index) {
+ return wrap(
+ new OperandBundleDef(unwrap<CallBase>(C)->getOperandBundleAt(Index)));
+}
+
/*--.. Operations on call instructions (only) ..............................--*/
LLVMBool LLVMIsTailCall(LLVMValueRef Call) {
@@ -3140,6 +3180,20 @@ LLVMValueRef LLVMBuildInvoke2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
ArrayRef(unwrap(Args), NumArgs), Name));
}
+LLVMValueRef LLVMBuildInvokeWithOperandBundles(
+ LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, LLVMValueRef *Args,
+ unsigned NumArgs, LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
+ LLVMOperandBundleRef *Bundles, unsigned NumBundles, const char *Name) {
+ SmallVector<OperandBundleDef, 8> OBs;
+ for (auto *Bundle : ArrayRef(Bundles, NumBundles)) {
+ OperandBundleDef *OB = unwrap(Bundle);
+ OBs.push_back(*OB);
+ }
+ return wrap(unwrap(B)->CreateInvoke(
+ unwrap<FunctionType>(Ty), unwrap(Fn), unwrap(Then), unwrap(Catch),
+ ArrayRef(unwrap(Args), NumArgs), OBs, Name));
+}
+
LLVMValueRef LLVMBuildLandingPad(LLVMBuilderRef B, LLVMTypeRef Ty,
LLVMValueRef PersFn, unsigned NumClauses,
const char *Name) {
@@ -3878,6 +3932,21 @@ LLVMValueRef LLVMBuildCall2(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
ArrayRef(unwrap(Args), NumArgs), Name));
}
+LLVMValueRef
+LLVMBuildCallWithOperandBundles(LLVMBuilderRef B, LLVMTypeRef Ty,
+ LLVMValueRef Fn, LLVMValueRef *Args,
+ unsigned NumArgs, LLVMOperandBundleRef *Bundles,
+ unsigned NumBundles, const char *Name) {
+ FunctionType *FTy = unwrap<FunctionType>(Ty);
+ SmallVector<OperandBundleDef, 8> OBs;
+ for (auto *Bundle : ArrayRef(Bundles, NumBundles)) {
+ OperandBundleDef *OB = unwrap(Bundle);
+ OBs.push_back(*OB);
+ }
+ return wrap(unwrap(B)->CreateCall(
+ FTy, unwrap(Fn), ArrayRef(unwrap(Args), NumArgs), OBs, Name));
+}
+
LLVMValueRef LLVMBuildSelect(LLVMBuilderRef B, LLVMValueRef If,
LLVMValueRef Then, LLVMValueRef Else,
const char *Name) {
diff --git a/llvm/test/Bindings/llvm-c/echo.ll b/llvm/test/Bindings/llvm-c/echo.ll
index 0775cbb673e4ee..2e195beebd7bb3 100644
--- a/llvm/test/Bindings/llvm-c/echo.ll
+++ b/llvm/test/Bindings/llvm-c/echo.ll
@@ -269,6 +269,17 @@ exit:
ret void
}
+define void @operandbundles() personality ptr @personalityFn {
+ call void @decl() [ "foo"(), "bar\00x"(i32 0, ptr null, token none) ]
+ invoke void @decl() [ "baz"(label %bar) ] to label %foo unwind label %bar
+foo:
+ ret void
+bar:
+ %1 = landingpad { ptr, i32 }
+ cleanup
+ ret void
+}
+
define void @with_debuginfo() !dbg !4 {
ret void, !dbg !7
}
diff --git a/llvm/tools/llvm-c-test/echo.cpp b/llvm/tools/llvm-c-test/echo.cpp
index e2617583ff9bab..bfc14e85a12bff 100644
--- a/llvm/tools/llvm-c-test/echo.cpp
+++ b/llvm/tools/llvm-c-test/echo.cpp
@@ -548,16 +548,26 @@ struct FunCloner {
break;
case LLVMInvoke: {
SmallVector<LLVMValueRef, 8> Args;
- int ArgCount = LLVMGetNumArgOperands(Src);
- for (int i = 0; i < ArgCount; i++)
+ SmallVector<LLVMOperandBundleRef, 8> Bundles;
+ unsigned ArgCount = LLVMGetNumArgOperands(Src);
+ for (unsigned i = 0; i < ArgCount; ++i)
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
+ unsigned BundleCount = LLVMGetNumOperandBundles(Src);
+ for (unsigned i = 0; i < BundleCount; ++i) {
+ auto Bundle = LLVMGetOperandBundleAtIndex(Src, i);
+ Bundles.push_back(CloneOB(Bundle));
+ LLVMDisposeOperandBundle(Bundle);
+ }
LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src));
LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
LLVMBasicBlockRef Then = DeclareBB(LLVMGetNormalDest(Src));
LLVMBasicBlockRef Unwind = DeclareBB(LLVMGetUnwindDest(Src));
- Dst = LLVMBuildInvoke2(Builder, FnTy, Fn, Args.data(), ArgCount,
- Then, Unwind, Name);
+ Dst = LLVMBuildInvokeWithOperandBundles(
+ Builder, FnTy, Fn, Args.data(), ArgCount, Then, Unwind,
+ Bundles.data(), Bundles.size(), Name);
CloneAttrs(Src, Dst);
+ for (auto Bundle : Bundles)
+ LLVMDisposeOperandBundle(Bundle);
break;
}
case LLVMUnreachable:
@@ -764,14 +774,25 @@ struct FunCloner {
}
case LLVMCall: {
SmallVector<LLVMValueRef, 8> Args;
- int ArgCount = LLVMGetNumArgOperands(Src);
- for (int i = 0; i < ArgCount; i++)
+ SmallVector<LLVMOperandBundleRef, 8> Bundles;
+ unsigned ArgCount = LLVMGetNumArgOperands(Src);
+ for (unsigned i = 0; i < ArgCount; ++i)
Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
+ unsigned BundleCount = LLVMGetNumOperandBundles(Src);
+ for (unsigned i = 0; i < BundleCount; ++i) {
+ auto Bundle = LLVMGetOperandBundleAtIndex(Src, i);
+ Bundles.push_back(CloneOB(Bundle));
+ LLVMDisposeOperandBundle(Bundle);
+ }
LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src));
LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
- Dst = LLVMBuildCall2(Builder, FnTy, Fn, Args.data(), ArgCount, Name);
+ Dst = LLVMBuildCallWithOperandBundles(Builder, FnTy, Fn, Args.data(),
+ ArgCount, Bundles.data(),
+ Bundles.size(), Name);
LLVMSetTailCallKind(Dst, LLVMGetTailCallKind(Src));
CloneAttrs(Src, Dst);
+ for (auto Bundle : Bundles)
+ LLVMDisposeOperandBundle(Bundle);
break;
}
case LLVMResume: {
@@ -935,6 +956,17 @@ struct FunCloner {
return VMap[Src] = Dst;
}
+ LLVMOperandBundleRef CloneOB(LLVMOperandBundleRef Src) {
+ size_t TagLen;
+ const char *Tag = LLVMGetOperandBundleTag(Src, &TagLen);
+
+ SmallVector<LLVMValueRef, 8> Args;
+ for (unsigned i = 0, n = LLVMGetNumOperandBundleArgs(Src); i != n; ++i)
+ Args.push_back(CloneValue(LLVMGetOperandBundleArgAtIndex(Src, i)));
+
+ return LLVMCreateOperandBundle(Tag, TagLen, Args.data(), Args.size());
+ }
+
LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
// Check if this is something we already computed.
{
More information about the llvm-commits
mailing list