[Mlir-commits] [mlir] [MLIR][LLVM] add metadata attrs and `llvm.named_metadata` op (PR #186703)
Maksim Levental
llvmlistbot at llvm.org
Sun Mar 15 15:15:21 PDT 2026
https://github.com/makslevental updated https://github.com/llvm/llvm-project/pull/186703
>From df6e557170ccd863222e219a71de6a74dd4236ab Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Sun, 15 Mar 2026 13:25:38 -0700
Subject: [PATCH 1/4] [MLIR][LLVM] add metadata attrs and llvm.named_metadata
---
mlir/include/mlir-c/Dialect/LLVM.h | 65 ++++++++
.../mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 70 +++++++++
mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 40 +++++
mlir/lib/Bindings/Python/DialectLLVM.cpp | 123 ++++++++++++++-
mlir/lib/CAPI/Dialect/LLVM.cpp | 88 ++++++++++-
.../LLVMIR/LLVMToLLVMIRTranslation.cpp | 143 ++++++++++++------
.../Target/LLVMIR/llvmir-named-metadata.mlir | 107 +++++++++++++
7 files changed, 585 insertions(+), 51 deletions(-)
create mode 100644 mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir
diff --git a/mlir/include/mlir-c/Dialect/LLVM.h b/mlir/include/mlir-c/Dialect/LLVM.h
index 93602a286c9c4..2d603ffc09edb 100644
--- a/mlir/include/mlir-c/Dialect/LLVM.h
+++ b/mlir/include/mlir-c/Dialect/LLVM.h
@@ -456,6 +456,71 @@ MLIR_CAPI_EXPORTED MlirStringRef mlirLLVMDIImportedEntityAttrGetName(void);
MLIR_CAPI_EXPORTED MlirAttribute
mlirLLVMDIModuleAttrGetScope(MlirAttribute diModule);
+//===----------------------------------------------------------------------===//
+// Metadata Attributes
+//===----------------------------------------------------------------------===//
+
+/// Creates an LLVM MDStringAttr.
+MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMMDStringAttrGet(MlirContext ctx,
+ MlirStringRef value);
+
+/// Returns `true` if the attribute is an LLVM MDStringAttr.
+MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDStringAttr(MlirAttribute attr);
+
+/// Returns the TypeID of MDStringAttr.
+MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDStringAttrGetTypeID(void);
+
+/// Returns the string value of an LLVM MDStringAttr.
+MLIR_CAPI_EXPORTED MlirStringRef
+mlirLLVMMDStringAttrGetValue(MlirAttribute attr);
+
+/// Creates an LLVM MDConstantAttr wrapping an integer attribute.
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirLLVMMDConstantAttrGet(MlirContext ctx, MlirAttribute integerAttr);
+
+/// Returns `true` if the attribute is an LLVM MDConstantAttr.
+MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDConstantAttr(MlirAttribute attr);
+
+/// Returns the TypeID of MDConstantAttr.
+MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDConstantAttrGetTypeID(void);
+
+/// Returns the integer attribute value of an LLVM MDConstantAttr.
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirLLVMMDConstantAttrGetValue(MlirAttribute attr);
+
+/// Creates an LLVM MDFuncAttr referencing a function symbol.
+MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMMDFuncAttrGet(MlirContext ctx,
+ MlirAttribute name);
+
+/// Returns `true` if the attribute is an LLVM MDFuncAttr.
+MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDFuncAttr(MlirAttribute attr);
+
+/// Returns the TypeID of MDFuncAttr.
+MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDFuncAttrGetTypeID(void);
+
+/// Returns the symbol name of an LLVM MDFuncAttr.
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirLLVMMDFuncAttrGetName(MlirAttribute attr);
+
+/// Creates an LLVM MDNodeAttr (metadata tuple).
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirLLVMMDNodeAttrGet(MlirContext ctx, intptr_t nOperands,
+ MlirAttribute const *operands);
+
+/// Returns `true` if the attribute is an LLVM MDNodeAttr.
+MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDNodeAttr(MlirAttribute attr);
+
+/// Returns the TypeID of MDNodeAttr.
+MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDNodeAttrGetTypeID(void);
+
+/// Returns the number of operands in an LLVM MDNodeAttr.
+MLIR_CAPI_EXPORTED intptr_t
+mlirLLVMMDNodeAttrGetNumOperands(MlirAttribute attr);
+
+/// Returns the operand at the given index of an LLVM MDNodeAttr.
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirLLVMMDNodeAttrGetOperand(MlirAttribute attr, intptr_t index);
+
#ifdef __cplusplus
}
#endif
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 36acf244865eb..b315d563df031 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1686,4 +1686,74 @@ def UWTableKindAttr : LLVM_Attr<"UWTableKind", "uwtableKind"> {
let assemblyFormat = "`<` $uwtableKind `>`";
}
+//===----------------------------------------------------------------------===//
+// Metadata Attributes
+//===----------------------------------------------------------------------===//
+//
+// These attributes model LLVM IR metadata nodes (llvm::Metadata and its
+// subclasses). They can be nested to form arbitrary metadata trees and are
+// translated to their LLVM IR counterparts during MLIR-to-LLVM-IR conversion.
+
+def LLVM_MDStringAttr : LLVM_Attr<"MDString", "md_string"> {
+ let summary = "LLVM metadata string";
+ let description = [{
+ Wraps a string as an LLVM metadata node, corresponding to
+ `llvm::MDString` in LLVM IR.
+
+ Example:
+ ```mlir
+ #llvm.md_string<"foo.buffer">
+ ```
+ }];
+ let parameters = (ins "StringAttr":$value);
+ let assemblyFormat = "`<` $value `>`";
+}
+
+def LLVM_MDConstantAttr : LLVM_Attr<"MDConstant", "md_const"> {
+ let summary = "LLVM constant-as-metadata";
+ let description = [{
+ Wraps an integer constant as an LLVM metadata node, corresponding to
+ `llvm::ConstantAsMetadata` wrapping a `llvm::ConstantInt` in LLVM IR.
+
+ Example:
+ ```mlir
+ #llvm.md_const<42 : i32>
+ ```
+ }];
+ let parameters = (ins "IntegerAttr":$value);
+ let assemblyFormat = "`<` $value `>`";
+}
+
+def LLVM_MDFuncAttr : LLVM_Attr<"MDFunc", "md_func"> {
+ let summary = "LLVM function-as-metadata";
+ let description = [{
+ References a function (or global) symbol as LLVM metadata, corresponding
+ to `llvm::ValueAsMetadata::get(function)` in LLVM IR.
+
+ Example:
+ ```mlir
+ #llvm.md_func<@my_kernel>
+ ```
+ }];
+ let parameters = (ins "FlatSymbolRefAttr":$name);
+ let assemblyFormat = "`<` $name `>`";
+}
+
+def LLVM_MDNodeAttr : LLVM_Attr<"MDNode", "md_node"> {
+ let summary = "LLVM metadata tuple node";
+ let description = [{
+ Represents an LLVM metadata tuple node (`llvm::MDTuple`). The operands
+ can be any combination of metadata attributes: `#llvm.md_string`,
+ `#llvm.md_const`, `#llvm.md_func`, or nested `#llvm.md_node`.
+
+ Example:
+ ```mlir
+ #llvm.md_node<[#llvm.md_const<0 : i32>, #llvm.md_string<"foo.buffer">]>
+ #llvm.md_node<[]>
+ ```
+ }];
+ let parameters = (ins "ArrayAttr":$operands);
+ let assemblyFormat = "`<` $operands `>`";
+}
+
#endif // LLVMIR_ATTRDEFS
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index e781d4c876315..097c41ee4668f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2576,4 +2576,44 @@ def LLVM_ModuleFlagsOp
let hasVerifier = 1;
}
+//===--------------------------------------------------------------------===//
+// NamedMetadataOp
+//===--------------------------------------------------------------------===//
+
+def LLVM_NamedMetadataOp
+ : LLVM_Op<"named_metadata"> {
+ let summary = "Module-level named metadata";
+ let description = [{
+ Represents an LLVM named metadata node (`llvm::NamedMDNode`). Named
+ metadata nodes are module-level metadata that associate a name string
+ with a list of metadata nodes. Each operand must be an `#llvm.md_node`.
+
+ Example:
+ ```mlir
+ llvm.named_metadata "foo.version" [
+ #llvm.md_node<[#llvm.md_const<2 : i32>, #llvm.md_const<9 : i32>,
+ #llvm.md_const<0 : i32>]>
+ ]
+ llvm.named_metadata "foo.kernel" [
+ #llvm.md_node<[
+ #llvm.md_func<@my_kernel>,
+ #llvm.md_node<[]>,
+ #llvm.md_node<[
+ #llvm.md_node<[#llvm.md_const<0 : i32>,
+ #llvm.md_string<"foo.buffer">]>
+ ]>
+ ]>
+ ]
+ ```
+ }];
+ let arguments = (ins StrAttr:$metadata_name, ArrayAttr:$nodes);
+ let assemblyFormat = [{
+ $metadata_name $nodes attr-dict
+ }];
+
+ let llvmBuilder = [{
+ convertNamedMetadataOp($metadata_name, $nodes, builder, moduleTranslation);
+ }];
+}
+
#endif // LLVMIR_OPS
diff --git a/mlir/lib/Bindings/Python/DialectLLVM.cpp b/mlir/lib/Bindings/Python/DialectLLVM.cpp
index 5c79f515c49eb..6db6748a40cb0 100644
--- a/mlir/lib/Bindings/Python/DialectLLVM.cpp
+++ b/mlir/lib/Bindings/Python/DialectLLVM.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include <string>
+#include <vector>
#include "mlir-c/Dialect/LLVM.h"
#include "mlir-c/IR.h"
@@ -25,7 +26,8 @@ using namespace mlir::python::nanobind_adaptors;
namespace mlir {
namespace python {
-namespace MLIR_BINDINGS_PYTHON_DOMAIN {
+namespace
+MLIR_BINDINGS_PYTHON_DOMAIN {
namespace llvm {
//===--------------------------------------------------------------------===//
// StructType
@@ -222,10 +224,129 @@ struct PointerType : PyConcreteType<PointerType> {
}
};
+//===--------------------------------------------------------------------===//
+// Metadata Attributes
+//===--------------------------------------------------------------------===//
+
+struct MDStringAttr : PyConcreteAttribute<MDStringAttr> {
+ static constexpr IsAFunctionTy isaFunction = mlirLLVMAttrIsAMDStringAttr;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLLVMMDStringAttrGetTypeID;
+ static constexpr const char *pyClassName = "MDStringAttr";
+ using Base::Base;
+
+ static void bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](const std::string &value, DefaultingPyMlirContext context) {
+ return MDStringAttr(context->getRef(),
+ mlirLLVMMDStringAttrGet(
+ context.get()->get(),
+ mlirStringRefCreate(value.data(),
+ value.size())));
+ },
+ "value"_a, nb::kw_only(), "context"_a = nb::none());
+ c.def_prop_ro("value", [](const MDStringAttr &self) {
+ MlirStringRef ref =
+ mlirLLVMMDStringAttrGetValue(self);
+ return nb::str(ref.data, ref.length);
+ });
+ }
+};
+
+struct MDConstantAttr : PyConcreteAttribute<MDConstantAttr> {
+ static constexpr IsAFunctionTy isaFunction = mlirLLVMAttrIsAMDConstantAttr;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLLVMMDConstantAttrGetTypeID;
+ static constexpr const char *pyClassName = "MDConstantAttr";
+ using Base::Base;
+
+ static void bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](PyAttribute &integerAttr, DefaultingPyMlirContext context) {
+ return MDConstantAttr(
+ context->getRef(),
+ mlirLLVMMDConstantAttrGet(context.get()->get(), integerAttr));
+ },
+ "value"_a, nb::kw_only(), "context"_a = nb::none());
+ c.def_prop_ro("value", [](const MDConstantAttr &self) {
+ return mlirLLVMMDConstantAttrGetValue(self);
+ });
+ }
+};
+
+struct MDFuncAttr : PyConcreteAttribute<MDFuncAttr> {
+ static constexpr IsAFunctionTy isaFunction = mlirLLVMAttrIsAMDFuncAttr;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLLVMMDFuncAttrGetTypeID;
+ static constexpr const char *pyClassName = "MDFuncAttr";
+ using Base::Base;
+
+ static void bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](const std::string &name, DefaultingPyMlirContext context) {
+ MlirAttribute symRef = mlirFlatSymbolRefAttrGet(
+ context.get()->get(),
+ mlirStringRefCreate(name.data(), name.size()));
+ return MDFuncAttr(context->getRef(),
+ mlirLLVMMDFuncAttrGet(context.get()->get(),
+ symRef));
+ },
+ "name"_a, nb::kw_only(), "context"_a = nb::none());
+ c.def_prop_ro("name", [](const MDFuncAttr &self) {
+ MlirAttribute symRef = mlirLLVMMDFuncAttrGetName(self);
+ MlirStringRef ref = mlirFlatSymbolRefAttrGetValue(symRef);
+ return nb::str(ref.data, ref.length);
+ });
+ }
+};
+
+struct MDNodeAttr : PyConcreteAttribute<MDNodeAttr> {
+ static constexpr IsAFunctionTy isaFunction = mlirLLVMAttrIsAMDNodeAttr;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLLVMMDNodeAttrGetTypeID;
+ static constexpr const char *pyClassName = "MDNodeAttr";
+ using Base::Base;
+
+ static void bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](const std::vector<PyAttribute> &operands,
+ DefaultingPyMlirContext context) {
+ std::vector<MlirAttribute> operands_(operands.size());
+ std::copy(operands.begin(), operands.end(), operands_.begin());
+ return MDNodeAttr(
+ context->getRef(),
+ mlirLLVMMDNodeAttrGet(context.get()->get(), operands_.size(),
+ operands_.data()));
+ },
+ "operands"_a, nb::kw_only(), "context"_a = nb::none());
+ c.def_prop_ro("num_operands", [](const MDNodeAttr &self) {
+ return mlirLLVMMDNodeAttrGetNumOperands(self);
+ });
+ c.def("__getitem__",
+ [](const MDNodeAttr &self, intptr_t index) {
+ intptr_t n = mlirLLVMMDNodeAttrGetNumOperands(self);
+ if (index < 0 || index >= n)
+ throw nb::index_error("MDNodeAttr operand index out of range");
+ return mlirLLVMMDNodeAttrGetOperand(self, index);
+ });
+ c.def("__len__", [](const MDNodeAttr &self) {
+ return mlirLLVMMDNodeAttrGetNumOperands(self);
+ });
+ }
+};
+
static void populateDialectLLVMSubmodule(nanobind::module_ &m) {
StructType::bind(m);
ArrayType::bind(m);
PointerType::bind(m);
+ MDStringAttr::bind(m);
+ MDConstantAttr::bind(m);
+ MDFuncAttr::bind(m);
+ MDNodeAttr::bind(m);
m.def(
"translate_module_to_llvmir",
diff --git a/mlir/lib/CAPI/Dialect/LLVM.cpp b/mlir/lib/CAPI/Dialect/LLVM.cpp
index eb30f169e4289..c9b2e999c645e 100644
--- a/mlir/lib/CAPI/Dialect/LLVM.cpp
+++ b/mlir/lib/CAPI/Dialect/LLVM.cpp
@@ -92,7 +92,7 @@ intptr_t mlirLLVMFunctionTypeGetNumInputs(MlirType type) {
MlirType mlirLLVMFunctionTypeGetInput(MlirType type, intptr_t pos) {
assert(pos >= 0 && "pos in array must be positive");
return wrap(llvm::cast<LLVM::LLVMFunctionType>(unwrap(type))
- .getParamType(static_cast<unsigned>(pos)));
+ .getParamType(static_cast<unsigned>(pos)));
}
MlirType mlirLLVMFunctionTypeGetReturnType(MlirType type) {
@@ -179,7 +179,7 @@ MlirLogicalResult mlirLLVMStructTypeSetBody(MlirType structType,
SmallVector<Type> fields;
return wrap(
cast<LLVM::LLVMStructType>(unwrap(structType))
- .setBody(unwrapList(nFieldTypes, fieldTypes, fields), isPacked));
+ .setBody(unwrapList(nFieldTypes, fieldTypes, fields), isPacked));
}
MlirAttribute mlirLLVMDIExpressionElemAttrGet(MlirContext ctx,
@@ -523,3 +523,87 @@ MlirAttribute mlirLLVMDIAnnotationAttrGet(MlirContext ctx, MlirAttribute name,
MlirStringRef mlirLLVMDIAnnotationAttrGetName(void) {
return wrap(DIAnnotationAttr::name);
}
+
+//===----------------------------------------------------------------------===//
+// Metadata Attributes
+//===----------------------------------------------------------------------===//
+
+MlirAttribute mlirLLVMMDStringAttrGet(MlirContext ctx, MlirStringRef value) {
+ return wrap(
+ MDStringAttr::get(unwrap(ctx),
+ StringAttr::get(unwrap(ctx), unwrap(value))));
+}
+
+bool mlirLLVMAttrIsAMDStringAttr(MlirAttribute attr) {
+ return isa<MDStringAttr>(unwrap(attr));
+}
+
+MlirTypeID mlirLLVMMDStringAttrGetTypeID(void) {
+ return wrap(MDStringAttr::getTypeID());
+}
+
+MlirStringRef mlirLLVMMDStringAttrGetValue(MlirAttribute attr) {
+ return wrap(cast<MDStringAttr>(unwrap(attr)).getValue().getValue());
+}
+
+MlirAttribute mlirLLVMMDConstantAttrGet(MlirContext ctx,
+ MlirAttribute integerAttr) {
+ return wrap(MDConstantAttr::get(unwrap(ctx),
+ cast<IntegerAttr>(unwrap(integerAttr))));
+}
+
+bool mlirLLVMAttrIsAMDConstantAttr(MlirAttribute attr) {
+ return isa<MDConstantAttr>(unwrap(attr));
+}
+
+MlirTypeID mlirLLVMMDConstantAttrGetTypeID(void) {
+ return wrap(MDConstantAttr::getTypeID());
+}
+
+MlirAttribute mlirLLVMMDConstantAttrGetValue(MlirAttribute attr) {
+ return wrap((Attribute)cast<MDConstantAttr>(unwrap(attr)).getValue());
+}
+
+MlirAttribute mlirLLVMMDFuncAttrGet(MlirContext ctx, MlirAttribute name) {
+ return wrap(
+ MDFuncAttr::get(unwrap(ctx), cast<FlatSymbolRefAttr>(unwrap(name))));
+}
+
+bool mlirLLVMAttrIsAMDFuncAttr(MlirAttribute attr) {
+ return isa<MDFuncAttr>(unwrap(attr));
+}
+
+MlirTypeID mlirLLVMMDFuncAttrGetTypeID(void) {
+ return wrap(MDFuncAttr::getTypeID());
+}
+
+MlirAttribute mlirLLVMMDFuncAttrGetName(MlirAttribute attr) {
+ return wrap((Attribute)cast<MDFuncAttr>(unwrap(attr)).getName());
+}
+
+MlirAttribute mlirLLVMMDNodeAttrGet(MlirContext ctx, intptr_t nOperands,
+ MlirAttribute const *operands) {
+ SmallVector<Attribute> attrStorage;
+ attrStorage.reserve(nOperands);
+ return wrap(MDNodeAttr::get(
+ unwrap(ctx),
+ ArrayAttr::get(unwrap(ctx),
+ unwrapList(nOperands, operands, attrStorage))));
+}
+
+bool mlirLLVMAttrIsAMDNodeAttr(MlirAttribute attr) {
+ return isa<MDNodeAttr>(unwrap(attr));
+}
+
+MlirTypeID mlirLLVMMDNodeAttrGetTypeID(void) {
+ return wrap(MDNodeAttr::getTypeID());
+}
+
+intptr_t mlirLLVMMDNodeAttrGetNumOperands(MlirAttribute attr) {
+ return cast<MDNodeAttr>(unwrap(attr)).getOperands().size();
+}
+
+MlirAttribute mlirLLVMMDNodeAttrGetOperand(MlirAttribute attr,
+ intptr_t index) {
+ return wrap(cast<MDNodeAttr>(unwrap(attr)).getOperands()[index]);
+}
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 21f7954fd338a..9e758e9fdb0e4 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "mlir/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.h"
+#include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/IR/Operation.h"
#include "mlir/Interfaces/CallInterfaces.h"
@@ -165,8 +166,8 @@ convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
// Check the result type of the call.
const llvm::Type *intrinType =
op.getNumResults() == 0
- ? llvm::Type::getVoidTy(module->getContext())
- : moduleTranslation.convertType(op.getResultTypes().front());
+ ? llvm::Type::getVoidTy(module->getContext())
+ : moduleTranslation.convertType(op.getResultTypes().front());
if (intrinType != fn->getReturnType()) {
return mlir::emitError(op.getLoc(), "intrinsic call returns ")
<< diagStr(intrinType) << " but " << op.getIntrinAttr()
@@ -215,6 +216,52 @@ convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
return success();
}
+/// Recursively converts an MLIR metadata attribute to an LLVM metadata node.
+static llvm::Metadata *
+convertMetadataAttr(Attribute attr, llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ return llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr)
+ .Case<LLVM::MDStringAttr>([&](auto a) -> llvm::Metadata * {
+ return llvm::MDString::get(builder.getContext(),
+ a.getValue().getValue());
+ })
+ .Case<LLVM::MDConstantAttr>([&](auto a) -> llvm::Metadata * {
+ IntegerAttr intAttr = a.getValue();
+ return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getIntNTy(builder.getContext(),
+ intAttr.getType().getIntOrFloatBitWidth()),
+ intAttr.getValue()));
+ })
+ .Case<LLVM::MDFuncAttr>([&](auto a) -> llvm::Metadata * {
+ if (llvm::Function *fn =
+ moduleTranslation.lookupFunction(a.getName().getValue()))
+ return llvm::ValueAsMetadata::get(fn);
+ return nullptr;
+ })
+ .Case<LLVM::MDNodeAttr>([&](auto a) -> llvm::Metadata * {
+ SmallVector<llvm::Metadata *> operands;
+ for (Attribute op : a.getOperands())
+ operands.push_back(
+ convertMetadataAttr(op, builder, moduleTranslation));
+ return llvm::MDNode::get(builder.getContext(), operands);
+ })
+ .Default([](auto) -> llvm::Metadata * { return nullptr; });
+}
+
+static void convertNamedMetadataOp(StringRef metadataName, ArrayAttr nodes,
+ llvm::IRBuilderBase &builder,
+ LLVM::ModuleTranslation &moduleTranslation) {
+ llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
+ llvm::NamedMDNode *namedMD =
+ llvmModule->getOrInsertNamedMetadata(metadataName);
+ for (Attribute nodeAttr : nodes) {
+ llvm::Metadata *md =
+ convertMetadataAttr(nodeAttr, builder, moduleTranslation);
+ if (auto *mdNode = llvm::dyn_cast_or_null<llvm::MDNode>(md))
+ namedMD->addOperand(mdNode);
+ }
+}
+
static void convertLinkerOptionsOp(ArrayAttr options,
llvm::IRBuilderBase &builder,
LLVM::ModuleTranslation &moduleTranslation) {
@@ -247,7 +294,7 @@ convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr,
if (!sym)
return nullptr;
if (llvm::Function *fn =
- moduleTranslation.lookupFunction(sym.getValue()))
+ moduleTranslation.lookupFunction(sym.getValue()))
return llvm::ValueAsMetadata::get(fn);
return nullptr;
};
@@ -274,7 +321,7 @@ static llvm::Metadata *convertModuleFlagProfileSummaryAttr(
auto getIntTuple = [&](StringRef key, uint64_t val) -> llvm::MDTuple * {
SmallVector<llvm::Metadata *> tupleNodes{
mdb.createString(key), mdb.createConstant(llvm::ConstantInt::get(
- llvm::Type::getInt64Ty(context), val))};
+ llvm::Type::getInt64Ty(context), val))};
return llvm::MDTuple::get(context, tupleNodes);
};
@@ -333,26 +380,26 @@ static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
llvm::Metadata *valueMetadata =
llvm::TypeSwitch<Attribute, llvm::Metadata *>(flagAttr.getValue())
- .Case([&](StringAttr strAttr) {
- return llvm::MDString::get(builder.getContext(),
- strAttr.getValue());
- })
- .Case([&](IntegerAttr intAttr) {
- return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(builder.getContext()),
- intAttr.getInt()));
- })
- .Case([&](ArrayAttr arrayAttr) {
- return convertModuleFlagValue(flagAttr.getKey().getValue(),
- arrayAttr, builder,
- moduleTranslation);
- })
- .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
- return convertModuleFlagProfileSummaryAttr(
- flagAttr.getKey().getValue(), summaryAttr, builder,
- moduleTranslation);
- })
- .Default([](auto) { return nullptr; });
+ .Case([&](StringAttr strAttr) {
+ return llvm::MDString::get(builder.getContext(),
+ strAttr.getValue());
+ })
+ .Case([&](IntegerAttr intAttr) {
+ return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(builder.getContext()),
+ intAttr.getInt()));
+ })
+ .Case([&](ArrayAttr arrayAttr) {
+ return convertModuleFlagValue(flagAttr.getKey().getValue(),
+ arrayAttr, builder,
+ moduleTranslation);
+ })
+ .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
+ return convertModuleFlagProfileSummaryAttr(
+ flagAttr.getKey().getValue(), summaryAttr, builder,
+ moduleTranslation);
+ })
+ .Default([](auto) { return nullptr; });
assert(valueMetadata && "expected valid metadata");
llvmModule->addModuleFlag(
@@ -365,9 +412,9 @@ static llvm::DILocalScope *
getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc,
LLVM::ModuleTranslation &moduleTranslation) {
if (auto scopeLoc =
- loc->findInstanceOf<FusedLocWith<LLVM::DILocalScopeAttr>>())
+ loc->findInstanceOf<FusedLocWith<LLVM::DILocalScopeAttr>>())
if (auto *localScope = llvm::dyn_cast<llvm::DILocalScope>(
- moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
+ moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
return localScope;
return builder.GetInsertBlock()->getParent()->getSubprogram();
}
@@ -396,7 +443,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
llvm::CallInst *call;
if (auto attr = callOp.getCalleeAttr()) {
if (llvm::Function *function =
- moduleTranslation.lookupFunction(attr.getValue())) {
+ moduleTranslation.lookupFunction(attr.getValue())) {
call = builder.CreateCall(function, operandsRef, opBundles);
} else {
Operation *moduleOp = parentLLVMModule(&opInst);
@@ -480,8 +527,8 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
ModuleTranslation::convertDefaultFuncAttr);
if (llvm::Attribute attr =
- moduleTranslation.convertAllocsizeAttr(callOp.getAllocsizeAttr());
- attr.isValid())
+ moduleTranslation.convertAllocsizeAttr(callOp.getAllocsizeAttr());
+ attr.isValid())
call->addFnAttr(attr);
if (failed(moduleTranslation.convertArgAndResultAttrs(callOp, call)))
@@ -513,7 +560,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// that LLVM IR dialect CallOp has either 0 or 1 result.
if (opInst.getNumResults() != 0)
moduleTranslation.mapValue(opInst.getResult(0), call);
- // Check that LLVM call returns void for 0-result functions.
+ // Check that LLVM call returns void for 0-result functions.
else if (!call->getType()->isVoidTy())
return failure();
moduleTranslation.mapCall(callOp, call);
@@ -536,19 +583,19 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
llvm::InlineAsm *inlineAsmInst =
inlineAsmOp.getAsmDialect()
- ? llvm::InlineAsm::get(
- static_cast<llvm::FunctionType *>(
- moduleTranslation.convertType(ft)),
- inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
- inlineAsmOp.getHasSideEffects(),
- inlineAsmOp.getIsAlignStack(),
- convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
- : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
- moduleTranslation.convertType(ft)),
- inlineAsmOp.getAsmString(),
- inlineAsmOp.getConstraints(),
- inlineAsmOp.getHasSideEffects(),
- inlineAsmOp.getIsAlignStack());
+ ? llvm::InlineAsm::get(
+ static_cast<llvm::FunctionType *>(
+ moduleTranslation.convertType(ft)),
+ inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
+ inlineAsmOp.getHasSideEffects(),
+ inlineAsmOp.getIsAlignStack(),
+ convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
+ : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
+ moduleTranslation.convertType(ft)),
+ inlineAsmOp.getAsmString(),
+ inlineAsmOp.getConstraints(),
+ inlineAsmOp.getHasSideEffects(),
+ inlineAsmOp.getIsAlignStack());
llvm::CallInst *inst = builder.CreateCall(
inlineAsmInst,
moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
@@ -696,7 +743,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// The verifier should not have allowed this.
assert((global || function || alias || ifunc) &&
- "referencing an undefined global, function, alias, or ifunc");
+ "referencing an undefined global, function, alias, or ifunc");
llvm::Value *llvmValue = nullptr;
if (global)
@@ -715,7 +762,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// Emit dso_local_equivalent. We need to look up the global value referenced
// by the operation and store it in the MLIR-to-LLVM value mapping.
if (auto dsoLocalEquivalentOp =
- dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
+ dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
LLVM::LLVMFuncOp function =
dsoLocalEquivalentOp.getFunction(moduleTranslation.symbolTable());
LLVM::AliasOp alias =
@@ -723,7 +770,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// The verifier should not have allowed this.
assert((function || alias) &&
- "referencing an undefined function, or alias");
+ "referencing an undefined function, or alias");
llvm::Value *llvmValue = nullptr;
if (alias)
@@ -762,8 +809,8 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
/*isConstant=*/true, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
/*Initializer=*/nullptr,
Twine("__mlir_block_address_")
- .concat(Twine(fnName))
- .concat(Twine((uint64_t)blockAddressOp.getOperation())));
+ .concat(Twine(fnName))
+ .concat(Twine((uint64_t)blockAddressOp.getOperation())));
moduleTranslation.mapUnresolvedBlockAddress(blockAddressOp, llvmValue);
}
diff --git a/mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir b/mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir
new file mode 100644
index 0000000000000..144285e9bfebc
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir
@@ -0,0 +1,107 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// Tests LLVM named metadata translation with deeply nested metadata trees.
+
+// CHECK: !foo.version = !{![[VERSION:[0-9]+]]}
+// CHECK: !foo.language_version = !{![[LANG:[0-9]+]]}
+// CHECK: !foo.kernel = !{![[KERNEL:[0-9]+]]}
+
+llvm.func @my_kernel() {
+ llvm.return
+}
+
+llvm.named_metadata "foo.version" [
+ #llvm.md_node<[#llvm.md_const<1 : i32>, #llvm.md_const<0 : i32>,
+ #llvm.md_const<0 : i32>]>
+]
+// CHECK-DAG: ![[VERSION]] = !{i32 1, i32 0, i32 0}
+
+llvm.named_metadata "foo.language_version" [
+ #llvm.md_node<[#llvm.md_string<"Bar">, #llvm.md_const<1 : i32>,
+ #llvm.md_const<2 : i32>, #llvm.md_const<3 : i32>]>
+]
+// CHECK-DAG: ![[LANG]] = !{!"Bar", i32 1, i32 2, i32 3}
+
+#buf0 = #llvm.md_node<[
+ #llvm.md_const<0 : i32>, #llvm.md_string<"foo.buffer">,
+ #llvm.md_string<"foo.idx">, #llvm.md_const<0 : i32>,
+ #llvm.md_const<1 : i32>, #llvm.md_string<"foo.read">,
+ #llvm.md_string<"foo.address_space">, #llvm.md_const<1 : i32>,
+ #llvm.md_string<"foo.size">, #llvm.md_const<4 : i32>,
+ #llvm.md_string<"foo.align_size">, #llvm.md_const<4 : i32>
+]>
+// CHECK-DAG: ![[A0:[0-9]+]] = !{i32 0, !"foo.buffer", !"foo.idx", i32 0, i32 1, !"foo.read", !"foo.address_space", i32 1, !"foo.size", i32 4, !"foo.align_size", i32 4}
+
+#buf1 = #llvm.md_node<[
+ #llvm.md_const<1 : i32>, #llvm.md_string<"foo.buffer">,
+ #llvm.md_string<"foo.idx">, #llvm.md_const<1 : i32>,
+ #llvm.md_const<1 : i32>, #llvm.md_string<"foo.read_write">,
+ #llvm.md_string<"foo.address_space">, #llvm.md_const<1 : i32>,
+ #llvm.md_string<"foo.size">, #llvm.md_const<4 : i32>,
+ #llvm.md_string<"foo.align_size">, #llvm.md_const<4 : i32>
+]>
+// CHECK-DAG: ![[A1:[0-9]+]] = !{i32 1, !"foo.buffer", !"foo.idx", i32 1, i32 1, !"foo.read_write", !"foo.address_space", i32 1, !"foo.size", i32 4, !"foo.align_size", i32 4}
+
+#buf2 = #llvm.md_node<[
+ #llvm.md_const<2 : i32>, #llvm.md_string<"foo.buffer">,
+ #llvm.md_string<"foo.idx">, #llvm.md_const<2 : i32>,
+ #llvm.md_const<1 : i32>, #llvm.md_string<"foo.read">,
+ #llvm.md_string<"foo.address_space">, #llvm.md_const<2 : i32>,
+ #llvm.md_string<"foo.size">, #llvm.md_const<4 : i32>,
+ #llvm.md_string<"foo.align_size">, #llvm.md_const<4 : i32>
+]>
+// CHECK-DAG: ![[A2:[0-9]+]] = !{i32 2, !"foo.buffer", !"foo.idx", i32 2, i32 1, !"foo.read", !"foo.address_space", i32 2, !"foo.size", i32 4, !"foo.align_size", i32 4}
+
+#pos3 = #llvm.md_node<[
+ #llvm.md_const<3 : i32>, #llvm.md_string<"foo.block_position_in_grid">,
+ #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
+ #llvm.md_string<"foo.arg_name">, #llvm.md_string<"block_position_in_grid">
+]>
+// CHECK-DAG: ![[A3:[0-9]+]] = !{i32 3, !"foo.block_position_in_grid", !"foo.name", !"vec3", !"foo.arg_name", !"block_position_in_grid"}
+
+#pos4 = #llvm.md_node<[
+ #llvm.md_const<4 : i32>, #llvm.md_string<"foo.blocks_per_grid">,
+ #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
+ #llvm.md_string<"foo.arg_name">, #llvm.md_string<"blocks_per_grid">
+]>
+// CHECK-DAG: ![[A4:[0-9]+]] = !{i32 4, !"foo.blocks_per_grid", !"foo.name", !"vec3", !"foo.arg_name", !"blocks_per_grid"}
+
+#pos5 = #llvm.md_node<[
+ #llvm.md_const<5 : i32>, #llvm.md_string<"foo.thread_position_in_block">,
+ #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
+ #llvm.md_string<"foo.arg_name">, #llvm.md_string<"thread_position_in_block">
+]>
+// CHECK-DAG: ![[A5:[0-9]+]] = !{i32 5, !"foo.thread_position_in_block", !"foo.name", !"vec3", !"foo.arg_name", !"thread_position_in_block"}
+
+#pos6 = #llvm.md_node<[
+ #llvm.md_const<6 : i32>, #llvm.md_string<"foo.threads_per_block">,
+ #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
+ #llvm.md_string<"foo.arg_name">, #llvm.md_string<"threads_per_block">
+]>
+// CHECK-DAG: ![[A6:[0-9]+]] = !{i32 6, !"foo.threads_per_block", !"foo.name", !"vec3", !"foo.arg_name", !"threads_per_block"}
+
+#pos7 = #llvm.md_node<[
+ #llvm.md_const<7 : i32>, #llvm.md_string<"foo.thread_idx_in_warp">,
+ #llvm.md_string<"foo.name">, #llvm.md_string<"vec1">,
+ #llvm.md_string<"foo.arg_name">, #llvm.md_string<"thread_idx_in_warp">
+]>
+// CHECK-DAG: ![[A7:[0-9]+]] = !{i32 7, !"foo.thread_idx_in_warp", !"foo.name", !"vec1", !"foo.arg_name", !"thread_idx_in_warp"}
+
+#pos8 = #llvm.md_node<[
+ #llvm.md_const<8 : i32>, #llvm.md_string<"foo.warp_idx_in_block">,
+ #llvm.md_string<"foo.name">, #llvm.md_string<"vec1">,
+ #llvm.md_string<"foo.arg_name">, #llvm.md_string<"warp_idx_in_block">
+]>
+// CHECK-DAG: ![[A8:[0-9]+]] = !{i32 8, !"foo.warp_idx_in_block", !"foo.name", !"vec1", !"foo.arg_name", !"warp_idx_in_block"}
+
+llvm.named_metadata "foo.kernel" [
+ #llvm.md_node<[
+ #llvm.md_func<@my_kernel>,
+ #llvm.md_node<[]>,
+ #llvm.md_node<[#buf0, #buf1, #buf2,
+ #pos3, #pos4, #pos5, #pos6, #pos7, #pos8]>
+ ]>
+]
+// CHECK-DAG: ![[KERNEL]] = !{ptr @my_kernel, ![[EMPTY:[0-9]+]], ![[ARGS:[0-9]+]]}
+// CHECK-DAG: ![[EMPTY]] = !{}
+// CHECK-DAG: ![[ARGS]] = !{![[A0]], ![[A1]], ![[A2]], ![[A3]], ![[A4]], ![[A5]], ![[A6]], ![[A7]], ![[A8]]}
>From b748bea46836d94cc05a1348631e701e7820e843 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Sun, 15 Mar 2026 13:58:08 -0700
Subject: [PATCH 2/4] add python bindings test
---
mlir/include/mlir-c/Dialect/LLVM.h | 23 +++-
mlir/lib/Bindings/Python/DialectLLVM.cpp | 48 +++++++++
mlir/lib/CAPI/Dialect/LLVM.cpp | 12 +++
mlir/test/python/dialects/llvm.py | 130 +++++++++++++++++++++++
4 files changed, 208 insertions(+), 5 deletions(-)
diff --git a/mlir/include/mlir-c/Dialect/LLVM.h b/mlir/include/mlir-c/Dialect/LLVM.h
index 2d603ffc09edb..a78cb84642b1c 100644
--- a/mlir/include/mlir-c/Dialect/LLVM.h
+++ b/mlir/include/mlir-c/Dialect/LLVM.h
@@ -63,6 +63,12 @@ mlirLLVMFunctionTypeGet(MlirType resultType, intptr_t nArgumentTypes,
MLIR_CAPI_EXPORTED MlirStringRef mlirLLVMFunctionTypeGetName(void);
+/// Returns `true` if the type is an LLVM dialect function type.
+MLIR_CAPI_EXPORTED bool mlirTypeIsALLVMFunctionType(MlirType type);
+
+/// Returns the TypeID of an LLVM function type.
+MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMFunctionTypeGetTypeID(void);
+
/// Returns the number of input types.
MLIR_CAPI_EXPORTED intptr_t mlirLLVMFunctionTypeGetNumInputs(MlirType type);
@@ -70,6 +76,9 @@ MLIR_CAPI_EXPORTED intptr_t mlirLLVMFunctionTypeGetNumInputs(MlirType type);
MLIR_CAPI_EXPORTED MlirType mlirLLVMFunctionTypeGetInput(MlirType type,
intptr_t pos);
+/// Returns `true` if the function type is variadic.
+MLIR_CAPI_EXPORTED bool mlirLLVMFunctionTypeIsVarArg(MlirType type);
+
/// Returns the return type of the function type.
MLIR_CAPI_EXPORTED MlirType mlirLLVMFunctionTypeGetReturnType(MlirType type);
@@ -190,6 +199,7 @@ enum MlirLLVMCConv {
MlirLLVMCConvAMDGPU_Gfx = 100,
MlirLLVMCConvM68k_INTR = 101,
};
+
typedef enum MlirLLVMCConv MlirLLVMCConv;
/// Creates a LLVM CConv attribute.
@@ -205,6 +215,7 @@ enum MlirLLVMComdat {
MlirLLVMComdatNoDeduplicate = 3,
MlirLLVMComdatSameSize = 4,
};
+
typedef enum MlirLLVMComdat MlirLLVMComdat;
/// Creates a LLVM Comdat attribute.
@@ -226,6 +237,7 @@ enum MlirLLVMLinkage {
MlirLLVMLinkageExternWeak = 9,
MlirLLVMLinkageCommon = 10,
};
+
typedef enum MlirLLVMLinkage MlirLLVMLinkage;
/// Creates a LLVM Linkage attribute.
@@ -274,6 +286,7 @@ enum MlirLLVMTypeEncoding {
MlirLLVMTypeEncodingLoUser = 0x80,
MlirLLVMTypeEncodingHiUser = 0xff,
};
+
typedef enum MlirLLVMTypeEncoding MlirLLVMTypeEncoding;
/// Creates a LLVM DIBasicType attribute.
@@ -337,6 +350,7 @@ enum MlirLLVMDIEmissionKind {
MlirLLVMDIEmissionKindLineTablesOnly = 2,
MlirLLVMDIEmissionKindDebugDirectivesOnly = 3,
};
+
typedef enum MlirLLVMDIEmissionKind MlirLLVMDIEmissionKind;
enum MlirLLVMDINameTableKind {
@@ -345,6 +359,7 @@ enum MlirLLVMDINameTableKind {
MlirLLVMDINameTableKindNone = 2,
MlirLLVMDINameTableKindApple = 3,
};
+
typedef enum MlirLLVMDINameTableKind MlirLLVMDINameTableKind;
/// Creates a LLVM DICompileUnit attribute.
@@ -499,13 +514,11 @@ MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDFuncAttr(MlirAttribute attr);
MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDFuncAttrGetTypeID(void);
/// Returns the symbol name of an LLVM MDFuncAttr.
-MLIR_CAPI_EXPORTED MlirAttribute
-mlirLLVMMDFuncAttrGetName(MlirAttribute attr);
+MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMMDFuncAttrGetName(MlirAttribute attr);
/// Creates an LLVM MDNodeAttr (metadata tuple).
-MLIR_CAPI_EXPORTED MlirAttribute
-mlirLLVMMDNodeAttrGet(MlirContext ctx, intptr_t nOperands,
- MlirAttribute const *operands);
+MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMMDNodeAttrGet(
+ MlirContext ctx, intptr_t nOperands, MlirAttribute const *operands);
/// Returns `true` if the attribute is an LLVM MDNodeAttr.
MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDNodeAttr(MlirAttribute attr);
diff --git a/mlir/lib/Bindings/Python/DialectLLVM.cpp b/mlir/lib/Bindings/Python/DialectLLVM.cpp
index 6db6748a40cb0..3f9442adf9de7 100644
--- a/mlir/lib/Bindings/Python/DialectLLVM.cpp
+++ b/mlir/lib/Bindings/Python/DialectLLVM.cpp
@@ -224,6 +224,53 @@ struct PointerType : PyConcreteType<PointerType> {
}
};
+//===--------------------------------------------------------------------===//
+// FunctionType
+//===--------------------------------------------------------------------===//
+
+struct FunctionType : PyConcreteType<FunctionType> {
+ static constexpr IsAFunctionTy isaFunction = mlirTypeIsALLVMFunctionType;
+ static constexpr GetTypeIDFunctionTy getTypeIdFunction =
+ mlirLLVMFunctionTypeGetTypeID;
+ static constexpr const char *pyClassName = "FunctionType";
+ static inline const MlirStringRef name = mlirLLVMFunctionTypeGetName();
+ using Base::Base;
+
+ static void bindDerived(ClassTy &c) {
+ c.def_static(
+ "get",
+ [](PyType &resultType, const std::vector<PyType> &argumentTypes,
+ bool isVarArg) {
+ std::vector<MlirType> argTypes(argumentTypes.size());
+ std::copy(argumentTypes.begin(), argumentTypes.end(),
+ argTypes.begin());
+ return FunctionType(
+ resultType.getContext(),
+ mlirLLVMFunctionTypeGet(resultType, argTypes.size(),
+ argTypes.data(), isVarArg));
+ },
+ "result_type"_a, "argument_types"_a, nb::kw_only(),
+ "is_var_arg"_a = false);
+ c.def_prop_ro("return_type", [](const FunctionType &type) {
+ return mlirLLVMFunctionTypeGetReturnType(type);
+ });
+ c.def_prop_ro("num_inputs", [](const FunctionType &type) {
+ return mlirLLVMFunctionTypeGetNumInputs(type);
+ });
+ c.def_prop_ro("inputs", [](const FunctionType &type) {
+ nb::list inputs;
+ for (intptr_t i = 0, e = mlirLLVMFunctionTypeGetNumInputs(type); i < e;
+ ++i) {
+ inputs.append(mlirLLVMFunctionTypeGetInput(type, i));
+ }
+ return inputs;
+ });
+ c.def_prop_ro("is_var_arg", [](const FunctionType &type) {
+ return mlirLLVMFunctionTypeIsVarArg(type);
+ });
+ }
+};
+
//===--------------------------------------------------------------------===//
// Metadata Attributes
//===--------------------------------------------------------------------===//
@@ -343,6 +390,7 @@ static void populateDialectLLVMSubmodule(nanobind::module_ &m) {
StructType::bind(m);
ArrayType::bind(m);
PointerType::bind(m);
+ FunctionType::bind(m);
MDStringAttr::bind(m);
MDConstantAttr::bind(m);
MDFuncAttr::bind(m);
diff --git a/mlir/lib/CAPI/Dialect/LLVM.cpp b/mlir/lib/CAPI/Dialect/LLVM.cpp
index c9b2e999c645e..8f46a60f5ad13 100644
--- a/mlir/lib/CAPI/Dialect/LLVM.cpp
+++ b/mlir/lib/CAPI/Dialect/LLVM.cpp
@@ -85,6 +85,14 @@ MlirStringRef mlirLLVMFunctionTypeGetName(void) {
return wrap(LLVMFunctionType::name);
}
+bool mlirTypeIsALLVMFunctionType(MlirType type) {
+ return isa<LLVM::LLVMFunctionType>(unwrap(type));
+}
+
+MlirTypeID mlirLLVMFunctionTypeGetTypeID(void) {
+ return wrap(LLVM::LLVMFunctionType::getTypeID());
+}
+
intptr_t mlirLLVMFunctionTypeGetNumInputs(MlirType type) {
return llvm::cast<LLVM::LLVMFunctionType>(unwrap(type)).getNumParams();
}
@@ -99,6 +107,10 @@ MlirType mlirLLVMFunctionTypeGetReturnType(MlirType type) {
return wrap(llvm::cast<LLVM::LLVMFunctionType>(unwrap(type)).getReturnType());
}
+bool mlirLLVMFunctionTypeIsVarArg(MlirType type) {
+ return llvm::cast<LLVM::LLVMFunctionType>(unwrap(type)).isVarArg();
+}
+
bool mlirTypeIsALLVMStructType(MlirType type) {
return isa<LLVM::LLVMStructType>(unwrap(type));
}
diff --git a/mlir/test/python/dialects/llvm.py b/mlir/test/python/dialects/llvm.py
index 7a2b8e1809c47..b1d64f5fc27fe 100644
--- a/mlir/test/python/dialects/llvm.py
+++ b/mlir/test/python/dialects/llvm.py
@@ -215,3 +215,133 @@ def testTranslateToLLVMIR():
# CHECK: ret i64 %3
# CHECK: }
print(llvm.translate_module_to_llvmir(module.operation))
+
+
+# CHECK-LABEL: testMetadataAttrs
+ at constructAndPrintInModule
+def testMetadataAttrs():
+ # MDStringAttr
+ md_str = llvm.MDStringAttr.get("foo.buffer")
+ # CHECK: #llvm.md_string<"foo.buffer">
+ print(md_str)
+ assert md_str.value == "foo.buffer"
+
+ # MDConstantAttr
+ i32 = IntegerType.get_signless(32)
+ md_const = llvm.MDConstantAttr.get(IntegerAttr.get(i32, 42))
+ # CHECK: #llvm.md_const<42 : i32>
+ print(md_const)
+
+ # MDFuncAttr
+ md_func = llvm.MDFuncAttr.get("my_kernel")
+ # CHECK: #llvm.md_func<@my_kernel>
+ print(md_func)
+ assert md_func.name == "my_kernel"
+
+ # MDNodeAttr - empty
+ md_empty = llvm.MDNodeAttr.get([])
+ # CHECK: #llvm.md_node<[]>
+ print(md_empty)
+ assert len(md_empty) == 0
+
+ # MDNodeAttr - with operands
+ md_node = llvm.MDNodeAttr.get([md_const, md_str])
+ # CHECK: #llvm.md_node<[#llvm.md_const<42 : i32>, #llvm.md_string<"foo.buffer">]>
+ print(md_node)
+ assert len(md_node) == 2
+
+ # MDNodeAttr - nested
+ md_nested = llvm.MDNodeAttr.get([md_node, md_empty])
+ # CHECK: #llvm.md_node<[#llvm.md_node<[#llvm.md_const<42 : i32>, #llvm.md_string<"foo.buffer">]>, #llvm.md_node<[]>]>
+ print(md_nested)
+ assert len(md_nested) == 2
+
+
+# CHECK-LABEL: testNamedMetadata
+ at constructAndPrintInModule
+def testNamedMetadata():
+ i32 = IntegerType.get_signless(32)
+
+ def md_const(val):
+ return llvm.MDConstantAttr.get(IntegerAttr.get(i32, val))
+
+ def md_str(s):
+ return llvm.MDStringAttr.get(s)
+
+ void = Type.parse("!llvm.void")
+ func_ty = llvm.FunctionType.get(void, [])
+
+ llvm.LLVMFuncOp("my_kernel", TypeAttr.get(func_ty))
+ # CHECK-LABEL: llvm.func @my_kernel()
+
+ llvm.NamedMetadataOp(
+ metadata_name="foo.version",
+ nodes=ArrayAttr.get(
+ [llvm.MDNodeAttr.get([md_const(1), md_const(0), md_const(0)])]
+ ),
+ )
+ # CHECK: llvm.named_metadata "foo.version" [#llvm.md_node<[#llvm.md_const<1 : i32>, #llvm.md_const<0 : i32>, #llvm.md_const<0 : i32>]>]
+
+ llvm.NamedMetadataOp(
+ metadata_name="foo.language_version",
+ nodes=ArrayAttr.get(
+ [
+ llvm.MDNodeAttr.get(
+ [md_str("Bar"), md_const(1), md_const(2), md_const(3)]
+ )
+ ]
+ ),
+ )
+ # CHECK: llvm.named_metadata "foo.language_version" [#llvm.md_node<[#llvm.md_string<"Bar">, #llvm.md_const<1 : i32>, #llvm.md_const<2 : i32>, #llvm.md_const<3 : i32>]>]
+
+ buf0 = llvm.MDNodeAttr.get(
+ [
+ md_const(0),
+ md_str("foo.buffer"),
+ md_str("foo.idx"),
+ md_const(0),
+ md_const(1),
+ md_str("foo.read"),
+ md_str("foo.address_space"),
+ md_const(1),
+ md_str("foo.size"),
+ md_const(4),
+ md_str("foo.align_size"),
+ md_const(4),
+ ]
+ )
+
+ llvm.NamedMetadataOp(
+ metadata_name="foo.kernel",
+ nodes=ArrayAttr.get(
+ [
+ llvm.MDNodeAttr.get(
+ [
+ llvm.MDFuncAttr.get("my_kernel"),
+ llvm.MDNodeAttr.get([]),
+ buf0,
+ ]
+ )
+ ]
+ ),
+ )
+ # CHECK: llvm.named_metadata "foo.kernel" [
+ # CHECK-SAME: #llvm.md_node<[
+ # CHECK-SAME: #llvm.md_func<@my_kernel>,
+ # CHECK-SAME: #llvm.md_node<[]>,
+ # CHECK-SAME: #llvm.md_node<[
+ # CHECK-SAME: #llvm.md_const<0 : i32>,
+ # CHECK-SAME: #llvm.md_string<"foo.buffer">,
+ # CHECK-SAME: #llvm.md_string<"foo.idx">,
+ # CHECK-SAME: #llvm.md_const<0 : i32>,
+ # CHECK-SAME: #llvm.md_const<1 : i32>,
+ # CHECK-SAME: #llvm.md_string<"foo.read">,
+ # CHECK-SAME: #llvm.md_string<"foo.address_space">,
+ # CHECK-SAME: #llvm.md_const<1 : i32>,
+ # CHECK-SAME: #llvm.md_string<"foo.size">,
+ # CHECK-SAME: #llvm.md_const<4 : i32>,
+ # CHECK-SAME: #llvm.md_string<"foo.align_size">,
+ # CHECK-SAME: #llvm.md_const<4 : i32>
+ # CHECK-SAME: ]>
+ # CHECK-SAME: ]>
+ # CHECK-SAME: ]
>From 5a729d8ebaf1417e260666f52a51b65dff78f4c5 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Sun, 15 Mar 2026 14:42:26 -0700
Subject: [PATCH 3/4] format and document integer limitation
---
mlir/include/mlir-c/Dialect/LLVM.h | 2 +-
.../mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 9 +-
mlir/lib/Bindings/Python/DialectLLVM.cpp | 47 +++---
mlir/lib/CAPI/Dialect/LLVM.cpp | 21 ++-
.../LLVMIR/LLVMToLLVMIRTranslation.cpp | 149 +++++++++---------
mlir/python/mlir/dialects/llvm.py | 17 +-
mlir/test/python/dialects/llvm.py | 53 ++++---
7 files changed, 160 insertions(+), 138 deletions(-)
diff --git a/mlir/include/mlir-c/Dialect/LLVM.h b/mlir/include/mlir-c/Dialect/LLVM.h
index a78cb84642b1c..b36a5f6f98a97 100644
--- a/mlir/include/mlir-c/Dialect/LLVM.h
+++ b/mlir/include/mlir-c/Dialect/LLVM.h
@@ -516,7 +516,7 @@ MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDFuncAttrGetTypeID(void);
/// Returns the symbol name of an LLVM MDFuncAttr.
MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMMDFuncAttrGetName(MlirAttribute attr);
-/// Creates an LLVM MDNodeAttr (metadata tuple).
+/// Creates an LLVM MDNodeAttr.
MLIR_CAPI_EXPORTED MlirAttribute mlirLLVMMDNodeAttrGet(
MlirContext ctx, intptr_t nOperands, MlirAttribute const *operands);
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index b315d563df031..f360c69c6436f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1713,14 +1713,15 @@ def LLVM_MDConstantAttr : LLVM_Attr<"MDConstant", "md_const"> {
let summary = "LLVM constant-as-metadata";
let description = [{
Wraps an integer constant as an LLVM metadata node, corresponding to
- `llvm::ConstantAsMetadata` wrapping a `llvm::ConstantInt` in LLVM IR.
+ `llvm::ConstantAsMetadata` wrapping a `llvm::Constant*` in LLVM IR.
+ Currently, only integers/IntegerAttrs supported.
Example:
```mlir
#llvm.md_const<42 : i32>
```
}];
- let parameters = (ins "IntegerAttr":$value);
+ let parameters = (ins "Attribute":$value);
let assemblyFormat = "`<` $value `>`";
}
@@ -1740,9 +1741,9 @@ def LLVM_MDFuncAttr : LLVM_Attr<"MDFunc", "md_func"> {
}
def LLVM_MDNodeAttr : LLVM_Attr<"MDNode", "md_node"> {
- let summary = "LLVM metadata tuple node";
+ let summary = "LLVM metadata node";
let description = [{
- Represents an LLVM metadata tuple node (`llvm::MDTuple`). The operands
+ Represents an LLVM metadata node. The operands
can be any combination of metadata attributes: `#llvm.md_string`,
`#llvm.md_const`, `#llvm.md_func`, or nested `#llvm.md_node`.
diff --git a/mlir/lib/Bindings/Python/DialectLLVM.cpp b/mlir/lib/Bindings/Python/DialectLLVM.cpp
index 3f9442adf9de7..7e4f24b556613 100644
--- a/mlir/lib/Bindings/Python/DialectLLVM.cpp
+++ b/mlir/lib/Bindings/Python/DialectLLVM.cpp
@@ -26,8 +26,7 @@ using namespace mlir::python::nanobind_adaptors;
namespace mlir {
namespace python {
-namespace
-MLIR_BINDINGS_PYTHON_DOMAIN {
+namespace MLIR_BINDINGS_PYTHON_DOMAIN {
namespace llvm {
//===--------------------------------------------------------------------===//
// StructType
@@ -286,16 +285,15 @@ struct MDStringAttr : PyConcreteAttribute<MDStringAttr> {
c.def_static(
"get",
[](const std::string &value, DefaultingPyMlirContext context) {
- return MDStringAttr(context->getRef(),
- mlirLLVMMDStringAttrGet(
- context.get()->get(),
- mlirStringRefCreate(value.data(),
- value.size())));
+ return MDStringAttr(
+ context->getRef(),
+ mlirLLVMMDStringAttrGet(
+ context.get()->get(),
+ mlirStringRefCreate(value.data(), value.size())));
},
"value"_a, nb::kw_only(), "context"_a = nb::none());
c.def_prop_ro("value", [](const MDStringAttr &self) {
- MlirStringRef ref =
- mlirLLVMMDStringAttrGetValue(self);
+ MlirStringRef ref = mlirLLVMMDStringAttrGetValue(self);
return nb::str(ref.data, ref.length);
});
}
@@ -311,10 +309,10 @@ struct MDConstantAttr : PyConcreteAttribute<MDConstantAttr> {
static void bindDerived(ClassTy &c) {
c.def_static(
"get",
- [](PyAttribute &integerAttr, DefaultingPyMlirContext context) {
+ [](PyAttribute &valueAttr, DefaultingPyMlirContext context) {
return MDConstantAttr(
context->getRef(),
- mlirLLVMMDConstantAttrGet(context.get()->get(), integerAttr));
+ mlirLLVMMDConstantAttrGet(context.get()->get(), valueAttr));
},
"value"_a, nb::kw_only(), "context"_a = nb::none());
c.def_prop_ro("value", [](const MDConstantAttr &self) {
@@ -337,9 +335,9 @@ struct MDFuncAttr : PyConcreteAttribute<MDFuncAttr> {
MlirAttribute symRef = mlirFlatSymbolRefAttrGet(
context.get()->get(),
mlirStringRefCreate(name.data(), name.size()));
- return MDFuncAttr(context->getRef(),
- mlirLLVMMDFuncAttrGet(context.get()->get(),
- symRef));
+ return MDFuncAttr(
+ context->getRef(),
+ mlirLLVMMDFuncAttrGet(context.get()->get(), symRef));
},
"name"_a, nb::kw_only(), "context"_a = nb::none());
c.def_prop_ro("name", [](const MDFuncAttr &self) {
@@ -364,22 +362,21 @@ struct MDNodeAttr : PyConcreteAttribute<MDNodeAttr> {
DefaultingPyMlirContext context) {
std::vector<MlirAttribute> operands_(operands.size());
std::copy(operands.begin(), operands.end(), operands_.begin());
- return MDNodeAttr(
- context->getRef(),
- mlirLLVMMDNodeAttrGet(context.get()->get(), operands_.size(),
- operands_.data()));
+ return MDNodeAttr(context->getRef(),
+ mlirLLVMMDNodeAttrGet(context.get()->get(),
+ operands_.size(),
+ operands_.data()));
},
"operands"_a, nb::kw_only(), "context"_a = nb::none());
c.def_prop_ro("num_operands", [](const MDNodeAttr &self) {
return mlirLLVMMDNodeAttrGetNumOperands(self);
});
- c.def("__getitem__",
- [](const MDNodeAttr &self, intptr_t index) {
- intptr_t n = mlirLLVMMDNodeAttrGetNumOperands(self);
- if (index < 0 || index >= n)
- throw nb::index_error("MDNodeAttr operand index out of range");
- return mlirLLVMMDNodeAttrGetOperand(self, index);
- });
+ c.def("__getitem__", [](const MDNodeAttr &self, intptr_t index) {
+ intptr_t n = mlirLLVMMDNodeAttrGetNumOperands(self);
+ if (index < 0 || index >= n)
+ throw nb::index_error("MDNodeAttr operand index out of range");
+ return mlirLLVMMDNodeAttrGetOperand(self, index);
+ });
c.def("__len__", [](const MDNodeAttr &self) {
return mlirLLVMMDNodeAttrGetNumOperands(self);
});
diff --git a/mlir/lib/CAPI/Dialect/LLVM.cpp b/mlir/lib/CAPI/Dialect/LLVM.cpp
index 8f46a60f5ad13..f05529ba2ccdf 100644
--- a/mlir/lib/CAPI/Dialect/LLVM.cpp
+++ b/mlir/lib/CAPI/Dialect/LLVM.cpp
@@ -100,7 +100,7 @@ intptr_t mlirLLVMFunctionTypeGetNumInputs(MlirType type) {
MlirType mlirLLVMFunctionTypeGetInput(MlirType type, intptr_t pos) {
assert(pos >= 0 && "pos in array must be positive");
return wrap(llvm::cast<LLVM::LLVMFunctionType>(unwrap(type))
- .getParamType(static_cast<unsigned>(pos)));
+ .getParamType(static_cast<unsigned>(pos)));
}
MlirType mlirLLVMFunctionTypeGetReturnType(MlirType type) {
@@ -191,7 +191,7 @@ MlirLogicalResult mlirLLVMStructTypeSetBody(MlirType structType,
SmallVector<Type> fields;
return wrap(
cast<LLVM::LLVMStructType>(unwrap(structType))
- .setBody(unwrapList(nFieldTypes, fieldTypes, fields), isPacked));
+ .setBody(unwrapList(nFieldTypes, fieldTypes, fields), isPacked));
}
MlirAttribute mlirLLVMDIExpressionElemAttrGet(MlirContext ctx,
@@ -541,9 +541,8 @@ MlirStringRef mlirLLVMDIAnnotationAttrGetName(void) {
//===----------------------------------------------------------------------===//
MlirAttribute mlirLLVMMDStringAttrGet(MlirContext ctx, MlirStringRef value) {
- return wrap(
- MDStringAttr::get(unwrap(ctx),
- StringAttr::get(unwrap(ctx), unwrap(value))));
+ return wrap(MDStringAttr::get(unwrap(ctx),
+ StringAttr::get(unwrap(ctx), unwrap(value))));
}
bool mlirLLVMAttrIsAMDStringAttr(MlirAttribute attr) {
@@ -560,8 +559,8 @@ MlirStringRef mlirLLVMMDStringAttrGetValue(MlirAttribute attr) {
MlirAttribute mlirLLVMMDConstantAttrGet(MlirContext ctx,
MlirAttribute integerAttr) {
- return wrap(MDConstantAttr::get(unwrap(ctx),
- cast<IntegerAttr>(unwrap(integerAttr))));
+ return wrap(
+ MDConstantAttr::get(unwrap(ctx), cast<IntegerAttr>(unwrap(integerAttr))));
}
bool mlirLLVMAttrIsAMDConstantAttr(MlirAttribute attr) {
@@ -598,9 +597,8 @@ MlirAttribute mlirLLVMMDNodeAttrGet(MlirContext ctx, intptr_t nOperands,
SmallVector<Attribute> attrStorage;
attrStorage.reserve(nOperands);
return wrap(MDNodeAttr::get(
- unwrap(ctx),
- ArrayAttr::get(unwrap(ctx),
- unwrapList(nOperands, operands, attrStorage))));
+ unwrap(ctx), ArrayAttr::get(unwrap(ctx), unwrapList(nOperands, operands,
+ attrStorage))));
}
bool mlirLLVMAttrIsAMDNodeAttr(MlirAttribute attr) {
@@ -615,7 +613,6 @@ intptr_t mlirLLVMMDNodeAttrGetNumOperands(MlirAttribute attr) {
return cast<MDNodeAttr>(unwrap(attr)).getOperands().size();
}
-MlirAttribute mlirLLVMMDNodeAttrGetOperand(MlirAttribute attr,
- intptr_t index) {
+MlirAttribute mlirLLVMMDNodeAttrGetOperand(MlirAttribute attr, intptr_t index) {
return wrap(cast<MDNodeAttr>(unwrap(attr)).getOperands()[index]);
}
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 9e758e9fdb0e4..30f11db091836 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -166,8 +166,8 @@ convertCallLLVMIntrinsicOp(CallIntrinsicOp op, llvm::IRBuilderBase &builder,
// Check the result type of the call.
const llvm::Type *intrinType =
op.getNumResults() == 0
- ? llvm::Type::getVoidTy(module->getContext())
- : moduleTranslation.convertType(op.getResultTypes().front());
+ ? llvm::Type::getVoidTy(module->getContext())
+ : moduleTranslation.convertType(op.getResultTypes().front());
if (intrinType != fn->getReturnType()) {
return mlir::emitError(op.getLoc(), "intrinsic call returns ")
<< diagStr(intrinType) << " but " << op.getIntrinAttr()
@@ -221,31 +221,33 @@ static llvm::Metadata *
convertMetadataAttr(Attribute attr, llvm::IRBuilderBase &builder,
LLVM::ModuleTranslation &moduleTranslation) {
return llvm::TypeSwitch<Attribute, llvm::Metadata *>(attr)
- .Case<LLVM::MDStringAttr>([&](auto a) -> llvm::Metadata * {
- return llvm::MDString::get(builder.getContext(),
- a.getValue().getValue());
- })
- .Case<LLVM::MDConstantAttr>([&](auto a) -> llvm::Metadata * {
- IntegerAttr intAttr = a.getValue();
- return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
- llvm::Type::getIntNTy(builder.getContext(),
- intAttr.getType().getIntOrFloatBitWidth()),
- intAttr.getValue()));
- })
- .Case<LLVM::MDFuncAttr>([&](auto a) -> llvm::Metadata * {
- if (llvm::Function *fn =
- moduleTranslation.lookupFunction(a.getName().getValue()))
- return llvm::ValueAsMetadata::get(fn);
- return nullptr;
- })
- .Case<LLVM::MDNodeAttr>([&](auto a) -> llvm::Metadata * {
- SmallVector<llvm::Metadata *> operands;
- for (Attribute op : a.getOperands())
- operands.push_back(
- convertMetadataAttr(op, builder, moduleTranslation));
- return llvm::MDNode::get(builder.getContext(), operands);
- })
- .Default([](auto) -> llvm::Metadata * { return nullptr; });
+ .Case<LLVM::MDStringAttr>([&](auto a) -> llvm::Metadata * {
+ return llvm::MDString::get(builder.getContext(),
+ a.getValue().getValue());
+ })
+ .Case<LLVM::MDConstantAttr>([&](auto a) -> llvm::Metadata * {
+ IntegerAttr intAttr = llvm::dyn_cast<IntegerAttr>(a.getValue());
+ if (!intAttr)
+ return nullptr;
+ return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getIntNTy(builder.getContext(),
+ intAttr.getType().getIntOrFloatBitWidth()),
+ intAttr.getValue()));
+ })
+ .Case<LLVM::MDFuncAttr>([&](auto a) -> llvm::Metadata * {
+ if (llvm::Function *fn =
+ moduleTranslation.lookupFunction(a.getName().getValue()))
+ return llvm::ValueAsMetadata::get(fn);
+ return nullptr;
+ })
+ .Case<LLVM::MDNodeAttr>([&](auto a) -> llvm::Metadata * {
+ SmallVector<llvm::Metadata *> operands;
+ for (Attribute op : a.getOperands())
+ operands.push_back(
+ convertMetadataAttr(op, builder, moduleTranslation));
+ return llvm::MDNode::get(builder.getContext(), operands);
+ })
+ .Default([](auto) -> llvm::Metadata * { return nullptr; });
}
static void convertNamedMetadataOp(StringRef metadataName, ArrayAttr nodes,
@@ -294,7 +296,7 @@ convertModuleFlagValue(StringRef key, ArrayAttr arrayAttr,
if (!sym)
return nullptr;
if (llvm::Function *fn =
- moduleTranslation.lookupFunction(sym.getValue()))
+ moduleTranslation.lookupFunction(sym.getValue()))
return llvm::ValueAsMetadata::get(fn);
return nullptr;
};
@@ -321,7 +323,7 @@ static llvm::Metadata *convertModuleFlagProfileSummaryAttr(
auto getIntTuple = [&](StringRef key, uint64_t val) -> llvm::MDTuple * {
SmallVector<llvm::Metadata *> tupleNodes{
mdb.createString(key), mdb.createConstant(llvm::ConstantInt::get(
- llvm::Type::getInt64Ty(context), val))};
+ llvm::Type::getInt64Ty(context), val))};
return llvm::MDTuple::get(context, tupleNodes);
};
@@ -380,26 +382,26 @@ static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
llvm::Metadata *valueMetadata =
llvm::TypeSwitch<Attribute, llvm::Metadata *>(flagAttr.getValue())
- .Case([&](StringAttr strAttr) {
- return llvm::MDString::get(builder.getContext(),
- strAttr.getValue());
- })
- .Case([&](IntegerAttr intAttr) {
- return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
- llvm::Type::getInt32Ty(builder.getContext()),
- intAttr.getInt()));
- })
- .Case([&](ArrayAttr arrayAttr) {
- return convertModuleFlagValue(flagAttr.getKey().getValue(),
- arrayAttr, builder,
- moduleTranslation);
- })
- .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
- return convertModuleFlagProfileSummaryAttr(
- flagAttr.getKey().getValue(), summaryAttr, builder,
- moduleTranslation);
- })
- .Default([](auto) { return nullptr; });
+ .Case([&](StringAttr strAttr) {
+ return llvm::MDString::get(builder.getContext(),
+ strAttr.getValue());
+ })
+ .Case([&](IntegerAttr intAttr) {
+ return llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
+ llvm::Type::getInt32Ty(builder.getContext()),
+ intAttr.getInt()));
+ })
+ .Case([&](ArrayAttr arrayAttr) {
+ return convertModuleFlagValue(flagAttr.getKey().getValue(),
+ arrayAttr, builder,
+ moduleTranslation);
+ })
+ .Case([&](ModuleFlagProfileSummaryAttr summaryAttr) {
+ return convertModuleFlagProfileSummaryAttr(
+ flagAttr.getKey().getValue(), summaryAttr, builder,
+ moduleTranslation);
+ })
+ .Default([](auto) { return nullptr; });
assert(valueMetadata && "expected valid metadata");
llvmModule->addModuleFlag(
@@ -412,9 +414,9 @@ static llvm::DILocalScope *
getLocalScopeFromLoc(llvm::IRBuilderBase &builder, Location loc,
LLVM::ModuleTranslation &moduleTranslation) {
if (auto scopeLoc =
- loc->findInstanceOf<FusedLocWith<LLVM::DILocalScopeAttr>>())
+ loc->findInstanceOf<FusedLocWith<LLVM::DILocalScopeAttr>>())
if (auto *localScope = llvm::dyn_cast<llvm::DILocalScope>(
- moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
+ moduleTranslation.translateDebugInfo(scopeLoc.getMetadata())))
return localScope;
return builder.GetInsertBlock()->getParent()->getSubprogram();
}
@@ -428,6 +430,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
builder.setFastMathFlags(getFastmathFlags(fmf));
#include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
+
#include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
// Emit function calls. If the "callee" attribute is present, this is a
@@ -443,7 +446,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
llvm::CallInst *call;
if (auto attr = callOp.getCalleeAttr()) {
if (llvm::Function *function =
- moduleTranslation.lookupFunction(attr.getValue())) {
+ moduleTranslation.lookupFunction(attr.getValue())) {
call = builder.CreateCall(function, operandsRef, opBundles);
} else {
Operation *moduleOp = parentLLVMModule(&opInst);
@@ -527,8 +530,8 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
ModuleTranslation::convertDefaultFuncAttr);
if (llvm::Attribute attr =
- moduleTranslation.convertAllocsizeAttr(callOp.getAllocsizeAttr());
- attr.isValid())
+ moduleTranslation.convertAllocsizeAttr(callOp.getAllocsizeAttr());
+ attr.isValid())
call->addFnAttr(attr);
if (failed(moduleTranslation.convertArgAndResultAttrs(callOp, call)))
@@ -560,7 +563,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// that LLVM IR dialect CallOp has either 0 or 1 result.
if (opInst.getNumResults() != 0)
moduleTranslation.mapValue(opInst.getResult(0), call);
- // Check that LLVM call returns void for 0-result functions.
+ // Check that LLVM call returns void for 0-result functions.
else if (!call->getType()->isVoidTy())
return failure();
moduleTranslation.mapCall(callOp, call);
@@ -583,19 +586,19 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
auto ft = LLVM::LLVMFunctionType::get(resultType, operandTypes);
llvm::InlineAsm *inlineAsmInst =
inlineAsmOp.getAsmDialect()
- ? llvm::InlineAsm::get(
- static_cast<llvm::FunctionType *>(
- moduleTranslation.convertType(ft)),
- inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
- inlineAsmOp.getHasSideEffects(),
- inlineAsmOp.getIsAlignStack(),
- convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
- : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
- moduleTranslation.convertType(ft)),
- inlineAsmOp.getAsmString(),
- inlineAsmOp.getConstraints(),
- inlineAsmOp.getHasSideEffects(),
- inlineAsmOp.getIsAlignStack());
+ ? llvm::InlineAsm::get(
+ static_cast<llvm::FunctionType *>(
+ moduleTranslation.convertType(ft)),
+ inlineAsmOp.getAsmString(), inlineAsmOp.getConstraints(),
+ inlineAsmOp.getHasSideEffects(),
+ inlineAsmOp.getIsAlignStack(),
+ convertAsmDialectToLLVM(*inlineAsmOp.getAsmDialect()))
+ : llvm::InlineAsm::get(static_cast<llvm::FunctionType *>(
+ moduleTranslation.convertType(ft)),
+ inlineAsmOp.getAsmString(),
+ inlineAsmOp.getConstraints(),
+ inlineAsmOp.getHasSideEffects(),
+ inlineAsmOp.getIsAlignStack());
llvm::CallInst *inst = builder.CreateCall(
inlineAsmInst,
moduleTranslation.lookupValues(inlineAsmOp.getOperands()));
@@ -743,7 +746,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// The verifier should not have allowed this.
assert((global || function || alias || ifunc) &&
- "referencing an undefined global, function, alias, or ifunc");
+ "referencing an undefined global, function, alias, or ifunc");
llvm::Value *llvmValue = nullptr;
if (global)
@@ -762,7 +765,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// Emit dso_local_equivalent. We need to look up the global value referenced
// by the operation and store it in the MLIR-to-LLVM value mapping.
if (auto dsoLocalEquivalentOp =
- dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
+ dyn_cast<LLVM::DSOLocalEquivalentOp>(opInst)) {
LLVM::LLVMFuncOp function =
dsoLocalEquivalentOp.getFunction(moduleTranslation.symbolTable());
LLVM::AliasOp alias =
@@ -770,7 +773,7 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
// The verifier should not have allowed this.
assert((function || alias) &&
- "referencing an undefined function, or alias");
+ "referencing an undefined function, or alias");
llvm::Value *llvmValue = nullptr;
if (alias)
@@ -809,8 +812,8 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
/*isConstant=*/true, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
/*Initializer=*/nullptr,
Twine("__mlir_block_address_")
- .concat(Twine(fnName))
- .concat(Twine((uint64_t)blockAddressOp.getOperation())));
+ .concat(Twine(fnName))
+ .concat(Twine((uint64_t)blockAddressOp.getOperation())));
moduleTranslation.mapUnresolvedBlockAddress(blockAddressOp, llvmValue);
}
diff --git a/mlir/python/mlir/dialects/llvm.py b/mlir/python/mlir/dialects/llvm.py
index 1fd7e64251e61..6ef2efc1dca04 100644
--- a/mlir/python/mlir/dialects/llvm.py
+++ b/mlir/python/mlir/dialects/llvm.py
@@ -6,7 +6,7 @@
from ._llvm_ops_gen import _Dialect
from ._llvm_enum_gen import *
from .._mlir_libs._mlirDialectsLLVM import *
-from ..ir import Value
+from ..ir import Value, IntegerType, IntegerAttr
from ._ods_common import get_op_result_or_op_results as _get_op_result_or_op_results
@@ -14,3 +14,18 @@ def mlir_constant(value, *, loc=None, ip=None) -> Value:
return _get_op_result_or_op_results(
ConstantOp(res=value.type, value=value, loc=loc, ip=ip)
)
+
+
+def md_const(val, *, width=32, context=None):
+ """Create an MDConstantIntAttr wrapping an i<width> integer constant."""
+ if not isinstance(val, int):
+ raise NotImplementedError(
+ f"{val=} not supported; only integers currently supported."
+ )
+ i_type = IntegerType.get_signless(width, context=context)
+ return MDConstantAttr.get(IntegerAttr.get(i_type, val), context=context)
+
+
+def md_str(s, *, context=None):
+ """Create an MDStringAttr wrapping a string."""
+ return MDStringAttr.get(s, context=context)
diff --git a/mlir/test/python/dialects/llvm.py b/mlir/test/python/dialects/llvm.py
index b1d64f5fc27fe..52dd1109ab58f 100644
--- a/mlir/test/python/dialects/llvm.py
+++ b/mlir/test/python/dialects/llvm.py
@@ -250,6 +250,14 @@ def testMetadataAttrs():
print(md_node)
assert len(md_node) == 2
+ # MDNodeAttr - __getitem__
+ # CHECK: #llvm.md_const<42 : i32>
+ print(md_node[0])
+ # CHECK: #llvm.md_string<"foo.buffer">
+ print(md_node[1])
+ assert str(md_node[0]) == str(md_const)
+ assert str(md_node[1]) == str(md_str)
+
# MDNodeAttr - nested
md_nested = llvm.MDNodeAttr.get([md_node, md_empty])
# CHECK: #llvm.md_node<[#llvm.md_node<[#llvm.md_const<42 : i32>, #llvm.md_string<"foo.buffer">]>, #llvm.md_node<[]>]>
@@ -260,14 +268,6 @@ def testMetadataAttrs():
# CHECK-LABEL: testNamedMetadata
@constructAndPrintInModule
def testNamedMetadata():
- i32 = IntegerType.get_signless(32)
-
- def md_const(val):
- return llvm.MDConstantAttr.get(IntegerAttr.get(i32, val))
-
- def md_str(s):
- return llvm.MDStringAttr.get(s)
-
void = Type.parse("!llvm.void")
func_ty = llvm.FunctionType.get(void, [])
@@ -277,7 +277,11 @@ def md_str(s):
llvm.NamedMetadataOp(
metadata_name="foo.version",
nodes=ArrayAttr.get(
- [llvm.MDNodeAttr.get([md_const(1), md_const(0), md_const(0)])]
+ [
+ llvm.MDNodeAttr.get(
+ [llvm.md_const(1), llvm.md_const(0), llvm.md_const(0)]
+ )
+ ]
),
)
# CHECK: llvm.named_metadata "foo.version" [#llvm.md_node<[#llvm.md_const<1 : i32>, #llvm.md_const<0 : i32>, #llvm.md_const<0 : i32>]>]
@@ -287,7 +291,12 @@ def md_str(s):
nodes=ArrayAttr.get(
[
llvm.MDNodeAttr.get(
- [md_str("Bar"), md_const(1), md_const(2), md_const(3)]
+ [
+ llvm.md_str("Bar"),
+ llvm.md_const(1),
+ llvm.md_const(2),
+ llvm.md_const(3),
+ ]
)
]
),
@@ -296,18 +305,18 @@ def md_str(s):
buf0 = llvm.MDNodeAttr.get(
[
- md_const(0),
- md_str("foo.buffer"),
- md_str("foo.idx"),
- md_const(0),
- md_const(1),
- md_str("foo.read"),
- md_str("foo.address_space"),
- md_const(1),
- md_str("foo.size"),
- md_const(4),
- md_str("foo.align_size"),
- md_const(4),
+ llvm.md_const(0),
+ llvm.md_str("foo.buffer"),
+ llvm.md_str("foo.idx"),
+ llvm.md_const(0),
+ llvm.md_const(1),
+ llvm.md_str("foo.read"),
+ llvm.md_str("foo.address_space"),
+ llvm.md_const(1),
+ llvm.md_str("foo.size"),
+ llvm.md_const(4),
+ llvm.md_str("foo.align_size"),
+ llvm.md_const(4),
]
)
>From f5a5596430017cff7d08aa12b94008acb074d586 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Sun, 15 Mar 2026 15:04:39 -0700
Subject: [PATCH 4/4] reduce lit test
---
mlir/include/mlir-c/Dialect/LLVM.h | 6 +-
.../mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 2 +-
mlir/lib/CAPI/Dialect/LLVM.cpp | 5 +-
.../LLVMIR/LLVMToLLVMIRTranslation.cpp | 1 -
mlir/python/mlir/dialects/llvm.py | 2 -
.../Target/LLVMIR/llvmir-named-metadata.mlir | 80 +++----------------
6 files changed, 17 insertions(+), 79 deletions(-)
diff --git a/mlir/include/mlir-c/Dialect/LLVM.h b/mlir/include/mlir-c/Dialect/LLVM.h
index b36a5f6f98a97..2c167d23a7d9a 100644
--- a/mlir/include/mlir-c/Dialect/LLVM.h
+++ b/mlir/include/mlir-c/Dialect/LLVM.h
@@ -489,9 +489,9 @@ MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDStringAttrGetTypeID(void);
MLIR_CAPI_EXPORTED MlirStringRef
mlirLLVMMDStringAttrGetValue(MlirAttribute attr);
-/// Creates an LLVM MDConstantAttr wrapping an integer attribute.
+/// Creates an LLVM MDConstantAttr wrapping an attribute.
MLIR_CAPI_EXPORTED MlirAttribute
-mlirLLVMMDConstantAttrGet(MlirContext ctx, MlirAttribute integerAttr);
+mlirLLVMMDConstantAttrGet(MlirContext ctx, MlirAttribute valueAttr);
/// Returns `true` if the attribute is an LLVM MDConstantAttr.
MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDConstantAttr(MlirAttribute attr);
@@ -499,7 +499,7 @@ MLIR_CAPI_EXPORTED bool mlirLLVMAttrIsAMDConstantAttr(MlirAttribute attr);
/// Returns the TypeID of MDConstantAttr.
MLIR_CAPI_EXPORTED MlirTypeID mlirLLVMMDConstantAttrGetTypeID(void);
-/// Returns the integer attribute value of an LLVM MDConstantAttr.
+/// Returns the attribute value of an LLVM MDConstantAttr.
MLIR_CAPI_EXPORTED MlirAttribute
mlirLLVMMDConstantAttrGetValue(MlirAttribute attr);
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index f360c69c6436f..077c5c880cc9b 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1712,7 +1712,7 @@ def LLVM_MDStringAttr : LLVM_Attr<"MDString", "md_string"> {
def LLVM_MDConstantAttr : LLVM_Attr<"MDConstant", "md_const"> {
let summary = "LLVM constant-as-metadata";
let description = [{
- Wraps an integer constant as an LLVM metadata node, corresponding to
+ Wraps an attribute as an LLVM metadata node, corresponding to
`llvm::ConstantAsMetadata` wrapping a `llvm::Constant*` in LLVM IR.
Currently, only integers/IntegerAttrs supported.
diff --git a/mlir/lib/CAPI/Dialect/LLVM.cpp b/mlir/lib/CAPI/Dialect/LLVM.cpp
index f05529ba2ccdf..0b85acaed4727 100644
--- a/mlir/lib/CAPI/Dialect/LLVM.cpp
+++ b/mlir/lib/CAPI/Dialect/LLVM.cpp
@@ -558,9 +558,8 @@ MlirStringRef mlirLLVMMDStringAttrGetValue(MlirAttribute attr) {
}
MlirAttribute mlirLLVMMDConstantAttrGet(MlirContext ctx,
- MlirAttribute integerAttr) {
- return wrap(
- MDConstantAttr::get(unwrap(ctx), cast<IntegerAttr>(unwrap(integerAttr))));
+ MlirAttribute valueAttr) {
+ return wrap(MDConstantAttr::get(unwrap(ctx), unwrap(valueAttr)));
}
bool mlirLLVMAttrIsAMDConstantAttr(MlirAttribute attr) {
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 30f11db091836..e60a682b42ea1 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -430,7 +430,6 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
builder.setFastMathFlags(getFastmathFlags(fmf));
#include "mlir/Dialect/LLVMIR/LLVMConversions.inc"
-
#include "mlir/Dialect/LLVMIR/LLVMIntrinsicConversions.inc"
// Emit function calls. If the "callee" attribute is present, this is a
diff --git a/mlir/python/mlir/dialects/llvm.py b/mlir/python/mlir/dialects/llvm.py
index 6ef2efc1dca04..23ed23997c3ba 100644
--- a/mlir/python/mlir/dialects/llvm.py
+++ b/mlir/python/mlir/dialects/llvm.py
@@ -17,7 +17,6 @@ def mlir_constant(value, *, loc=None, ip=None) -> Value:
def md_const(val, *, width=32, context=None):
- """Create an MDConstantIntAttr wrapping an i<width> integer constant."""
if not isinstance(val, int):
raise NotImplementedError(
f"{val=} not supported; only integers currently supported."
@@ -27,5 +26,4 @@ def md_const(val, *, width=32, context=None):
def md_str(s, *, context=None):
- """Create an MDStringAttr wrapping a string."""
return MDStringAttr.get(s, context=context)
diff --git a/mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir b/mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir
index 144285e9bfebc..16b7162079583 100644
--- a/mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-named-metadata.mlir
@@ -11,14 +11,19 @@ llvm.func @my_kernel() {
}
llvm.named_metadata "foo.version" [
- #llvm.md_node<[#llvm.md_const<1 : i32>, #llvm.md_const<0 : i32>,
- #llvm.md_const<0 : i32>]>
+ #llvm.md_node<[#llvm.md_const<1 : i32>,
+ #llvm.md_const<0 : i32>,
+ #llvm.md_const<0 : i32>
+ ]>
]
// CHECK-DAG: ![[VERSION]] = !{i32 1, i32 0, i32 0}
llvm.named_metadata "foo.language_version" [
- #llvm.md_node<[#llvm.md_string<"Bar">, #llvm.md_const<1 : i32>,
- #llvm.md_const<2 : i32>, #llvm.md_const<3 : i32>]>
+ #llvm.md_node<[#llvm.md_string<"Bar">,
+ #llvm.md_const<1 : i32>,
+ #llvm.md_const<2 : i32>,
+ #llvm.md_const<3 : i32>
+ ]>
]
// CHECK-DAG: ![[LANG]] = !{!"Bar", i32 1, i32 2, i32 3}
@@ -32,76 +37,13 @@ llvm.named_metadata "foo.language_version" [
]>
// CHECK-DAG: ![[A0:[0-9]+]] = !{i32 0, !"foo.buffer", !"foo.idx", i32 0, i32 1, !"foo.read", !"foo.address_space", i32 1, !"foo.size", i32 4, !"foo.align_size", i32 4}
-#buf1 = #llvm.md_node<[
- #llvm.md_const<1 : i32>, #llvm.md_string<"foo.buffer">,
- #llvm.md_string<"foo.idx">, #llvm.md_const<1 : i32>,
- #llvm.md_const<1 : i32>, #llvm.md_string<"foo.read_write">,
- #llvm.md_string<"foo.address_space">, #llvm.md_const<1 : i32>,
- #llvm.md_string<"foo.size">, #llvm.md_const<4 : i32>,
- #llvm.md_string<"foo.align_size">, #llvm.md_const<4 : i32>
-]>
-// CHECK-DAG: ![[A1:[0-9]+]] = !{i32 1, !"foo.buffer", !"foo.idx", i32 1, i32 1, !"foo.read_write", !"foo.address_space", i32 1, !"foo.size", i32 4, !"foo.align_size", i32 4}
-
-#buf2 = #llvm.md_node<[
- #llvm.md_const<2 : i32>, #llvm.md_string<"foo.buffer">,
- #llvm.md_string<"foo.idx">, #llvm.md_const<2 : i32>,
- #llvm.md_const<1 : i32>, #llvm.md_string<"foo.read">,
- #llvm.md_string<"foo.address_space">, #llvm.md_const<2 : i32>,
- #llvm.md_string<"foo.size">, #llvm.md_const<4 : i32>,
- #llvm.md_string<"foo.align_size">, #llvm.md_const<4 : i32>
-]>
-// CHECK-DAG: ![[A2:[0-9]+]] = !{i32 2, !"foo.buffer", !"foo.idx", i32 2, i32 1, !"foo.read", !"foo.address_space", i32 2, !"foo.size", i32 4, !"foo.align_size", i32 4}
-
-#pos3 = #llvm.md_node<[
- #llvm.md_const<3 : i32>, #llvm.md_string<"foo.block_position_in_grid">,
- #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
- #llvm.md_string<"foo.arg_name">, #llvm.md_string<"block_position_in_grid">
-]>
-// CHECK-DAG: ![[A3:[0-9]+]] = !{i32 3, !"foo.block_position_in_grid", !"foo.name", !"vec3", !"foo.arg_name", !"block_position_in_grid"}
-
-#pos4 = #llvm.md_node<[
- #llvm.md_const<4 : i32>, #llvm.md_string<"foo.blocks_per_grid">,
- #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
- #llvm.md_string<"foo.arg_name">, #llvm.md_string<"blocks_per_grid">
-]>
-// CHECK-DAG: ![[A4:[0-9]+]] = !{i32 4, !"foo.blocks_per_grid", !"foo.name", !"vec3", !"foo.arg_name", !"blocks_per_grid"}
-
-#pos5 = #llvm.md_node<[
- #llvm.md_const<5 : i32>, #llvm.md_string<"foo.thread_position_in_block">,
- #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
- #llvm.md_string<"foo.arg_name">, #llvm.md_string<"thread_position_in_block">
-]>
-// CHECK-DAG: ![[A5:[0-9]+]] = !{i32 5, !"foo.thread_position_in_block", !"foo.name", !"vec3", !"foo.arg_name", !"thread_position_in_block"}
-
-#pos6 = #llvm.md_node<[
- #llvm.md_const<6 : i32>, #llvm.md_string<"foo.threads_per_block">,
- #llvm.md_string<"foo.name">, #llvm.md_string<"vec3">,
- #llvm.md_string<"foo.arg_name">, #llvm.md_string<"threads_per_block">
-]>
-// CHECK-DAG: ![[A6:[0-9]+]] = !{i32 6, !"foo.threads_per_block", !"foo.name", !"vec3", !"foo.arg_name", !"threads_per_block"}
-
-#pos7 = #llvm.md_node<[
- #llvm.md_const<7 : i32>, #llvm.md_string<"foo.thread_idx_in_warp">,
- #llvm.md_string<"foo.name">, #llvm.md_string<"vec1">,
- #llvm.md_string<"foo.arg_name">, #llvm.md_string<"thread_idx_in_warp">
-]>
-// CHECK-DAG: ![[A7:[0-9]+]] = !{i32 7, !"foo.thread_idx_in_warp", !"foo.name", !"vec1", !"foo.arg_name", !"thread_idx_in_warp"}
-
-#pos8 = #llvm.md_node<[
- #llvm.md_const<8 : i32>, #llvm.md_string<"foo.warp_idx_in_block">,
- #llvm.md_string<"foo.name">, #llvm.md_string<"vec1">,
- #llvm.md_string<"foo.arg_name">, #llvm.md_string<"warp_idx_in_block">
-]>
-// CHECK-DAG: ![[A8:[0-9]+]] = !{i32 8, !"foo.warp_idx_in_block", !"foo.name", !"vec1", !"foo.arg_name", !"warp_idx_in_block"}
-
llvm.named_metadata "foo.kernel" [
#llvm.md_node<[
#llvm.md_func<@my_kernel>,
#llvm.md_node<[]>,
- #llvm.md_node<[#buf0, #buf1, #buf2,
- #pos3, #pos4, #pos5, #pos6, #pos7, #pos8]>
+ #llvm.md_node<[#buf0]>
]>
]
// CHECK-DAG: ![[KERNEL]] = !{ptr @my_kernel, ![[EMPTY:[0-9]+]], ![[ARGS:[0-9]+]]}
// CHECK-DAG: ![[EMPTY]] = !{}
-// CHECK-DAG: ![[ARGS]] = !{![[A0]], ![[A1]], ![[A2]], ![[A3]], ![[A4]], ![[A5]], ![[A6]], ![[A7]], ![[A8]]}
+// CHECK-DAG: ![[ARGS]] = !{![[A0]]}
More information about the Mlir-commits
mailing list