[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