[Mlir-commits] [mlir] [MLIR][LLVMIR] Add module flags support (PR #130679)

Bruno Cardoso Lopes llvmlistbot at llvm.org
Fri Mar 14 12:07:20 PDT 2025


https://github.com/bcardosolopes updated https://github.com/llvm/llvm-project/pull/130679

>From 3a692db7b71d94757d951a1b604dbb66ec44ad8d Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Fri, 7 Mar 2025 19:37:28 -0800
Subject: [PATCH 01/18] [MLIR][LLVMIR] Add module flags support

Import and translation support.

Note that existing support (prior to this PR) already covers enough in
translation specifically to emit "Debug Info Version". Also, the debug info
version metadata is being emitted even though the imported IR has no
information and is showing up in some tests (will fix that in another PR).
---
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 25 +++++++++++
 .../mlir/Dialect/LLVMIR/LLVMDialect.td        |  1 +
 mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td | 33 +++++++++++++++
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   | 32 +++++++++++++++
 .../include/mlir/Target/LLVMIR/ModuleImport.h |  4 ++
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp    | 15 +++++++
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp        | 13 ++++++
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       | 41 +++++++++++++++++++
 mlir/test/Dialect/LLVMIR/invalid.mlir         |  7 ++++
 .../test/Dialect/LLVMIR/module-roundtrip.mlir | 16 ++++++++
 .../test/Target/LLVMIR/Import/module-flags.ll | 25 +++++++++++
 mlir/test/Target/LLVMIR/llvmir-invalid.mlir   | 14 +++++++
 mlir/test/Target/LLVMIR/llvmir.mlir           | 19 +++++++++
 13 files changed, 245 insertions(+)
 create mode 100644 mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
 create mode 100644 mlir/test/Target/LLVMIR/Import/module-flags.ll

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index d90d2ba6d6181..43d33aa5f4b2e 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1291,4 +1291,29 @@ def LLVM_DereferenceableAttr : LLVM_Attr<"Dereferenceable", "dereferenceable"> {
   let assemblyFormat = "`<` struct(params) `>`";
 }
 
+//===----------------------------------------------------------------------===//
+// ModuleFlagAttr
+//===----------------------------------------------------------------------===//
+
+def ModuleFlagAttr
+    : LLVM_Attr<"ModuleFlag", "mlir.module_flag"> {
+  let summary = "LLVM module flag metadata";
+  let description = [{
+    Represents a single entry of llvm.module.flags metadata
+    (llvm::Module::ModuleFlagEntry in LLVM). The first element is a behavior
+    flag described by `ModFlagBehaviorAttr`, the second is a string ID
+    and third is the value of the flag (currently only integer constant
+    supported).
+
+    Example:
+    ```mlir
+      #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>
+    ```
+  }];
+  let parameters = (ins "ModFlagBehaviorAttr":$behavior,
+                        "StringAttr":$key,
+                        "IntegerAttr":$value);
+  let assemblyFormat = "`<` $behavior `,` $key `,` $value `>`";
+}
+
 #endif // LLVMIR_ATTRDEFS
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
index d35f48b13b2d8..46fae44f7b0fa 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
@@ -33,6 +33,7 @@ def LLVM_Dialect : Dialect {
     static StringRef getAliasScopesAttrName() { return "alias_scopes"; }
     static StringRef getAccessGroupsAttrName() { return "access_groups"; }
     static StringRef getIdentAttrName() { return "llvm.ident"; }
+    static StringRef getModuleFlags() { return "llvm.module.flags"; }
     static StringRef getCommandlineAttrName() { return "llvm.commandline"; }
 
     /// Names of llvm parameter attributes.
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
index c08b75de03647..a9de787806452 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMEnums.td
@@ -818,4 +818,37 @@ def FPExceptionBehaviorAttr : LLVM_EnumAttr<
   let cppNamespace = "::mlir::LLVM";
 }
 
+//===----------------------------------------------------------------------===//
+// Module Flag Behavior
+//===----------------------------------------------------------------------===//
+
+// These values must match llvm::Module::ModFlagBehavior ones.
+// See llvm/include/llvm/IR/Module.h.
+def ModFlagBehaviorError
+    : LLVM_EnumAttrCase<"Error", "error", "Error", 1>;
+def ModFlagBehaviorWarning
+    : LLVM_EnumAttrCase<"Warning", "warning", "Warning", 2>;
+def ModFlagBehaviorRequire
+    : LLVM_EnumAttrCase<"Require", "require", "Require", 3>;
+def ModFlagBehaviorOverride
+    : LLVM_EnumAttrCase<"Override", "override", "Override", 4>;
+def ModFlagBehaviorAppend
+    : LLVM_EnumAttrCase<"Append", "append", "Append", 5>;
+def ModFlagBehaviorAppendUnique
+    : LLVM_EnumAttrCase<"AppendUnique", "append_unique", "AppendUnique", 6>;
+def ModFlagBehaviorMax
+    : LLVM_EnumAttrCase<"Max", "max", "Max", 7>;
+def ModFlagBehaviorMin
+    : LLVM_EnumAttrCase<"Min", "min", "Min", 8>;
+
+def ModFlagBehaviorAttr : LLVM_EnumAttr<
+    "ModFlagBehavior",
+    "::llvm::Module::ModFlagBehavior",
+    "LLVM Module Flag Behavior",
+    [ModFlagBehaviorError, ModFlagBehaviorWarning, ModFlagBehaviorRequire,
+     ModFlagBehaviorOverride, ModFlagBehaviorAppend,
+     ModFlagBehaviorAppendUnique, ModFlagBehaviorMax, ModFlagBehaviorMin]> {
+  let cppNamespace = "::mlir::LLVM";
+}
+
 #endif // LLVMIR_ENUMS
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index b27da58d484a3..413658628729d 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2183,4 +2183,36 @@ def LLVM_LinkerOptionsOp
   let hasVerifier = 1;
 }
 
