[Mlir-commits] [mlir] [mlir][llvm] adds an attribute for the module level assembly (PR #151318)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Thu Jul 31 04:58:19 PDT 2025


https://github.com/gitoleg updated https://github.com/llvm/llvm-project/pull/151318

>From dd8b762c237f4a7a8c4087757f695a0879c8f05b Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Wed, 30 Jul 2025 15:36:44 +0300
Subject: [PATCH 1/9] [mlir][llvm] adds an attribute for the module level
 assembly

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td | 3 +++
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp    | 4 ++++
 mlir/test/Target/LLVMIR/module-asm.mlir         | 5 +++++
 3 files changed, 12 insertions(+)
 create mode 100644 mlir/test/Target/LLVMIR/module-asm.mlir

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
index b5ea8fc5da500..107bf3edb657a 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
@@ -83,6 +83,9 @@ def LLVM_Dialect : Dialect {
       return "llvm.emit_c_interface";
     }
 
+    /// Name of the module level assembly attribute.
+    static StringRef getModuleLevelAsmAttrName() { return "llvm.module_asm"; }
+
     /// Name of the dependent libraries attribute.
     static StringRef getDependentLibrariesAttrName() {
       return "llvm.dependent_libraries";
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index b997e559885e2..2c2ef598aa6a9 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2276,6 +2276,10 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
     llvmModule->setTargetTriple(
         llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
 
+  if (auto asmAttr =
+          m->getDiscardableAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName()))
+    llvmModule->setModuleInlineAsm(cast<StringAttr>(asmAttr).getValue());
+
   return llvmModule;
 }
 
diff --git a/mlir/test/Target/LLVMIR/module-asm.mlir b/mlir/test/Target/LLVMIR/module-asm.mlir
new file mode 100644
index 0000000000000..fa8158ac2677a
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/module-asm.mlir
@@ -0,0 +1,5 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+module attributes {llvm.module_asm = "foo"} {}
+
+// CHECK: module asm "foo"
\ No newline at end of file

>From bc7cf6c3a25b081cf0c27599973b9a46d59643af Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Wed, 30 Jul 2025 18:36:43 +0300
Subject: [PATCH 2/9] use ArrayAttr

---
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 7 +++++--
 mlir/test/Target/LLVMIR/module-asm.mlir      | 5 +++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 2c2ef598aa6a9..4048b30c2b811 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2277,8 +2277,11 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
         llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
 
   if (auto asmAttr =
-          m->getDiscardableAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName()))
-    llvmModule->setModuleInlineAsm(cast<StringAttr>(asmAttr).getValue());
+          m->getDiscardableAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
+    auto arr = cast<ArrayAttr>(asmAttr);
+    for (unsigned i = 0; i < arr.size(); ++i)
+      llvmModule->appendModuleInlineAsm(cast<StringAttr>(arr[i]).getValue());
+  }
 
   return llvmModule;
 }
diff --git a/mlir/test/Target/LLVMIR/module-asm.mlir b/mlir/test/Target/LLVMIR/module-asm.mlir
index fa8158ac2677a..f3404dd1a7001 100644
--- a/mlir/test/Target/LLVMIR/module-asm.mlir
+++ b/mlir/test/Target/LLVMIR/module-asm.mlir
@@ -1,5 +1,6 @@
 // RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
 
-module attributes {llvm.module_asm = "foo"} {}
+module attributes {llvm.module_asm = ["foo", "bar"]} {}
 
-// CHECK: module asm "foo"
\ No newline at end of file
+// CHECK: module asm "foo"
+// CHECK: module asm "bar"
\ No newline at end of file

>From 5bdb44d07ba5524235957d0d88ce5393de8c8d11 Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Thu, 31 Jul 2025 09:40:00 +0300
Subject: [PATCH 3/9] some changes after review

---
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 8 ++++----
 mlir/test/Target/LLVMIR/module-asm.mlir      | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 4048b30c2b811..ffc502566fab8 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2276,11 +2276,11 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
     llvmModule->setTargetTriple(
         llvm::Triple(cast<StringAttr>(targetTripleAttr).getValue()));
 
