Skip to content

[MLIR][LLVM] Add import-structs-as-literals flag to the IR import #140098

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 16, 2025

Conversation

Dinistro
Copy link
Contributor

This commit introduces the import-structs-as-literals option to the MLIR import. This ensures that all struct types are imported as literal structs, even when they are named in LLVM IR.

This commit introduces the `import-structs-as-literals` option to the
MLIR import. This ensures that all struct types are imported as literal
structs, even when they are named in LLVM IR.
@Dinistro Dinistro requested a review from gysit May 15, 2025 16:26
Copy link
Contributor

@gysit gysit left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Dinistro Dinistro marked this pull request as ready for review May 16, 2025 06:32
@llvmbot
Copy link
Member

llvmbot commented May 16, 2025

@llvm/pr-subscribers-mlir-llvm

@llvm/pr-subscribers-mlir

Author: Christian Ulmann (Dinistro)

Changes

This commit introduces the import-structs-as-literals option to the MLIR import. This ensures that all struct types are imported as literal structs, even when they are named in LLVM IR.


Full diff: https://github.com/llvm/llvm-project/pull/140098.diff

7 Files Affected:

  • (modified) mlir/include/mlir/Target/LLVMIR/Import.h (+5-1)
  • (modified) mlir/include/mlir/Target/LLVMIR/ModuleImport.h (+1-1)
  • (modified) mlir/include/mlir/Target/LLVMIR/TypeFromLLVM.h (+2-3)
  • (modified) mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp (+7-1)
  • (modified) mlir/lib/Target/LLVMIR/ModuleImport.cpp (+7-4)
  • (modified) mlir/lib/Target/LLVMIR/TypeFromLLVM.cpp (+13-6)
  • (added) mlir/test/Target/LLVMIR/Import/import-structs-as-literals.ll (+13)
diff --git a/mlir/include/mlir/Target/LLVMIR/Import.h b/mlir/include/mlir/Target/LLVMIR/Import.h
index c6181243a06b0..458361842ec81 100644
--- a/mlir/include/mlir/Target/LLVMIR/Import.h
+++ b/mlir/include/mlir/Target/LLVMIR/Import.h
@@ -46,10 +46,14 @@ class ModuleOp;
 /// registered an explicit intrinsic operation. Warning: passes that rely on
 /// matching explicit intrinsic operations may not work properly if this flag is
 /// enabled.
+/// The `importStructsAsLiterals` flag (default off) ensures that all structs
+/// are imported as literal structs, even when they are named in the LLVM
+/// module.
 OwningOpRef<ModuleOp> translateLLVMIRToModule(
     std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,
     bool emitExpensiveWarnings = true, bool dropDICompositeTypeElements = false,
-    bool loadAllDialects = true, bool preferUnregisteredIntrinsics = false);
+    bool loadAllDialects = true, bool preferUnregisteredIntrinsics = false,
+    bool importStructsAsLiterals = false);
 
 /// Translate the given LLVM data layout into an MLIR equivalent using the DLTI
 /// dialect.
diff --git a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
index 568dc00b3bb97..a5b38299d07b2 100644
--- a/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
+++ b/mlir/include/mlir/Target/LLVMIR/ModuleImport.h
@@ -48,7 +48,7 @@ class ModuleImport {
 public:
   ModuleImport(ModuleOp mlirModule, std::unique_ptr<llvm::Module> llvmModule,
                bool emitExpensiveWarnings, bool importEmptyDICompositeTypes,
-               bool preferUnregisteredIntrinsics);
+               bool preferUnregisteredIntrinsics, bool importStructsAsLiterals);
 
   /// Calls the LLVMImportInterface initialization that queries the registered
   /// dialect interfaces for the supported LLVM IR intrinsics and metadata kinds
diff --git a/mlir/include/mlir/Target/LLVMIR/TypeFromLLVM.h b/mlir/include/mlir/Target/LLVMIR/TypeFromLLVM.h
index 9bb56ee358b8c..0a519534128d6 100644
--- a/mlir/include/mlir/Target/LLVMIR/TypeFromLLVM.h
+++ b/mlir/include/mlir/Target/LLVMIR/TypeFromLLVM.h
@@ -17,8 +17,6 @@
 #include <memory>
 
 namespace llvm {
-class DataLayout;
-class LLVMContext;
 class Type;
 } // namespace llvm
 