+//===--------------------------------------------------------------------===//
+// ModuleFlagsOp
+//===--------------------------------------------------------------------===//
+
+def LLVM_ModuleFlagsOp
+    : LLVM_Op<"module_flags"> {
+  let summary = "Information about module properties";
+  let description = [{
+    Represents the equivalent in MLIR for LLVM's `llvm.module.flags` metadata,
+    which requires a list of metadata triplets. Each triplet entry is described
+    by a `ModuleFlagAttr`.
+
+    Example:
+    ```mlir
+    llvm.module.flags [
+      #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
+      #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>
+    ]
+    ```
+  }];
+  let arguments  = (ins ArrayAttr:$flags);
+  let assemblyFormat = [{
+    $flags attr-dict
+  }];
+
+  let llvmBuilder = [{
+    convertModuleFlagsOp($flags, builder, moduleTranslation);
+  }];
+
+  let hasVerifier = 1;
+}
+
 #endif // LLVMIR_OPS
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index a4d108e349c00..aabe01559843a 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -218,6 +218,10 @@ class ModuleImport {
   /// LLVM dialect operation.
   LogicalResult convertLinkerOptionsMetadata();
 
+  /// Converts !llvm.module.flags metadata to the XYZ
+  /// LLVM dialect operation.
+  LogicalResult convertModuleFlagsMetadata();
+
   /// Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.
   LogicalResult convertIdentMetadata();
 
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 239dcbd8c5d19..21b59b0b7e49f 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3712,6 +3712,21 @@ LogicalResult LinkerOptionsOp::verify() {
   return success();
 }
 
+//===----------------------------------------------------------------------===//
+// ModuleFlagsOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult ModuleFlagsOp::verify() {
+  if (mlir::Operation *parentOp = (*this)->getParentOp();
+      parentOp && !satisfiesLLVMModule(parentOp))
+    return emitOpError("must appear at the module level");
+  for (auto &flag : getFlags()) {
+    if (!isa<ModuleFlagAttr>(flag))
+      return emitOpError("expected a module flag attribute");
+  }
+  return success();
+}
+
 //===----------------------------------------------------------------------===//
 // InlineAsmOp
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 25599efe64322..c1df6fdd9ef34 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -270,6 +270,19 @@ static void convertLinkerOptionsOp(ArrayAttr options,
   linkerMDNode->addOperand(listMDNode);
 }
 
