[Mlir-commits] [mlir] [MLIR][LLVM] Preserve global value metadata operands on import (PR #203017)
Akimasa Watanuki
llvmlistbot at llvm.org
Tue Aug 11 00:03:17 PDT 2026
https://github.com/Men-cotton updated https://github.com/llvm/llvm-project/pull/203017
>From c938d3b85fbed82781c6054e732efff72f3a875e Mon Sep 17 00:00:00 2001
From: mencotton <mencotton0410 at gmail.com>
Date: Wed, 10 Jun 2026 00:46:12 +0900
Subject: [PATCH 1/3] [MLIR][LLVM] Preserve global value metadata operands on
import
Import global value references inside LLVM metadata operands as LLVM dialect metadata symbol-reference attributes. Add llvm.read_register import coverage for function, global, alias, and nameless-global metadata operands.
---
mlir/lib/Target/LLVMIR/ModuleImport.cpp | 64 ++++++++++++---
.../Target/LLVMIR/Import/import-failure.ll | 45 +++++++++++
.../LLVMIR/Import/intrinsic-unregistered.ll | 80 +++++++++++++++++--
3 files changed, 171 insertions(+), 18 deletions(-)
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 725d7cf6c8413..3857a5e8d6c61 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -150,6 +150,29 @@ static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder,
return failure();
}
+static FlatSymbolRefAttr getMetadataGlobalValueSymbolRef(
+ MLIRContext *ctx, LLVMImportInterface &iface, llvm::GlobalValue *global,
+ llvm::function_ref<FlatSymbolRefAttr(llvm::GlobalVariable *)>
+ getNamelessGlobalSymbol) {
+ if (auto *globalVar = dyn_cast<llvm::GlobalVariable>(global)) {
+ StringRef name = globalVar->getName();
+ if (name.empty())
+ return getNamelessGlobalSymbol(globalVar);
+ if (name == getGlobalCtorsVarName() || name == getGlobalDtorsVarName())
+ return {};
+ }
+
+ if (auto *func = dyn_cast<llvm::Function>(global)) {
+ if (func->isIntrinsic() &&
+ iface.isConvertibleIntrinsic(func->getIntrinsicID()))
+ return {};
+ }
+
+ if (global->getName().empty())
+ return {};
+ return FlatSymbolRefAttr::get(ctx, global->getName());
+}
+
/// Depth-first conversion of the metadata node `md` to the matching LLVM
/// dialect metadata attribute. Returns a null attribute for shapes that the
/// dialect's metadata-attribute hierarchy does not currently model. `path`
@@ -162,24 +185,31 @@ static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder,
static Attribute convertMetadataToAttrImpl(
MLIRContext *ctx, const llvm::Metadata *md,
SmallPtrSetImpl<const llvm::Metadata *> &path,
- DenseMap<const llvm::Metadata *, Attribute> &attrMap) {
+ DenseMap<const llvm::Metadata *, Attribute> &attrMap,
+ LLVMImportInterface &iface,
+ llvm::function_ref<FlatSymbolRefAttr(llvm::GlobalVariable *)>
+ getNamelessGlobalSymbol) {
if (!md)
return {};
if (auto *mdStr = dyn_cast<llvm::MDString>(md))
return MDStringAttr::get(ctx, StringAttr::get(ctx, mdStr->getString()));
if (auto *cam = dyn_cast<llvm::ConstantAsMetadata>(md)) {
- auto *ci = dyn_cast<llvm::ConstantInt>(cam->getValue());
+ llvm::Constant *constant = cam->getValue();
+ if (auto *global = dyn_cast<llvm::GlobalValue>(constant)) {
+ if (FlatSymbolRefAttr symbolRef = getMetadataGlobalValueSymbolRef(
+ ctx, iface, global, getNamelessGlobalSymbol))
+ return MDGlobalValueAttr::get(ctx, symbolRef);
+ }
+ auto *ci = dyn_cast<llvm::ConstantInt>(constant);
if (!ci)
return {};
auto intType = IntegerType::get(ctx, ci->getBitWidth());
return MDConstantAttr::get(ctx, IntegerAttr::get(intType, ci->getValue()));
}
if (auto *vam = dyn_cast<llvm::ValueAsMetadata>(md)) {
- auto *fn = dyn_cast<llvm::Function>(vam->getValue());
- if (!fn)
- return {};
- return MDGlobalValueAttr::get(ctx,
- FlatSymbolRefAttr::get(ctx, fn->getName()));
+ if (isa<llvm::GlobalValue>(vam->getValue()))
+ llvm_unreachable("global values should be ConstantAsMetadata");
+ return {};
}
if (auto *node = dyn_cast<llvm::MDNode>(md)) {
// Metadata attributes cannot preserve distinctness, so bail out.
@@ -194,8 +224,8 @@ static Attribute convertMetadataToAttrImpl(
SmallVector<Attribute> operands;
operands.reserve(node->getNumOperands());
for (const llvm::MDOperand &op : node->operands()) {
- Attribute opAttr =
- convertMetadataToAttrImpl(ctx, op.get(), path, attrMap);
+ Attribute opAttr = convertMetadataToAttrImpl(
+ ctx, op.get(), path, attrMap, iface, getNamelessGlobalSymbol);
if (!opAttr)
return {};
operands.push_back(opAttr);
@@ -213,11 +243,14 @@ static Attribute convertMetadataToAttrImpl(
/// metadata-attribute hierarchy does not currently model, including distinct
/// nodes and cyclic metadata graphs that the immutable metadata attributes
/// cannot express.
-static Attribute convertMetadataToAttr(MLIRContext *ctx,
- const llvm::Metadata *md) {
+static Attribute convertMetadataToAttr(
+ MLIRContext *ctx, const llvm::Metadata *md, LLVMImportInterface &iface,
+ llvm::function_ref<FlatSymbolRefAttr(llvm::GlobalVariable *)>
+ getNamelessGlobalSymbol) {
SmallPtrSet<const llvm::Metadata *, 8> path;
DenseMap<const llvm::Metadata *, Attribute> attrMap;
- return convertMetadataToAttrImpl(ctx, md, path, attrMap);
+ return convertMetadataToAttrImpl(ctx, md, path, attrMap, iface,
+ getNamelessGlobalSymbol);
}
/// Get a topologically sorted list of blocks for the given basic blocks.
@@ -1990,7 +2023,12 @@ FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
// attribute.
if (auto *mdAsVal = dyn_cast<llvm::MetadataAsValue>(value)) {
llvm::Metadata *md = mdAsVal->getMetadata();
- Attribute mdAttr = convertMetadataToAttr(context, md);
+ auto getNamelessGlobalSymbol =
+ [this](llvm::GlobalVariable *globalVar) -> FlatSymbolRefAttr {
+ return getOrCreateNamelessSymbolName(globalVar);
+ };
+ Attribute mdAttr =
+ convertMetadataToAttr(context, md, iface, getNamelessGlobalSymbol);
if (!mdAttr)
return emitError(mlirModule.getLoc())
<< "unsupported metadata: " << diagMD(md, llvmModule.get());
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 564fbf4d3df68..30437a5097cd9 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -493,3 +493,48 @@ define i32 @cyclic_metadata_as_value() {
}
!0 = distinct !{!0}
+
+; // -----
+
+; CHECK: error: unsupported metadata: ptr @llvm.memcpy.p0.p0.i64
+declare i32 @llvm.read_register.i32(metadata)
+declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly, ptr noalias readonly, i64, i1 immarg)
+
+define i32 @skipped_intrinsic_metadata() {
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @llvm.memcpy.p0.p0.i64}
+
+; // -----
+
+; CHECK: error: unsupported metadata: ptr @llvm.global_ctors
+declare i32 @llvm.read_register.i32(metadata)
+define void @ctor() {
+ ret void
+}
+ at llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @ctor, ptr null }]
+
+define i32 @metadata_ref_global_ctors() {
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @llvm.global_ctors}
+
+; // -----
+
+; CHECK: error: unsupported metadata: ptr @llvm.global_dtors
+declare i32 @llvm.read_register.i32(metadata)
+define void @dtor() {
+ ret void
+}
+ at llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 0, ptr @dtor, ptr null }]
+
+define i32 @metadata_ref_global_dtors() {
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @llvm.global_dtors}
diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
index da58d48d995be..e358957de40e0 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
@@ -11,7 +11,6 @@ define dso_local void @t0(ptr %a) {
; CHECK-LABEL: llvm.func @t0
; CHECK: llvm.call_intrinsic "llvm.aarch64.ldxr.p0"({{.*}}) : (!llvm.ptr {llvm.elementtype = i8}) -> i64
; CHECK: llvm.return
-; CHECK: }
; // -----
@@ -22,10 +21,9 @@ define dso_local <8 x i8> @t1(<8 x i8> %lhs, <8 x i8> %rhs) {
ret <8 x i8> %r
}
-; CHECK: llvm.func @t1(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>) -> vector<8xi8> {{.*}} {
+; CHECK: llvm.func @t1(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>) -> vector<8xi8> {{.*}}
; CHECK: %[[R:.*]] = llvm.call_intrinsic "llvm.aarch64.neon.uabd.v8i8"(%[[A0]], %[[A1]]) : (vector<8xi8>, vector<8xi8>) -> vector<8xi8>
; CHECK: llvm.return %[[R]] : vector<8xi8>
-; CHECK: }
; // -----
@@ -36,10 +34,9 @@ define dso_local void @t2(<8 x i8> %lhs, <8 x i8> %rhs, ptr %a) {
ret void
}
-; CHECK: llvm.func @t2(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>, %[[A2:.*]]: !llvm.ptr) {{.*}} {
+; CHECK: llvm.func @t2(%[[A0:.*]]: vector<8xi8>, %[[A1:.*]]: vector<8xi8>, %[[A2:.*]]: !llvm.ptr) {{.*}}
; CHECK: llvm.call_intrinsic "llvm.aarch64.neon.st2.v8i8.p0"(%[[A0]], %[[A1]], %[[A2]]) : (vector<8xi8>, vector<8xi8>, !llvm.ptr) -> ()
; CHECK: llvm.return
-; CHECK: }
; // -----
@@ -115,3 +112,76 @@ define i32 @read_named_register() {
}
!0 = !{!"sp"}
+
+; // -----
+
+declare i32 @llvm.read_register.i32(metadata)
+
+ at global = global i32 0
+
+; CHECK-LABEL: llvm.func @read_global_metadata
+define i32 @read_global_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@global>
+ ; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @global}
+
+; // -----
+
+declare i32 @llvm.read_register.i32(metadata)
+
+define void @alias_target() {
+ ret void
+}
+ at alias = alias void (), ptr @alias_target
+
+; CHECK-LABEL: llvm.func @read_alias_metadata
+define i32 @read_alias_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@alias>
+ ; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @alias}
+
+; // -----
+
+declare i32 @llvm.read_register.i32(metadata)
+
+ at ifunc = ifunc void (), ptr @ifunc_resolver
+define ptr @ifunc_resolver() {
+ ret ptr @ifunc_target
+}
+define void @ifunc_target() {
+ ret void
+}
+
+; CHECK-LABEL: llvm.func @read_ifunc_metadata
+define i32 @read_ifunc_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@ifunc>
+ ; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @ifunc}
+
+; // -----
+
+declare i32 @llvm.read_register.i32(metadata)
+
+ at 0 = global i32 0
+
+; CHECK-LABEL: llvm.func @read_nameless_global_metadata
+define i32 @read_nameless_global_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@{{mlir\.llvm\.nameless_global_[0-9]+}}>
+ ; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @0}
>From db3f39cd3f80582b4c87e4a3e8d252d047008434 Mon Sep 17 00:00:00 2001
From: mencotton <mencotton0410 at gmail.com>
Date: Tue, 11 Aug 2026 15:41:59 +0900
Subject: [PATCH 2/3] fix: address review comments from gysit
---
.../include/mlir/Target/LLVMIR/ModuleImport.h | 12 ++++
mlir/lib/Target/LLVMIR/ModuleImport.cpp | 60 +++++++------------
.../Target/LLVMIR/Import/import-failure.ll | 13 ++++
.../LLVMIR/Import/intrinsic-unregistered.ll | 28 +++++++--
4 files changed, 70 insertions(+), 43 deletions(-)
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index dba950c0b48b6..da6471a2e001d 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -19,6 +19,7 @@
#include "mlir/Target/LLVMIR/Import.h"
#include "mlir/Target/LLVMIR/LLVMImportInterface.h"
#include "mlir/Target/LLVMIR/TypeFromLLVM.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Module.h"
namespace llvm {
@@ -378,6 +379,17 @@ class ModuleImport {
/// the resulting dialect attributes to the converted operation `op`. Emits a
/// warning if the conversion of a supported metadata kind fails.
void setNonDebugMetadataAttrs(llvm::Instruction *inst, Operation *op);
+ /// Returns the symbol reference for a global value that has a corresponding
+ /// imported MLIR symbol, or a null attribute otherwise.
+ FlatSymbolRefAttr getMetadataGlobalValueSymbolRef(llvm::GlobalValue *global);
+ /// Converts `md` to the matching LLVM dialect metadata attribute, or returns
+ /// a null attribute if the metadata cannot be represented.
+ Attribute convertMetadataToAttr(const llvm::Metadata *md);
+ /// Recursively converts `md` and tracks the current path and previously
+ /// converted nodes to reject cycles and preserve shared subgraphs.
+ Attribute convertMetadataToAttrImpl(
+ const llvm::Metadata *md, SmallPtrSetImpl<const llvm::Metadata *> &path,
+ DenseMap<const llvm::Metadata *, Attribute> &attrMap);
/// Imports `inst` and populates valueMapping[inst] with the result of the
/// imported operation or noResultOpMapping[inst] with the imported operation
/// if it has no result.
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 3857a5e8d6c61..3fefc8efcbbe7 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -150,19 +150,19 @@ static LogicalResult convertInstructionImpl(OpBuilder &odsBuilder,
return failure();
}
-static FlatSymbolRefAttr getMetadataGlobalValueSymbolRef(
- MLIRContext *ctx, LLVMImportInterface &iface, llvm::GlobalValue *global,
- llvm::function_ref<FlatSymbolRefAttr(llvm::GlobalVariable *)>
- getNamelessGlobalSymbol) {
+FlatSymbolRefAttr
+ModuleImport::getMetadataGlobalValueSymbolRef(llvm::GlobalValue *global) {
if (auto *globalVar = dyn_cast<llvm::GlobalVariable>(global)) {
StringRef name = globalVar->getName();
if (name.empty())
- return getNamelessGlobalSymbol(globalVar);
+ return getOrCreateNamelessSymbolName(globalVar);
if (name == getGlobalCtorsVarName() || name == getGlobalDtorsVarName())
return {};
}
if (auto *func = dyn_cast<llvm::Function>(global)) {
+ // Intrinsics with a dedicated import conversion do not have an imported
+ // function declaration that a metadata symbol reference could resolve to.
if (func->isIntrinsic() &&
iface.isConvertibleIntrinsic(func->getIntrinsicID()))
return {};
@@ -170,7 +170,7 @@ static FlatSymbolRefAttr getMetadataGlobalValueSymbolRef(
if (global->getName().empty())
return {};
- return FlatSymbolRefAttr::get(ctx, global->getName());
+ return FlatSymbolRefAttr::get(context, global->getName());
}
/// Depth-first conversion of the metadata node `md` to the matching LLVM
@@ -182,34 +182,26 @@ static FlatSymbolRefAttr getMetadataGlobalValueSymbolRef(
/// set lets the traversal recognize such a back-edge and bail out. `attrMap`
/// caches the attributes of fully converted nodes so that shared subgraphs
/// are visited only once.
-static Attribute convertMetadataToAttrImpl(
- MLIRContext *ctx, const llvm::Metadata *md,
- SmallPtrSetImpl<const llvm::Metadata *> &path,
- DenseMap<const llvm::Metadata *, Attribute> &attrMap,
- LLVMImportInterface &iface,
- llvm::function_ref<FlatSymbolRefAttr(llvm::GlobalVariable *)>
- getNamelessGlobalSymbol) {
+Attribute ModuleImport::convertMetadataToAttrImpl(
+ const llvm::Metadata *md, SmallPtrSetImpl<const llvm::Metadata *> &path,
+ DenseMap<const llvm::Metadata *, Attribute> &attrMap) {
if (!md)
return {};
if (auto *mdStr = dyn_cast<llvm::MDString>(md))
- return MDStringAttr::get(ctx, StringAttr::get(ctx, mdStr->getString()));
+ return MDStringAttr::get(context,
+ StringAttr::get(context, mdStr->getString()));
if (auto *cam = dyn_cast<llvm::ConstantAsMetadata>(md)) {
llvm::Constant *constant = cam->getValue();
if (auto *global = dyn_cast<llvm::GlobalValue>(constant)) {
- if (FlatSymbolRefAttr symbolRef = getMetadataGlobalValueSymbolRef(
- ctx, iface, global, getNamelessGlobalSymbol))
- return MDGlobalValueAttr::get(ctx, symbolRef);
+ if (FlatSymbolRefAttr symbolRef = getMetadataGlobalValueSymbolRef(global))
+ return MDGlobalValueAttr::get(context, symbolRef);
}
auto *ci = dyn_cast<llvm::ConstantInt>(constant);
if (!ci)
return {};
- auto intType = IntegerType::get(ctx, ci->getBitWidth());
- return MDConstantAttr::get(ctx, IntegerAttr::get(intType, ci->getValue()));
- }
- if (auto *vam = dyn_cast<llvm::ValueAsMetadata>(md)) {
- if (isa<llvm::GlobalValue>(vam->getValue()))
- llvm_unreachable("global values should be ConstantAsMetadata");
- return {};
+ auto intType = IntegerType::get(context, ci->getBitWidth());
+ return MDConstantAttr::get(context,
+ IntegerAttr::get(intType, ci->getValue()));
}
if (auto *node = dyn_cast<llvm::MDNode>(md)) {
// Metadata attributes cannot preserve distinctness, so bail out.
@@ -224,14 +216,13 @@ static Attribute convertMetadataToAttrImpl(
SmallVector<Attribute> operands;
operands.reserve(node->getNumOperands());
for (const llvm::MDOperand &op : node->operands()) {
- Attribute opAttr = convertMetadataToAttrImpl(
- ctx, op.get(), path, attrMap, iface, getNamelessGlobalSymbol);
+ Attribute opAttr = convertMetadataToAttrImpl(op.get(), path, attrMap);
if (!opAttr)
return {};
operands.push_back(opAttr);
}
path.erase(node);
- Attribute nodeAttr = MDNodeAttr::get(ctx, operands);
+ Attribute nodeAttr = MDNodeAttr::get(context, operands);
attrMap.try_emplace(node, nodeAttr);
return nodeAttr;
}
@@ -243,14 +234,10 @@ static Attribute convertMetadataToAttrImpl(
/// metadata-attribute hierarchy does not currently model, including distinct
/// nodes and cyclic metadata graphs that the immutable metadata attributes
/// cannot express.
-static Attribute convertMetadataToAttr(
- MLIRContext *ctx, const llvm::Metadata *md, LLVMImportInterface &iface,
- llvm::function_ref<FlatSymbolRefAttr(llvm::GlobalVariable *)>
- getNamelessGlobalSymbol) {
+Attribute ModuleImport::convertMetadataToAttr(const llvm::Metadata *md) {
SmallPtrSet<const llvm::Metadata *, 8> path;
DenseMap<const llvm::Metadata *, Attribute> attrMap;
- return convertMetadataToAttrImpl(ctx, md, path, attrMap, iface,
- getNamelessGlobalSymbol);
+ return convertMetadataToAttrImpl(md, path, attrMap);
}
/// Get a topologically sorted list of blocks for the given basic blocks.
@@ -2023,12 +2010,7 @@ FailureOr<Value> ModuleImport::convertValue(llvm::Value *value) {
// attribute.
if (auto *mdAsVal = dyn_cast<llvm::MetadataAsValue>(value)) {
llvm::Metadata *md = mdAsVal->getMetadata();
- auto getNamelessGlobalSymbol =
- [this](llvm::GlobalVariable *globalVar) -> FlatSymbolRefAttr {
- return getOrCreateNamelessSymbolName(globalVar);
- };
- Attribute mdAttr =
- convertMetadataToAttr(context, md, iface, getNamelessGlobalSymbol);
+ Attribute mdAttr = convertMetadataToAttr(md);
if (!mdAttr)
return emitError(mlirModule.getLoc())
<< "unsupported metadata: " << diagMD(md, llvmModule.get());
diff --git a/mlir/test/Target/LLVMIR/Import/import-failure.ll b/mlir/test/Target/LLVMIR/Import/import-failure.ll
index 30437a5097cd9..d995143a40576 100644
--- a/mlir/test/Target/LLVMIR/Import/import-failure.ll
+++ b/mlir/test/Target/LLVMIR/Import/import-failure.ll
@@ -496,6 +496,19 @@ define i32 @cyclic_metadata_as_value() {
; // -----
+; Local values cannot be represented by symbol-backed metadata attributes.
+; CHECK: error: unsupported metadata: i32 %{{.*}}
+declare i32 @llvm.read_register.i32(metadata)
+
+define i32 @local_value_metadata(i32 %arg) {
+ %r = call i32 @llvm.read_register.i32(metadata i32 %arg)
+ ret i32 %r
+}
+
+; // -----
+
+; Intrinsics with dedicated import conversions have no imported symbol for a
+; metadata symbol reference to target.
; CHECK: error: unsupported metadata: ptr @llvm.memcpy.p0.p0.i64
declare i32 @llvm.read_register.i32(metadata)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly, ptr noalias readonly, i64, i1 immarg)
diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
index e358957de40e0..969874e6bad20 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
@@ -115,13 +115,30 @@ define i32 @read_named_register() {
; // -----
+declare i32 @llvm.read_register.i32(metadata)
+declare void @callee()
+
+; CHECK: llvm.func @[[$CALLEE:callee]]()
+; CHECK-LABEL: llvm.func @read_function_metadata
+define i32 @read_function_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$CALLEE]]>
+ ; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @callee}
+
+; // -----
+
declare i32 @llvm.read_register.i32(metadata)
@global = global i32 0
+; CHECK: llvm.mlir.global external @[[$GLOBAL:global]]
; CHECK-LABEL: llvm.func @read_global_metadata
define i32 @read_global_metadata() {
- ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@global>
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$GLOBAL]]>
; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
%r = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %r
@@ -138,9 +155,10 @@ define void @alias_target() {
}
@alias = alias void (), ptr @alias_target
+; CHECK: llvm.mlir.alias external @[[$ALIAS:alias]]
; CHECK-LABEL: llvm.func @read_alias_metadata
define i32 @read_alias_metadata() {
- ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@alias>
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$ALIAS]]>
; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
%r = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %r
@@ -160,9 +178,10 @@ define void @ifunc_target() {
ret void
}
+; CHECK: llvm.mlir.ifunc external @[[$IFUNC:ifunc]]
; CHECK-LABEL: llvm.func @read_ifunc_metadata
define i32 @read_ifunc_metadata() {
- ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@ifunc>
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$IFUNC]]>
; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
%r = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %r
@@ -176,9 +195,10 @@ declare i32 @llvm.read_register.i32(metadata)
@0 = global i32 0
+; CHECK: llvm.mlir.global external @[[$NAMELESS_GLOBAL:mlir\.llvm\.nameless_global_[0-9]+]]
; CHECK-LABEL: llvm.func @read_nameless_global_metadata
define i32 @read_nameless_global_metadata() {
- ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@{{mlir\.llvm\.nameless_global_[0-9]+}}>
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$NAMELESS_GLOBAL]]>
; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
%r = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %r
>From d2beb1b2aca742df6d192ca9d7fb5aaecc2ed6df Mon Sep 17 00:00:00 2001
From: mencotton <mencotton0410 at gmail.com>
Date: Tue, 11 Aug 2026 15:58:54 +0900
Subject: [PATCH 3/3] fix: order global value metadata tests by import branch
---
.../LLVMIR/Import/intrinsic-unregistered.ll | 58 +++++++++----------
1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
index 969874e6bad20..06ad9a1e94f66 100644
--- a/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
+++ b/mlir/test/Target/LLVMIR/Import/intrinsic-unregistered.ll
@@ -116,35 +116,52 @@ define i32 @read_named_register() {
; // -----
declare i32 @llvm.read_register.i32(metadata)
-declare void @callee()
-; CHECK: llvm.func @[[$CALLEE:callee]]()
-; CHECK-LABEL: llvm.func @read_function_metadata
-define i32 @read_function_metadata() {
- ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$CALLEE]]>
+ at global = global i32 0
+
+; CHECK: llvm.mlir.global external @[[$GLOBAL:global]]
+; CHECK-LABEL: llvm.func @read_global_metadata
+define i32 @read_global_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$GLOBAL]]>
; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
%r = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %r
}
-!0 = !{ptr @callee}
+!0 = !{ptr @global}
; // -----
declare i32 @llvm.read_register.i32(metadata)
- at global = global i32 0
+ at 0 = global i32 0
-; CHECK: llvm.mlir.global external @[[$GLOBAL:global]]
-; CHECK-LABEL: llvm.func @read_global_metadata
-define i32 @read_global_metadata() {
- ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$GLOBAL]]>
+; CHECK: llvm.mlir.global external @[[$NAMELESS_GLOBAL:mlir\.llvm\.nameless_global_[0-9]+]]
+; CHECK-LABEL: llvm.func @read_nameless_global_metadata
+define i32 @read_nameless_global_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$NAMELESS_GLOBAL]]>
; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
%r = call i32 @llvm.read_register.i32(metadata !0)
ret i32 %r
}
-!0 = !{ptr @global}
+!0 = !{ptr @0}
+
+; // -----
+
+declare i32 @llvm.read_register.i32(metadata)
+declare void @callee()
+
+; CHECK: llvm.func @[[$CALLEE:callee]]()
+; CHECK-LABEL: llvm.func @read_function_metadata
+define i32 @read_function_metadata() {
+ ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$CALLEE]]>
+ ; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
+ %r = call i32 @llvm.read_register.i32(metadata !0)
+ ret i32 %r
+}
+
+!0 = !{ptr @callee}
; // -----
@@ -188,20 +205,3 @@ define i32 @read_ifunc_metadata() {
}
!0 = !{ptr @ifunc}
-
-; // -----
-
-declare i32 @llvm.read_register.i32(metadata)
-
- at 0 = global i32 0
-
-; CHECK: llvm.mlir.global external @[[$NAMELESS_GLOBAL:mlir\.llvm\.nameless_global_[0-9]+]]
-; CHECK-LABEL: llvm.func @read_nameless_global_metadata
-define i32 @read_nameless_global_metadata() {
- ; CHECK: %[[MD:.*]] = llvm.mlir.metadata_as_value #llvm.md_global_value<@[[$NAMELESS_GLOBAL]]>
- ; CHECK: llvm.call_intrinsic "llvm.read_register.i32"(%[[MD]]) : (!llvm.metadata) -> i32
- %r = call i32 @llvm.read_register.i32(metadata !0)
- ret i32 %r
-}
-
-!0 = !{ptr @0}
More information about the Mlir-commits
mailing list