-  if (auto asmAttr =
-          m->getDiscardableAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
+  if (auto asmAttr = m->getDiscardableAttr(
+          LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
     auto arr = cast<ArrayAttr>(asmAttr);
-    for (unsigned i = 0; i < arr.size(); ++i)
-      llvmModule->appendModuleInlineAsm(cast<StringAttr>(arr[i]).getValue());
+    for (auto elt : arr)
+      llvmModule->appendModuleInlineAsm(cast<StringAttr>(elt).getValue());
   }
 
   return llvmModule;
diff --git a/mlir/test/Target/LLVMIR/module-asm.mlir b/mlir/test/Target/LLVMIR/module-asm.mlir
index f3404dd1a7001..2afb37cf005bf 100644
--- a/mlir/test/Target/LLVMIR/module-asm.mlir
+++ b/mlir/test/Target/LLVMIR/module-asm.mlir
@@ -3,4 +3,4 @@
 module attributes {llvm.module_asm = ["foo", "bar"]} {}
 
 // CHECK: module asm "foo"
-// CHECK: module asm "bar"
\ No newline at end of file
+// CHECK: module asm "bar"

>From 7a20b31c2bae69367fb223d9cdcde52aa953ca84 Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Thu, 31 Jul 2025 10:39:05 +0300
Subject: [PATCH 4/9] added import implementation

---
 mlir/include/mlir/Target/LLVMIR/ModuleImport.h |  4 ++++
 mlir/lib/Target/LLVMIR/ModuleImport.cpp        | 15 +++++++++++++++
 mlir/test/Target/LLVMIR/Import/module-asm.ll   |  5 +++++
 3 files changed, 24 insertions(+)
 create mode 100644 mlir/test/Target/LLVMIR/Import/module-asm.ll

diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index 17ef8e44afd2d..b3fc3fb65c85d 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -83,6 +83,10 @@ class ModuleImport {
   /// specification.
   void convertTargetTriple();
 
+  /// Converts the module level asm of the LLVM module to an MLIR module
+  /// level asm specification.
+  void convertModuleLevelAsm();
+
   /// Stores the mapping between an LLVM value and its MLIR counterpart.
   void mapValue(llvm::Value *llvm, Value mlir) { mapValue(llvm) = mlir; }
 
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 58e3c44ec0049..59774d2046eab 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -30,6 +30,7 @@
 #include "llvm/ADT/DepthFirstIterator.h"
 #include "llvm/ADT/PostOrderIterator.h"
 #include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/IR/Comdat.h"
 #include "llvm/IR/Constants.h"
@@ -1063,6 +1064,19 @@ void ModuleImport::convertTargetTriple() {
       builder.getStringAttr(llvmModule->getTargetTriple().str()));
 }
 
+void ModuleImport::convertModuleLevelAsm() {
+  auto str = llvmModule->getModuleInlineAsm();
+  llvm::SmallVector<mlir::Attribute> arr;
+
+  for (auto line : llvm::split(str, '\n'))
+    if (!line.empty())
+      arr.push_back(builder.getStringAttr(line));
+
+  mlirModule->setAttr(
+      LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
+      builder.getArrayAttr(arr));
+}
+
 LogicalResult ModuleImport::convertFunctions() {
   for (llvm::Function &func : llvmModule->functions())
     if (failed(processFunction(&func)))
@@ -3199,5 +3213,6 @@ OwningOpRef<ModuleOp> mlir::translateLLVMIRToModule(
   if (failed(moduleImport.convertIFuncs()))
     return {};
   moduleImport.convertTargetTriple();
+  moduleImport.convertModuleLevelAsm();
   return module;
 }
diff --git a/mlir/test/Target/LLVMIR/Import/module-asm.ll b/mlir/test/Target/LLVMIR/Import/module-asm.ll
new file mode 100644
index 0000000000000..38f6ea448acba
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/module-asm.ll
@@ -0,0 +1,5 @@
+; RUN: mlir-translate -import-llvm %s | FileCheck %s
+; CHECK: llvm.module_asm = ["foo", "bar"]
+
+module asm "foo"
+module asm "bar"

>From 5d8479f1dab3bfd4c5335b53d531d8ecfa921988 Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Thu, 31 Jul 2025 11:22:43 +0300
Subject: [PATCH 5/9] added checks for attributes

---
 mlir/lib/Target/LLVMIR/ModuleImport.cpp      |  5 ++---
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 13 ++++++++++++-
 mlir/test/Target/LLVMIR/invalid-module.mlir  | 10 +++++++++-
 3 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 59774d2046eab..7de6cd19d09c2 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1072,9 +1072,8 @@ void ModuleImport::convertModuleLevelAsm() {
     if (!line.empty())
       arr.push_back(builder.getStringAttr(line));
 
-  mlirModule->setAttr(
-      LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
-      builder.getArrayAttr(arr));
+  mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
+                      builder.getArrayAttr(arr));
 }
 
 LogicalResult ModuleImport::convertFunctions() {
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index ffc502566fab8..25aa6eba3e1f5 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2278,9 +2278,20 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
 
   if (auto asmAttr = m->getDiscardableAttr(
           LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
+    if (!isa<ArrayAttr>(asmAttr)) {
+      m->emitError("expected an array attribute for a module level asm");
+      return nullptr;
+    }
+
     auto arr = cast<ArrayAttr>(asmAttr);
-    for (auto elt : arr)
+    for (auto elt : arr) {
+      if (!isa<StringAttr>(elt)) {
+        m->emitError(
+            "expected a string attribute for each entry of a module level asm");
+        return nullptr;
+      }
       llvmModule->appendModuleInlineAsm(cast<StringAttr>(elt).getValue());
+    }
   }
 
   return llvmModule;
diff --git a/mlir/test/Target/LLVMIR/invalid-module.mlir b/mlir/test/Target/LLVMIR/invalid-module.mlir
index 7fd5f26998a09..2725612b2f0f6 100644
--- a/mlir/test/Target/LLVMIR/invalid-module.mlir
+++ b/mlir/test/Target/LLVMIR/invalid-module.mlir
@@ -1,6 +1,14 @@
-// RUN: mlir-translate -verify-diagnostics -mlir-to-llvmir --no-implicit-module %s
+// RUN: mlir-translate -verify-diagnostics -mlir-to-llvmir --no-implicit-module -split-input-file %s
 
 // expected-error at below {{'llvm.func' op can not be translated to an LLVMIR module}}
 llvm.func @foo() {
   llvm.return
 }
+
+// -----
+// expected-error at below {{expected an array attribute for a module level asm}}
+module attributes {llvm.module_asm = "foo"} {}
+
+// -----
+// expected-error at below {{expected a string attribute for each entry of a module level asm}}
+module attributes {llvm.module_asm = [42]} {}
\ No newline at end of file

>From 9a0ec93b3f9a1a6aa15840b204bf4812948a3a34 Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Thu, 31 Jul 2025 11:49:57 +0300
Subject: [PATCH 6/9] minor

---
 mlir/test/Target/LLVMIR/invalid-module.mlir | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/test/Target/LLVMIR/invalid-module.mlir b/mlir/test/Target/LLVMIR/invalid-module.mlir
index 2725612b2f0f6..54beb43edc410 100644
--- a/mlir/test/Target/LLVMIR/invalid-module.mlir
+++ b/mlir/test/Target/LLVMIR/invalid-module.mlir
@@ -11,4 +11,4 @@ module attributes {llvm.module_asm = "foo"} {}
 
 // -----
 // expected-error at below {{expected a string attribute for each entry of a module level asm}}
-module attributes {llvm.module_asm = [42]} {}
\ No newline at end of file
+module attributes {llvm.module_asm = [42]} {}

>From 5f7aa3023321f610da7fe1ff8ed029a58308bd45 Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Thu, 31 Jul 2025 14:35:19 +0300
Subject: [PATCH 7/9] changes after review

---
 mlir/lib/Target/LLVMIR/ModuleImport.cpp      | 10 +++++-----
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp |  9 +++++----
 mlir/test/Target/LLVMIR/invalid-module.mlir  |  2 ++
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 7de6cd19d09c2..7c3a58cb60b00 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1065,15 +1065,15 @@ void ModuleImport::convertTargetTriple() {
 }
 
 void ModuleImport::convertModuleLevelAsm() {
-  auto str = llvmModule->getModuleInlineAsm();
-  llvm::SmallVector<mlir::Attribute> arr;
+  llvm::StringRef asmStr = llvmModule->getModuleInlineAsm();
+  llvm::SmallVector<mlir::Attribute> asmArrayAttr;
 
-  for (auto line : llvm::split(str, '\n'))
+  for (llvm::StringRef line : llvm::split(asmStr, '\n'))
     if (!line.empty())
-      arr.push_back(builder.getStringAttr(line));
+      asmArrayAttr.push_back(builder.getStringAttr(line));
 
   mlirModule->setAttr(LLVM::LLVMDialect::getModuleLevelAsmAttrName(),
-                      builder.getArrayAttr(arr));
+                      builder.getArrayAttr(asmArrayAttr));
 }
 
 LogicalResult ModuleImport::convertFunctions() {
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 25aa6eba3e1f5..b9444f339dc4a 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2278,19 +2278,20 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
 
   if (auto asmAttr = m->getDiscardableAttr(
           LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
-    if (!isa<ArrayAttr>(asmAttr)) {
+    auto arr = dyn_cast<ArrayAttr>(asmAttr);
+    if (!arr) {
       m->emitError("expected an array attribute for a module level asm");
       return nullptr;
     }
 
-    auto arr = cast<ArrayAttr>(asmAttr);
     for (auto elt : arr) {
-      if (!isa<StringAttr>(elt)) {
+      auto asmStrAttr = dyn_cast<StringAttr>(elt);
+      if (!asmStrAttr) {
         m->emitError(
             "expected a string attribute for each entry of a module level asm");
         return nullptr;
       }
-      llvmModule->appendModuleInlineAsm(cast<StringAttr>(elt).getValue());
+      llvmModule->appendModuleInlineAsm(asmStrAttr.getValue());
     }
   }
 
diff --git a/mlir/test/Target/LLVMIR/invalid-module.mlir b/mlir/test/Target/LLVMIR/invalid-module.mlir
index 54beb43edc410..5ed62449d413c 100644
--- a/mlir/test/Target/LLVMIR/invalid-module.mlir
+++ b/mlir/test/Target/LLVMIR/invalid-module.mlir
@@ -6,9 +6,11 @@ llvm.func @foo() {
 }
 
 // -----
+
 // expected-error at below {{expected an array attribute for a module level asm}}
 module attributes {llvm.module_asm = "foo"} {}
 
 // -----
+
 // expected-error at below {{expected a string attribute for each entry of a module level asm}}
 module attributes {llvm.module_asm = [42]} {}

>From de0c3107ef06758d8eeea182dbe8d193ac9f310a Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Thu, 31 Jul 2025 14:43:54 +0300
Subject: [PATCH 8/9] minor

---
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index b9444f339dc4a..5f46c22b1fca0 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2278,13 +2278,13 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
 
   if (auto asmAttr = m->getDiscardableAttr(
           LLVM::LLVMDialect::getModuleLevelAsmAttrName())) {
-    auto arr = dyn_cast<ArrayAttr>(asmAttr);
-    if (!arr) {
+    auto asmArrayAttr = dyn_cast<ArrayAttr>(asmAttr);
+    if (!asmArrayAttr) {
       m->emitError("expected an array attribute for a module level asm");
       return nullptr;
     }
 
-    for (auto elt : arr) {
+    for (auto elt : asmArrayAttr) {
       auto asmStrAttr = dyn_cast<StringAttr>(elt);
       if (!asmStrAttr) {
         m->emitError(

>From 672f11505819a420135f9ae4f14dd7f5e7ffa935 Mon Sep 17 00:00:00 2001
From: gitoleg <forown at yandex.ru>
Date: Thu, 31 Jul 2025 14:58:08 +0300
Subject: [PATCH 9/9] Update mlir/lib/Target/LLVMIR/ModuleTranslation.cpp

Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 5f46c22b1fca0..45153edd932c5 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -2284,7 +2284,7 @@ prepareLLVMModule(Operation *m, llvm::LLVMContext &llvmContext,
       return nullptr;
     }
 
-    for (auto elt : asmArrayAttr) {
+    for (Attribute elt : asmArrayAttr) {
       auto asmStrAttr = dyn_cast<StringAttr>(elt);
       if (!asmStrAttr) {
         m->emitError(



More information about the Mlir-commits mailing list