+static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
+                                 LLVM::ModuleTranslation &moduleTranslation) {
+  llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
+  for (Attribute attr : flags) {
+    auto flag = cast<ModuleFlagAttr>(attr);
+    auto intVal = dyn_cast<IntegerAttr>(flag.getValue());
+    assert(intVal && "expected integer attribute");
+    llvmModule->addModuleFlag(
+        (llvm::Module::ModFlagBehavior)flag.getBehavior().getValue(),
+        flag.getKey().getValue(), (uint32_t)intVal.getUInt());
+  }
+}
+
 static LogicalResult
 convertOperationImpl(Operation &opInst, llvm::IRBuilderBase &builder,
                      LLVM::ModuleTranslation &moduleTranslation) {
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index ab187cd05de75..93fdeeb3faa37 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -517,6 +517,45 @@ void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {
   debugIntrinsics.insert(intrinsic);
 }
 
+LogicalResult ModuleImport::convertModuleFlagsMetadata() {
+  SmallVector<llvm::Module::ModuleFlagEntry, 4> llvmModuleFlags;
+  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
+    if (named.getName() != LLVMDialect::getModuleFlags())
+      continue;
+    llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
+    break; // there can only be one module flags.
+  }
+
+  SmallVector<Attribute, 4> moduleFlags;
+  for (const auto [behavior, key, val] : llvmModuleFlags) {
+    // Currently only supports most common: int constant values.
+    auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
+    if (!constInt) {
+      return emitWarning(mlirModule.getLoc())
+             << "unsupported module flag value: "
+             << diagMD(val, llvmModule.get())
+             << ", only constant integer currently supported";
+    }
+    auto valAttr = builder.getIntegerAttr(
+        IntegerType::get(context, constInt->getType()->getIntegerBitWidth()),
+        constInt->getValue());
+
+    ModFlagBehaviorAttr behaviorAttr = ModFlagBehaviorAttr::get(
+        builder.getContext(), (ModFlagBehavior)behavior);
+
+    moduleFlags.push_back(
+        ModuleFlagAttr::get(builder.getContext(), behaviorAttr,
+                            builder.getStringAttr(key->getString()), valAttr));
+  }
+
+  if (!moduleFlags.empty()) {
+    builder.create<LLVM::ModuleFlagsOp>(mlirModule.getLoc(),
+                                        builder.getArrayAttr(moduleFlags));
+  }
+
+  return success();
+}
+
 LogicalResult ModuleImport::convertLinkerOptionsMetadata() {
   for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
     if (named.getName() != "llvm.linker.options")
@@ -596,6 +635,8 @@ LogicalResult ModuleImport::convertMetadata() {
   }
   if (failed(convertLinkerOptionsMetadata()))
     return failure();
+  if (failed(convertModuleFlagsMetadata()))
+    return failure();
   if (failed(convertIdentMetadata()))
     return failure();
   if (failed(convertCommandlineMetadata()))
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index fcb6ae07f4912..69c798f5e926e 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -1764,3 +1764,10 @@ llvm.mlir.alias external @y5 : i32 {
   llvm.return %0 : !llvm.ptr<4>
 }
 
+// -----
+
+module {
+  // expected-error at +2 {{invalid kind of attribute specified}}
+  // expected-error at +1 {{failed to parse ModuleFlagAttr parameter 'value' which is to be a `IntegerAttr`}}
+  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", "yolo">]
+}
diff --git a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
new file mode 100644
index 0000000000000..55b79437f1c5c
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
@@ -0,0 +1,16 @@
+// RUN: mlir-opt %s | mlir-opt | FileCheck %s
+
+module {
+  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
+                     #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+}
+
+// CHECK: llvm.module_flags [
+// CHECK-SAME: #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
+// CHECK-SAME: #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
+// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
+// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
+// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
diff --git a/mlir/test/Target/LLVMIR/Import/module-flags.ll b/mlir/test/Target/LLVMIR/Import/module-flags.ll
new file mode 100644
index 0000000000000..feff48836bba7
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/module-flags.ll
@@ -0,0 +1,25 @@
+; RUN: mlir-translate -import-llvm -split-input-file -verify-diagnostics %s | FileCheck %s
+
+!llvm.module.flags = !{!0, !1, !2, !3, !4}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 8, !"PIC Level", i32 2}
+!2 = !{i32 7, !"PIE Level", i32 2}
+!3 = !{i32 7, !"uwtable", i32 2}
+!4 = !{i32 7, !"frame-pointer", i32 1}
+
+; CHECK-LABEL: module attributes {{.*}} {
+; CHECK: llvm.module_flags [
+; CHECK-SAME: #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
+; CHECK-SAME: #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
+; CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
+; CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
+; CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+; CHECK: }
+
+; // -----
+
+!llvm.module.flags = !{!0}
+
+; expected-warning at -5{{unsupported module flag value: !"yolo_more", only constant integer currently supported}}
+!0 = !{i32 1, !"yolo", !"yolo_more"}
diff --git a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
index 15658ea606812..b973d0087ad68 100644
--- a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
@@ -348,6 +348,20 @@ llvm.func @foo() {
 
 // -----
 
+llvm.func @foo() {
+  // expected-error @below{{must appear at the module level}}
+  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>]
+}
+
+// -----
+
+module attributes {} {
+  // expected-error @below{{expected a module flag attribute}}
+  llvm.module_flags [4 : i32]
+}
+
+// -----
+
 module @does_not_exist {
   // expected-error @below{{resource does not exist}}
   llvm.mlir.global internal constant @constant(dense_resource<test0> : tensor<4xf32>) : !llvm.array<4 x f32>
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index f9473bf112387..d81b83077aa04 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2510,6 +2510,25 @@ llvm.linker_options ["/DEFAULTLIB:", "libcmtd"]
 
 // -----
 
+module {
+  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
+                     #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+}
+
+// CHECK: !llvm.module.flags = !{![[DBG:.*]], ![[WCHAR:.*]], ![[PIC:.*]], ![[PIE:.*]], ![[UWTABLE:.*]], ![[FP:.*]]}
+
+// CHECK: ![[DBG]] = !{i32 2, !"Debug Info Version", i32 3}
+// CHECK: ![[WCHAR]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: ![[PIC]] = !{i32 8, !"PIC Level", i32 2}
+// CHECK: ![[PIE]] = !{i32 7, !"PIE Level", i32 2}
+// CHECK: ![[UWTABLE]] = !{i32 7, !"uwtable", i32 2}
+// CHECK: ![[FP]] = !{i32 7, !"frame-pointer", i32 1}
+
+// -----
+
 // CHECK: @big_ = common global [4294967296 x i8] zeroinitializer
 llvm.mlir.global common @big_(dense<0> : vector<4294967296xi8>) {addr_space = 0 : i32} : !llvm.array<4294967296 x i8>
 

>From 2ae67c750014df59e7d3bd5c6681a321b0c26779 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Mon, 10 Mar 2025 17:07:49 -0700
Subject: [PATCH 02/18] Attempt to get windows bot happy

---
 mlir/test/Target/LLVMIR/llvmir.mlir | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index d81b83077aa04..518ddef149e63 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2518,14 +2518,14 @@ module {
                      #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
 }
 
-// CHECK: !llvm.module.flags = !{![[DBG:.*]], ![[WCHAR:.*]], ![[PIC:.*]], ![[PIE:.*]], ![[UWTABLE:.*]], ![[FP:.*]]}
-
-// CHECK: ![[DBG]] = !{i32 2, !"Debug Info Version", i32 3}
-// CHECK: ![[WCHAR]] = !{i32 1, !"wchar_size", i32 4}
-// CHECK: ![[PIC]] = !{i32 8, !"PIC Level", i32 2}
-// CHECK: ![[PIE]] = !{i32 7, !"PIE Level", i32 2}
-// CHECK: ![[UWTABLE]] = !{i32 7, !"uwtable", i32 2}
-// CHECK: ![[FP]] = !{i32 7, !"frame-pointer", i32 1}
+// CHECK: !llvm.module.flags = !{![[#DBG:]], ![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FP:]]}
+
+// CHECK: ![[#DBG]] = !{i32 2, !"Debug Info Version", i32 3}
+// CHECK: ![[#WCHAR]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: ![[#PIC]] = !{i32 8, !"PIC Level", i32 2}
+// CHECK: ![[#PIE]] = !{i32 7, !"PIE Level", i32 2}
+// CHECK: ![[#UWTABLE]] = !{i32 7, !"uwtable", i32 2}
+// CHECK: ![[#FP]] = !{i32 7, !"frame-pointer", i32 1}
 
 // -----
 

>From 478d3ed8d6548b98f8ff3aa39e30924dc2b6c507 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Mon, 10 Mar 2025 18:47:59 -0700
Subject: [PATCH 03/18] More attempts to massage filecheck

---
 mlir/test/Target/LLVMIR/llvmir.mlir | 38 ++++++++++++++---------------
 1 file changed, 19 insertions(+), 19 deletions(-)

diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index 518ddef149e63..dcb3fd3548697 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2510,25 +2510,6 @@ llvm.linker_options ["/DEFAULTLIB:", "libcmtd"]
 
 // -----
 
-module {
-  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
-                     #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
-}
-
-// CHECK: !llvm.module.flags = !{![[#DBG:]], ![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FP:]]}
-
-// CHECK: ![[#DBG]] = !{i32 2, !"Debug Info Version", i32 3}
-// CHECK: ![[#WCHAR]] = !{i32 1, !"wchar_size", i32 4}
-// CHECK: ![[#PIC]] = !{i32 8, !"PIC Level", i32 2}
-// CHECK: ![[#PIE]] = !{i32 7, !"PIE Level", i32 2}
-// CHECK: ![[#UWTABLE]] = !{i32 7, !"uwtable", i32 2}
-// CHECK: ![[#FP]] = !{i32 7, !"frame-pointer", i32 1}
-
-// -----
-
 // CHECK: @big_ = common global [4294967296 x i8] zeroinitializer
 llvm.mlir.global common @big_(dense<0> : vector<4294967296xi8>) {addr_space = 0 : i32} : !llvm.array<4294967296 x i8>
 
@@ -2782,3 +2763,22 @@ llvm.func @call_intrin_with_opbundle(%arg0 : !llvm.ptr) {
 // CHECK-NEXT:   call void @llvm.assume(i1 true) [ "align"(ptr %0, i32 16) ]
 // CHECK-NEXT:   ret void
 // CHECK-NEXT: }
+
+// -----
+
+module {
+  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
+                     #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
+                     #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+}
+
+// CHECK: !llvm.module.flags = !{![[#DBG:]], ![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FP:]]}
+
+// CHECK: ![[#DBG]] = !{i32 2, !"Debug Info Version", i32 3}
+// CHECK: ![[#WCHAR]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: ![[#PIC]] = !{i32 8, !"PIC Level", i32 2}
+// CHECK: ![[#PIE]] = !{i32 7, !"PIE Level", i32 2}
+// CHECK: ![[#UWTABLE]] = !{i32 7, !"uwtable", i32 2}
+// CHECK: ![[#FP]] = !{i32 7, !"frame-pointer", i32 1}

>From 216e4807da8386b88e14810184eb573a5fafdd39 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:31:35 -0700
Subject: [PATCH 04/18] Update mlir/include/mlir/Target/LLVMIR/ModuleImport.h

Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
 mlir/include/mlir/Target/LLVMIR/ModuleImport.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index aabe01559843a..b766b1710ad80 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -218,8 +218,7 @@ class ModuleImport {
   /// LLVM dialect operation.
   LogicalResult convertLinkerOptionsMetadata();
 
-  /// Converts !llvm.module.flags metadata to the XYZ
-  /// LLVM dialect operation.
+  /// Converts !llvm.module.flags metadata.
   LogicalResult convertModuleFlagsMetadata();
 
   /// Converts !llvm.ident metadata to the llvm.ident LLVM ModuleOp attribute.

>From d42630cb794d3099c2289d6f1ba13993d31f9d60 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:31:48 -0700
Subject: [PATCH 05/18] Update
 mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp

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

diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index c1df6fdd9ef34..d99bc3f137ad8 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -278,7 +278,7 @@ static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
     auto intVal = dyn_cast<IntegerAttr>(flag.getValue());
     assert(intVal && "expected integer attribute");
     llvmModule->addModuleFlag(
-        (llvm::Module::ModFlagBehavior)flag.getBehavior().getValue(),
+        static_cast<llvm::Module::ModFlagBehavior>(flag.getBehavior().getValue()),
         flag.getKey().getValue(), (uint32_t)intVal.getUInt());
   }
 }

>From 2ccacdcc201fbf009fc3a574cca4ddcd761de62c Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:32:02 -0700
Subject: [PATCH 06/18] Update mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 43d33aa5f4b2e..e3e20cf5d5823 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1312,7 +1312,7 @@ def ModuleFlagAttr
   }];
   let parameters = (ins "ModFlagBehaviorAttr":$behavior,
                         "StringAttr":$key,
-                        "IntegerAttr":$value);
+                        "uint32_t":$value);
   let assemblyFormat = "`<` $behavior `,` $key `,` $value `>`";
 }
 

>From eb04bec598235a6c68eb1fbc62d010f89ec8269c Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:32:17 -0700
Subject: [PATCH 07/18] Update mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Co-authored-by: Tobias Gysi <tobias.gysi at nextsilicon.com>
---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index e3e20cf5d5823..ce5349a854ef3 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1310,7 +1310,7 @@ def ModuleFlagAttr
       #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>
     ```
   }];
-  let parameters = (ins "ModFlagBehaviorAttr":$behavior,
+  let parameters = (ins "ModFlagBehavior":$behavior,
                         "StringAttr":$key,
                         "uint32_t":$value);
   let assemblyFormat = "`<` $behavior `,` $key `,` $value `>`";

>From f1e4de8c43e13e8253f2c84d9f2de24b51889d6b Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:32:34 -0700
Subject: [PATCH 08/18] Update
 mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp

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

diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index d99bc3f137ad8..f29b08b4f79d9 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -273,7 +273,7 @@ static void convertLinkerOptionsOp(ArrayAttr options,
 static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
                                  LLVM::ModuleTranslation &moduleTranslation) {
   llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
-  for (Attribute attr : flags) {
+  for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
     auto flag = cast<ModuleFlagAttr>(attr);
     auto intVal = dyn_cast<IntegerAttr>(flag.getValue());
     assert(intVal && "expected integer attribute");

>From e9565c6f9ecc69a8446dd2f1cb832e41da4abca7 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:32:58 -0700
Subject: [PATCH 09/18] Update mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Co-authored-by: Henrich Lauko <xlauko at mail.muni.cz>
---
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 21b59b0b7e49f..2154293d63cca 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3717,7 +3717,7 @@ LogicalResult LinkerOptionsOp::verify() {
 //===----------------------------------------------------------------------===//
 
 LogicalResult ModuleFlagsOp::verify() {
-  if (mlir::Operation *parentOp = (*this)->getParentOp();
+  if (Operation *parentOp = (*this)->getParentOp();
       parentOp && !satisfiesLLVMModule(parentOp))
     return emitOpError("must appear at the module level");
   for (auto &flag : getFlags()) {

>From bef17f7837db5e070a5b43056b7f87642a5f7f22 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:33:07 -0700
Subject: [PATCH 10/18] Update mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Co-authored-by: Henrich Lauko <xlauko at mail.muni.cz>
---
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 2154293d63cca..dd46a061e5b4c 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3720,7 +3720,7 @@ LogicalResult ModuleFlagsOp::verify() {
   if (Operation *parentOp = (*this)->getParentOp();
       parentOp && !satisfiesLLVMModule(parentOp))
     return emitOpError("must appear at the module level");
-  for (auto &flag : getFlags()) {
+  for (Attribute flag : getFlags()) {
     if (!isa<ModuleFlagAttr>(flag))
       return emitOpError("expected a module flag attribute");
   }

>From 0a791e7a6cc6c1f13d23439c6a76d6787b31c02f Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Tue, 11 Mar 2025 11:34:18 -0700
Subject: [PATCH 11/18] Update mlir/lib/Target/LLVMIR/ModuleImport.cpp

Co-authored-by: Henrich Lauko <xlauko at mail.muni.cz>
---
 mlir/lib/Target/LLVMIR/ModuleImport.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 93fdeeb3faa37..72de7af0425cc 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -544,8 +544,8 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() {
         builder.getContext(), (ModFlagBehavior)behavior);
 
     moduleFlags.push_back(
-        ModuleFlagAttr::get(builder.getContext(), behaviorAttr,
-                            builder.getStringAttr(key->getString()), valAttr));
+        builder.getAttr<ModuleFlagAttr>(behaviorAttr, builder.getStringAttr(key->getString()),
+                                                                valAttr));
   }
 
   if (!moduleFlags.empty()) {

>From 02b854d87b31ddae3217fa0d275691efaca0c6cb Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 13 Mar 2025 16:04:04 -0700
Subject: [PATCH 12/18] Fix several review issues

---
 .../LLVMIR/LLVMToLLVMIRTranslation.cpp        | 10 +++-------
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       | 16 +++++++--------
 mlir/test/Dialect/LLVMIR/invalid.mlir         |  6 +++---
 .../test/Dialect/LLVMIR/module-roundtrip.mlir | 20 +++++++++----------
 .../test/Target/LLVMIR/Import/module-flags.ll | 10 +++++-----
 mlir/test/Target/LLVMIR/llvmir-invalid.mlir   |  2 +-
 mlir/test/Target/LLVMIR/llvmir.mlir           | 10 +++++-----
 mlir/test/mlir-translate/split-markers.mlir   |  2 ++
 8 files changed, 37 insertions(+), 39 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index f29b08b4f79d9..6a9e35d5ec1d4 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -273,14 +273,10 @@ static void convertLinkerOptionsOp(ArrayAttr options,
 static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
                                  LLVM::ModuleTranslation &moduleTranslation) {
   llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
-  for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>()) {
-    auto flag = cast<ModuleFlagAttr>(attr);
-    auto intVal = dyn_cast<IntegerAttr>(flag.getValue());
-    assert(intVal && "expected integer attribute");
+  for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>())
     llvmModule->addModuleFlag(
-        static_cast<llvm::Module::ModFlagBehavior>(flag.getBehavior().getValue()),
-        flag.getKey().getValue(), (uint32_t)intVal.getUInt());
-  }
+        static_cast<llvm::Module::ModFlagBehavior>(flagAttr.getBehavior()),
+        flagAttr.getKey().getValue(), flagAttr.getValue());
 }
 
 static LogicalResult
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 72de7af0425cc..10efc5152ca9d 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -536,16 +536,16 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() {
              << diagMD(val, llvmModule.get())
              << ", only constant integer currently supported";
     }
-    auto valAttr = builder.getIntegerAttr(
-        IntegerType::get(context, constInt->getType()->getIntegerBitWidth()),
-        constInt->getValue());
+    // auto valAttr = builder.getIntegerAttr(
+    //     IntegerType::get(context, constInt->getType()->getIntegerBitWidth()),
+    //     constInt->getValue());
 
-    ModFlagBehaviorAttr behaviorAttr = ModFlagBehaviorAttr::get(
-        builder.getContext(), (ModFlagBehavior)behavior);
+    // ModFlagBehaviorAttr behaviorAttr = ModFlagBehaviorAttr::get(
+    //     builder.getContext(), (ModFlagBehavior)behavior);
 
-    moduleFlags.push_back(
-        builder.getAttr<ModuleFlagAttr>(behaviorAttr, builder.getStringAttr(key->getString()),
-                                                                valAttr));
+    moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
+        (ModFlagBehavior)behavior, builder.getStringAttr(key->getString()),
+        constInt->getZExtValue()));
   }
 
   if (!moduleFlags.empty()) {
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index 69c798f5e926e..6d3d3937b651c 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -1767,7 +1767,7 @@ llvm.mlir.alias external @y5 : i32 {
 // -----
 
 module {
-  // expected-error at +2 {{invalid kind of attribute specified}}
-  // expected-error at +1 {{failed to parse ModuleFlagAttr parameter 'value' which is to be a `IntegerAttr`}}
-  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", "yolo">]
+  // expected-error at +2 {{expected integer value}}
+  // expected-error at +1 {{failed to parse ModuleFlagAttr parameter 'value' which is to be a `uint32_t`}}
+  llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", "yolo">]
 }
diff --git a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
index 55b79437f1c5c..d99a93c1e8565 100644
--- a/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
+++ b/mlir/test/Dialect/LLVMIR/module-roundtrip.mlir
@@ -1,16 +1,16 @@
 // RUN: mlir-opt %s | mlir-opt | FileCheck %s
 
 module {
-  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
-                     #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+  llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>,
+                     #llvm.mlir.module_flag<min, "PIC Level", 2>,
+                     #llvm.mlir.module_flag<max, "PIE Level", 2>,
+                     #llvm.mlir.module_flag<max, "uwtable", 2>,
+                     #llvm.mlir.module_flag<max, "frame-pointer", 1>]
 }
 
 // CHECK: llvm.module_flags [
-// CHECK-SAME: #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
-// CHECK-SAME: #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
-// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
-// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
-// CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+// CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4>,
+// CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2>,
+// CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2>,
+// CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2>,
+// CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1>]
diff --git a/mlir/test/Target/LLVMIR/Import/module-flags.ll b/mlir/test/Target/LLVMIR/Import/module-flags.ll
index feff48836bba7..b7b686f94c7f4 100644
--- a/mlir/test/Target/LLVMIR/Import/module-flags.ll
+++ b/mlir/test/Target/LLVMIR/Import/module-flags.ll
@@ -10,11 +10,11 @@
 
 ; CHECK-LABEL: module attributes {{.*}} {
 ; CHECK: llvm.module_flags [
-; CHECK-SAME: #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
-; CHECK-SAME: #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
-; CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
-; CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
-; CHECK-SAME: #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+; CHECK-SAME: #llvm.mlir.module_flag<error, "wchar_size", 4>,
+; CHECK-SAME: #llvm.mlir.module_flag<min, "PIC Level", 2>,
+; CHECK-SAME: #llvm.mlir.module_flag<max, "PIE Level", 2>,
+; CHECK-SAME: #llvm.mlir.module_flag<max, "uwtable", 2>,
+; CHECK-SAME: #llvm.mlir.module_flag<max, "frame-pointer", 1>]
 ; CHECK: }
 
 ; // -----
diff --git a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
index b973d0087ad68..f755c4e508c22 100644
--- a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
@@ -350,7 +350,7 @@ llvm.func @foo() {
 
 llvm.func @foo() {
   // expected-error @below{{must appear at the module level}}
-  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>]
+  llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>]
 }
 
 // -----
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index dcb3fd3548697..ce2225769d3b8 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2767,11 +2767,11 @@ llvm.func @call_intrin_with_opbundle(%arg0 : !llvm.ptr) {
 // -----
 
 module {
-  llvm.module_flags [#llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
-                     #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "PIE Level", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "uwtable", 2 : i32>,
-                     #llvm.mlir.module_flag<7 : i64, "frame-pointer", 1 : i32>]
+  llvm.module_flags [#llvm.mlir.module_flag<error, "wchar_size", 4>,
+                     #llvm.mlir.module_flag<min, "PIC Level", 2>,
+                     #llvm.mlir.module_flag<max, "PIE Level", 2>,
+                     #llvm.mlir.module_flag<max, "uwtable", 2>,
+                     #llvm.mlir.module_flag<max, "frame-pointer", 1>]
 }
 
 // CHECK: !llvm.module.flags = !{![[#DBG:]], ![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FP:]]}
diff --git a/mlir/test/mlir-translate/split-markers.mlir b/mlir/test/mlir-translate/split-markers.mlir
index ed576bcd85236..cf950eb12ec5a 100644
--- a/mlir/test/mlir-translate/split-markers.mlir
+++ b/mlir/test/mlir-translate/split-markers.mlir
@@ -21,6 +21,8 @@
 // CHECK-OUTPUT-NEXT: ModuleID
 
 // CHECK-ROUNDTRIP:       module {{.*}} {
+// FIXME: importer forces debug info version even without importing one.
+// CHECK-ROUNDTRIP-NEXT:    llvm.module_flag
 // CHECK-ROUNDTRIP-NEXT:  }
 // CHECK-ROUNDTRIP-EMPTY:
 // CHECK-ROUNDTRIP:       module

>From 62c1e4300092f68b16aa8541ed7a1e9b4349619e Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 13 Mar 2025 16:06:50 -0700
Subject: [PATCH 13/18] Improve tablegen docs

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index ce5349a854ef3..dced9e17dd517 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1307,7 +1307,7 @@ def ModuleFlagAttr
 
     Example:
     ```mlir
-      #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>
+      #llvm.mlir.module_flag<error, "wchar_size", 4>
     ```
   }];
   let parameters = (ins "ModFlagBehavior":$behavior,

>From 2665e611289e6ceaebfb7f8b1dbc7851689d29f1 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 13 Mar 2025 16:18:49 -0700
Subject: [PATCH 14/18] Use convertModFlagBehaviorFromLLVM

---
 mlir/lib/Target/LLVMIR/ModuleImport.cpp | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 10efc5152ca9d..66961f741b9d8 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -530,28 +530,20 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() {
   for (const auto [behavior, key, val] : llvmModuleFlags) {
     // Currently only supports most common: int constant values.
     auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
-    if (!constInt) {
+    if (!constInt)
       return emitWarning(mlirModule.getLoc())
              << "unsupported module flag value: "
              << diagMD(val, llvmModule.get())
              << ", only constant integer currently supported";
-    }
-    // auto valAttr = builder.getIntegerAttr(
-    //     IntegerType::get(context, constInt->getType()->getIntegerBitWidth()),
-    //     constInt->getValue());
-
-    // ModFlagBehaviorAttr behaviorAttr = ModFlagBehaviorAttr::get(
-    //     builder.getContext(), (ModFlagBehavior)behavior);
 
     moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
-        (ModFlagBehavior)behavior, builder.getStringAttr(key->getString()),
-        constInt->getZExtValue()));
+        convertModFlagBehaviorFromLLVM(behavior),
+        builder.getStringAttr(key->getString()), constInt->getZExtValue()));
   }
 
-  if (!moduleFlags.empty()) {
+  if (!moduleFlags.empty())
     builder.create<LLVM::ModuleFlagsOp>(mlirModule.getLoc(),
                                         builder.getArrayAttr(moduleFlags));
-  }
 
   return success();
 }

>From ddb49f96799efbe0945df2bd91afc5b9bb7ebb6d Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 13 Mar 2025 16:20:09 -0700
Subject: [PATCH 15/18] Use convertModFlagBehaviorToLLVM

---
 .../Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
index 6a9e35d5ec1d4..833b19c1bece2 100644
--- a/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/Dialect/LLVMIR/LLVMToLLVMIRTranslation.cpp
@@ -275,7 +275,7 @@ static void convertModuleFlagsOp(ArrayAttr flags, llvm::IRBuilderBase &builder,
   llvm::Module *llvmModule = moduleTranslation.getLLVMModule();
   for (auto flagAttr : flags.getAsRange<ModuleFlagAttr>())
     llvmModule->addModuleFlag(
-        static_cast<llvm::Module::ModFlagBehavior>(flagAttr.getBehavior()),
+        convertModFlagBehaviorToLLVM(flagAttr.getBehavior()),
         flagAttr.getKey().getValue(), flagAttr.getValue());
 }
 

>From 3f347a7e6f5e4259e2d552d4b162b15f9956decc Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 13 Mar 2025 16:21:48 -0700
Subject: [PATCH 16/18] Update more comments

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 413658628729d..90cc851c0a3b2 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -2198,8 +2198,8 @@ def LLVM_ModuleFlagsOp
     Example:
     ```mlir
     llvm.module.flags [
-      #llvm.mlir.module_flag<1 : i64, "wchar_size", 4 : i32>,
-      #llvm.mlir.module_flag<8 : i64, "PIC Level", 2 : i32>
+      #llvm.mlir.module_flag<error, "wchar_size", 4>,
+      #llvm.mlir.module_flag<max, "PIC Level", 2>
     ]
     ```
   }];

>From 708cda8a07b40c0feaf68127060f63f908683bee Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Thu, 13 Mar 2025 19:31:36 -0700
Subject: [PATCH 17/18] Procude as much warnings as possible

---
 mlir/lib/Target/LLVMIR/ModuleImport.cpp | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 66961f741b9d8..d375f62337830 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -530,11 +530,12 @@ LogicalResult ModuleImport::convertModuleFlagsMetadata() {
   for (const auto [behavior, key, val] : llvmModuleFlags) {
     // Currently only supports most common: int constant values.
     auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
-    if (!constInt)
-      return emitWarning(mlirModule.getLoc())
-             << "unsupported module flag value: "
-             << diagMD(val, llvmModule.get())
-             << ", only constant integer currently supported";
+    if (!constInt) {
+      emitWarning(mlirModule.getLoc())
+          << "unsupported module flag value: " << diagMD(val, llvmModule.get())
+          << ", only constant integer currently supported";
+      continue;
+    }
 
     moduleFlags.push_back(builder.getAttr<ModuleFlagAttr>(
         convertModFlagBehaviorFromLLVM(behavior),

>From 220fa4a967753c672effd8b2fa5457e1e32a4bc7 Mon Sep 17 00:00:00 2001
From: Bruno Cardoso Lopes <bruno.cardoso at gmail.com>
Date: Fri, 14 Mar 2025 11:44:35 -0700
Subject: [PATCH 18/18] Address review

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td |  4 ++--
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp       |  3 +--
 mlir/lib/Target/LLVMIR/ModuleImport.cpp          | 11 +++--------
 mlir/test/Target/LLVMIR/llvmir.mlir              |  4 ++--
 4 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index dced9e17dd517..ede9f2d365b20 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1302,8 +1302,8 @@ def ModuleFlagAttr
     Represents a single entry of llvm.module.flags metadata
     (llvm::Module::ModuleFlagEntry in LLVM). The first element is a behavior
     flag described by `ModFlagBehaviorAttr`, the second is a string ID
-    and third is the value of the flag (currently only integer constant
-    supported).
+    and third is the value of the flag (currently only integer constants
+    are supported).
 
     Example:
     ```mlir
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index dd46a061e5b4c..5370de501a85c 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -3720,10 +3720,9 @@ LogicalResult ModuleFlagsOp::verify() {
   if (Operation *parentOp = (*this)->getParentOp();
       parentOp && !satisfiesLLVMModule(parentOp))
     return emitOpError("must appear at the module level");
-  for (Attribute flag : getFlags()) {
+  for (Attribute flag : getFlags())
     if (!isa<ModuleFlagAttr>(flag))
       return emitOpError("expected a module flag attribute");
-  }
   return success();
 }
 
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index d375f62337830..663cad7d3cd24 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -518,15 +518,10 @@ void ModuleImport::addDebugIntrinsic(llvm::CallInst *intrinsic) {
 }
 
 LogicalResult ModuleImport::convertModuleFlagsMetadata() {
-  SmallVector<llvm::Module::ModuleFlagEntry, 4> llvmModuleFlags;
-  for (const llvm::NamedMDNode &named : llvmModule->named_metadata()) {
-    if (named.getName() != LLVMDialect::getModuleFlags())
-      continue;
-    llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
-    break; // there can only be one module flags.
-  }
+  SmallVector<llvm::Module::ModuleFlagEntry> llvmModuleFlags;
+  llvmModule->getModuleFlagsMetadata(llvmModuleFlags);
 
-  SmallVector<Attribute, 4> moduleFlags;
+  SmallVector<Attribute> moduleFlags;
   for (const auto [behavior, key, val] : llvmModuleFlags) {
     // Currently only supports most common: int constant values.
     auto *constInt = llvm::mdconst::dyn_extract<llvm::ConstantInt>(val);
diff --git a/mlir/test/Target/LLVMIR/llvmir.mlir b/mlir/test/Target/LLVMIR/llvmir.mlir
index ce2225769d3b8..ca06b26b03409 100644
--- a/mlir/test/Target/LLVMIR/llvmir.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir.mlir
@@ -2774,11 +2774,11 @@ module {
                      #llvm.mlir.module_flag<max, "frame-pointer", 1>]
 }
 
-// CHECK: !llvm.module.flags = !{![[#DBG:]], ![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FP:]]}
+// CHECK: !llvm.module.flags = !{![[#DBG:]], ![[#WCHAR:]], ![[#PIC:]], ![[#PIE:]], ![[#UWTABLE:]], ![[#FrameP:]]}
 
 // CHECK: ![[#DBG]] = !{i32 2, !"Debug Info Version", i32 3}
 // CHECK: ![[#WCHAR]] = !{i32 1, !"wchar_size", i32 4}
 // CHECK: ![[#PIC]] = !{i32 8, !"PIC Level", i32 2}
 // CHECK: ![[#PIE]] = !{i32 7, !"PIE Level", i32 2}
 // CHECK: ![[#UWTABLE]] = !{i32 7, !"uwtable", i32 2}
-// CHECK: ![[#FP]] = !{i32 7, !"frame-pointer", i32 1}
+// CHECK: ![[#FrameP]] = !{i32 7, !"frame-pointer", i32 1}



More information about the Mlir-commits mailing list