[Mlir-commits] [mlir] [MLIR][LLVM] Model llvm.module_asm instruction (PR #151996)

Morris Hafner llvmlistbot at llvm.org
Mon Aug 4 09:27:21 PDT 2025


https://github.com/mmha created https://github.com/llvm/llvm-project/pull/151996

This patch adds a new llvm.module_asm operator which models LLVM's `module asm` blocks. It provides translation to LLVM IR but does not check for the validity of asm_string.

>From b00351c4a436525842cc0c954adae3acd47194e0 Mon Sep 17 00:00:00 2001
From: Morris Hafner <mhafner at nvidia.com>
Date: Mon, 4 Aug 2025 18:08:33 +0200
Subject: [PATCH] [MLIR][LLVM] Model llvm.module_asm instruction

This patch adds a new llvm.module_asm operator which models LLVM's `module asm` blocks. It provides translation to LLVM IR but does not check for the validity of asm_string.
---
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   | 23 +++++++++++++++++++
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp        |  6 +++++
 mlir/test/Dialect/LLVMIR/canonicalize.mlir    |  8 +++++++
 mlir/test/Target/LLVMIR/llvmir.mlir           |  9 ++++++++
 4 files changed, 46 insertions(+)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 3f27f6d9ae8b7..b9c138c70a940 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2399,6 +2399,29 @@ def LLVM_InlineAsmOp : LLVM_Op<"inline_asm", [DeclareOpInterfaceMethods<MemoryEf
   let hasVerifier = 1;
 }
 
+def LLVM_ModuleAsmOp : LLVM_Op<"module_asm"> {
+  let description = [{
+    The ModuleAsmOp mirrors the underlying LLVM "module asm" semantics, 
+    allowing target-specific assembly code to be embedded at module level.
+    
+    Module asm blocks are concatenated and emitted outside of any function,
+    corresponding to GCC's file scope inline assembly. The assembly string
+    must be parseable by LLVM's integrated assembler and can reference 
+    module-level symbols but not local variables.
+
+    Example:
+    ```
+    llvm.module_asm "my_function: ret"
+    llvm.module_asm ".globl my_symbol"
+    ```
+  }];
+  let arguments = (ins StrAttr:$asm_string);
+
+  let assemblyFormat = [{
+    attr-dict $asm_string
+   }];
+}
+
 //===--------------------------------------------------------------------===//
 // CallIntrinsicOp
 //===--------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 0f675a0a5df5d..3b91fcab9a926 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -505,6 +505,12 @@ convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
     return success();
   }
 
+  if (auto moduleAsmOp = dyn_cast<LLVM::ModuleAsmOp>(opInst)) {
+    moduleTranslation.getLLVMModule()->appendModuleInlineAsm(
+        moduleAsmOp.getAsmString());
+    return success();
+  }
+
   if (auto invOp = dyn_cast<LLVM::InvokeOp>(opInst)) {
     auto operands = moduleTranslation.lookupValues(invOp.getCalleeOperands());
     SmallVector<llvm::OperandBundleDef> opBundles =
diff --git a/mlir/test/Dialect/LLVMIR/canonicalize.mlir b/mlir/test/Dialect/LLVMIR/canonicalize.mlir
index 8accf6e263863..326058884500b 100644
--- a/mlir/test/Dialect/LLVMIR/canonicalize.mlir
+++ b/mlir/test/Dialect/LLVMIR/canonicalize.mlir
@@ -307,3 +307,11 @@ llvm.func @inline_asm_side_effects(%x : i32) {
   llvm.inline_asm has_side_effects "inline asm with side effects", "r" %x : (i32) -> ()
   llvm.return
 }
+
+// -----
+
+// CHECK-LABEL: llvm.module_asm
+// CHECK-SAME: ".global some_symbol"
+// CHECK-NEXT: llvm.module_asm ".global another_symbol"
+llvm.module_asm ".global some_symbol"
+llvm.module_asm ".global another_symbol"
\ No newline at end of file
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index fc1993b50ba2d..a4c301c12b3b0 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2088,6 +2088,15 @@ llvm.func @useInlineAsm2(%arg0: !llvm.ptr, %arg1: i64, %arg2: !llvm.ptr, %arg3:
 
 // -----
 
+module {
+  // CHECK: module asm ".global file_scope_asm_symbol"
+  // CHECK-NEXT: module asm "some_asm_label:"
+  llvm.module_asm ".global file_scope_asm_symbol"
+  llvm.module_asm "some_asm_label:"
+}
+
+// -----
+
 llvm.func @fastmathFlagsFunc(f32) -> f32
 
 // CHECK-LABEL: @fastmathFlags



More information about the Mlir-commits mailing list