@@ -38,7 +36,8 @@ class TypeFromLLVMIRTranslatorImpl;
 /// reused across translations.
 class TypeFromLLVMIRTranslator {
 public:
-  TypeFromLLVMIRTranslator(MLIRContext &context);
+  TypeFromLLVMIRTranslator(MLIRContext &context,
+                           bool importStructsAsLiterals = false);
   ~TypeFromLLVMIRTranslator();
 
   /// Translates the given LLVM IR type to the MLIR LLVM dialect.
diff --git a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
index b21db4aa18284..187e2a9b75a9b 100644
--- a/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
+++ b/mlir/lib/Target/LLVMIR/ConvertFromLLVMIR.cpp
@@ -44,6 +44,12 @@ void registerFromLLVMIRTranslation() {
           "of using dialect supported intrinsics"),
       llvm::cl::init(false));
 
+  static llvm::cl::opt<bool> importStructsAsLiterals(
+      "import-structs-as-literals",
+      llvm::cl::desc("Controls if structs should be imported as literal "
+                     "structs, i.e., nameless structs."),
+      llvm::cl::init(false));
+
   TranslateToMLIRRegistration registration(
       "import-llvm", "Translate LLVMIR to MLIR",
       [](llvm::SourceMgr &sourceMgr,
@@ -70,7 +76,7 @@ void registerFromLLVMIRTranslation() {
         return translateLLVMIRToModule(
             std::move(llvmModule), context, emitExpensiveWarnings,
             dropDICompositeTypeElements, /*loadAllDialects=*/true,
-            preferUnregisteredIntrinsics);
+            preferUnregisteredIntrinsics, importStructsAsLiterals);
       },
       [](DialectRegistry &registry) {
         // Register the DLTI dialect used to express the data layout
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 77094d4b75f38..8a3e47d29c258 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -164,11 +164,12 @@ ModuleImport::ModuleImport(ModuleOp mlirModule,
                            std::unique_ptr<llvm::Module> llvmModule,
                            bool emitExpensiveWarnings,
                            bool importEmptyDICompositeTypes,
-                           bool preferUnregisteredIntrinsics)
+                           bool preferUnregisteredIntrinsics,
+                           bool importStructsAsLiterals)
     : builder(mlirModule->getContext()), context(mlirModule->getContext()),
       mlirModule(mlirModule), llvmModule(std::move(llvmModule)),
       iface(mlirModule->getContext()),
-      typeTranslator(*mlirModule->getContext()),
+      typeTranslator(*mlirModule->getContext(), importStructsAsLiterals),
       debugImporter(std::make_unique<DebugImporter>(
           mlirModule, importEmptyDICompositeTypes)),
       loopAnnotationImporter(
@@ -3080,7 +3081,8 @@ ModuleImport::translateDereferenceableAttr(const llvm::MDNode *node,
 OwningOpRef<ModuleOp> mlir::translateLLVMIRToModule(
     std::unique_ptr<llvm::Module> llvmModule, MLIRContext *context,
     bool emitExpensiveWarnings, bool dropDICompositeTypeElements,
-    bool loadAllDialects, bool preferUnregisteredIntrinsics) {
+    bool loadAllDialects, bool preferUnregisteredIntrinsics,
+    bool importStructsAsLiterals) {
   // Preload all registered dialects to allow the import to iterate the
   // registered LLVMImportDialectInterface implementations and query the
   // supported LLVM IR constructs before starting the translation. Assumes the
@@ -3098,7 +3100,8 @@ OwningOpRef<ModuleOp> mlir::translateLLVMIRToModule(
 
   ModuleImport moduleImport(module.get(), std::move(llvmModule),
                             emitExpensiveWarnings, dropDICompositeTypeElements,
-                            preferUnregisteredIntrinsics);
+                            preferUnregisteredIntrinsics,
+                            importStructsAsLiterals);
   if (failed(moduleImport.initializeImportInterface()))
     return {};
   if (failed(moduleImport.convertDataLayout()))
diff --git a/mlir/lib/Target/LLVMIR/TypeFromLLVM.cpp b/mlir/lib/Target/LLVMIR/TypeFromLLVM.cpp
index c46aa3e80d51a..5d9345d707a44 100644
--- a/mlir/lib/Target/LLVMIR/TypeFromLLVM.cpp
+++ b/mlir/lib/Target/LLVMIR/TypeFromLLVM.cpp
@@ -12,7 +12,6 @@
 #include "mlir/IR/MLIRContext.h"
 
 #include "llvm/ADT/TypeSwitch.h"
-#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Type.h"
 
@@ -25,7 +24,9 @@ namespace detail {
 class TypeFromLLVMIRTranslatorImpl {
 public:
   /// Constructs a class creating types in the given MLIR context.
-  TypeFromLLVMIRTranslatorImpl(MLIRContext &context) : context(context) {}
+  TypeFromLLVMIRTranslatorImpl(MLIRContext &context,
+                               bool importStructsAsLiterals)
+      : context(context), importStructsAsLiterals(importStructsAsLiterals) {}
 
   /// Translates the given type.
   Type translateType(llvm::Type *type) {
@@ -103,7 +104,7 @@ class TypeFromLLVMIRTranslatorImpl {
   /// Translates the given structure type.
   Type translate(llvm::StructType *type) {
     SmallVector<Type, 8> subtypes;
-    if (type->isLiteral()) {
+    if (type->isLiteral() || importStructsAsLiterals) {
       translateTypes(type->subtypes(), subtypes);
       return LLVM::LLVMStructType::getLiteral(&context, subtypes,
                                               type->isPacked());
@@ -132,7 +133,7 @@ class TypeFromLLVMIRTranslatorImpl {
   Type translate(llvm::ScalableVectorType *type) {
     return VectorType::get(type->getMinNumElements(),
                            translateType(type->getElementType()),
-                           /*scalable=*/true);
+                           /*scalableDims=*/true);
   }
 
   /// Translates the given target extension type.
@@ -158,14 +159,20 @@ class TypeFromLLVMIRTranslatorImpl {
 
   /// The context in which MLIR types are created.
   MLIRContext &context;
+
+  /// Controls if structs should be imported as literal structs, i.e., nameless
+  /// structs.
+  bool importStructsAsLiterals;
 };
 
 } // namespace detail
 } // namespace LLVM
 } // namespace mlir
 
-LLVM::TypeFromLLVMIRTranslator::TypeFromLLVMIRTranslator(MLIRContext &context)
-    : impl(new detail::TypeFromLLVMIRTranslatorImpl(context)) {}
+LLVM::TypeFromLLVMIRTranslator::TypeFromLLVMIRTranslator(
+    MLIRContext &context, bool importStructsAsLiterals)
+    : impl(std::make_unique<detail::TypeFromLLVMIRTranslatorImpl>(
+          context, importStructsAsLiterals)) {}
 
 LLVM::TypeFromLLVMIRTranslator::~TypeFromLLVMIRTranslator() = default;
 
diff --git a/mlir/test/Target/LLVMIR/Import/import-structs-as-literals.ll b/mlir/test/Target/LLVMIR/Import/import-structs-as-literals.ll
new file mode 100644
index 0000000000000..40fd834817d04
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/import-structs-as-literals.ll
@@ -0,0 +1,13 @@
+; RUN: mlir-translate -import-llvm -import-structs-as-literals -split-input-file %s | FileCheck %s
+
+%named = type {i32, i8, i16, i32}
+
+; CHECK: @named
+; CHECK-SAME: !llvm.struct<(i32, i8, i16, i32)>
+@named = external global %named
+
+%opaque = type opaque
+
+; CHECK: @opaque
+; CHECK-SAME: !llvm.struct<()>
+@opaque = external global %opaque

@Dinistro Dinistro merged commit 1001d6a into main May 16, 2025
16 checks passed
@Dinistro Dinistro deleted the users/dinistro/add-literal-struct-import-flag branch May 16, 2025 06:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants