[flang-commits] [flang] [mlir] [MLIR][LLVMIR][DLTI] Add `LLVM::TargetAttrInterface` and `#llvm.target` attr (PR #145899)

Rolf Morel via flang-commits flang-commits at lists.llvm.org
Wed Aug 20 12:21:34 PDT 2025


https://github.com/rolfmorel updated https://github.com/llvm/llvm-project/pull/145899

>From 6523e512f69d38efe8218590b501eb28737d6522 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Thu, 26 Jun 2025 07:16:09 -0700
Subject: [PATCH 01/18] [MLIR][LLVMIR][DLTI] Add LLVMTargetAttrInterface,
 #llvm.target and #llvm.data_layout

---
 .../mlir/Dialect/LLVMIR/CMakeLists.txt        |  13 +-
 .../mlir/Dialect}/LLVMIR/DataLayoutImporter.h |  29 ++-
 .../Dialect/LLVMIR/LLVMAttrAndEnumDefs.td     |  10 +
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 180 +++++++++++-------
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h  |  10 +-
 .../mlir/Dialect/LLVMIR/LLVMDialect.td        |   8 +
 .../mlir/Dialect/LLVMIR/LLVMInterfaces.td     |  43 +++++
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   |   1 +
 .../LLVMIR/LLVMTargetFeaturesAttrDefs.td      |  82 ++++++++
 .../mlir/Dialect/LLVMIR/Transforms/Passes.td  |   8 +
 mlir/lib/Dialect/DLTI/DLTI.cpp                |   2 +-
 mlir/lib/Dialect/DLTI/Traits.cpp              |   2 +-
 mlir/lib/Dialect/LLVMIR/CMakeLists.txt        |  11 ++
 .../LLVMIR/IR}/DataLayoutImporter.cpp         |  18 +-
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp      |  76 +++++++-
 .../Dialect/LLVMIR/Transforms/CMakeLists.txt  |   1 +
 .../Transforms/DataLayoutFromTarget.cpp       |  62 ++++++
 mlir/lib/Target/LLVMIR/CMakeLists.txt         |   2 -
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       |   2 +-
 19 files changed, 462 insertions(+), 98 deletions(-)
 rename mlir/{lib/Target => include/mlir/Dialect}/LLVMIR/DataLayoutImporter.h (82%)
 create mode 100644 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
 create mode 100644 mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td
 rename mlir/lib/{Target/LLVMIR => Dialect/LLVMIR/IR}/DataLayoutImporter.cpp (94%)
 create mode 100644 mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp

diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index cfad07e57021f..311f1489e4e7e 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -7,12 +7,21 @@ mlir_tablegen(LLVMOpsDialect.h.inc -gen-dialect-decls)
 mlir_tablegen(LLVMOpsDialect.cpp.inc -gen-dialect-defs)
 mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls)
 mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs)
-mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls
-              -attrdefs-dialect=llvm)
 mlir_tablegen(LLVMOpsAttrDefs.cpp.inc -gen-attrdef-defs
               -attrdefs-dialect=llvm)
 add_public_tablegen_target(MLIRLLVMOpsIncGen)
 
+# FIXME: explain how this solves generated header recursive dependency
+set(LLVM_TARGET_DEFINITIONS LLVMAttrAndEnumDefs.td)
+mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls -attrdefs-dialect=llvm)
+add_public_tablegen_target(MLIRLLVMAttrsIncGen)
+
+# FIXME: explain how this solves generated header recursive dependency
+set(LLVM_TARGET_DEFINITIONS LLVMTargetFeaturesAttrDefs.td)
+mlir_tablegen(LLVMTargetFeaturesAttrDefs.h.inc -gen-attrdef-decls)
+mlir_tablegen(LLVMTargetFeaturesAttrDefs.cpp.inc -gen-attrdef-defs)
+add_public_tablegen_target(MLIRLLVMTargetFeaturesAttrsIncGen)
+
 set(LLVM_TARGET_DEFINITIONS LLVMTypes.td)
 mlir_tablegen(LLVMTypes.h.inc -gen-typedef-decls -typedefs-dialect=llvm)
 mlir_tablegen(LLVMTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=llvm)
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
similarity index 82%
rename from mlir/lib/Target/LLVMIR/DataLayoutImporter.h
rename to mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
index 88ceaf1a74e62..435528540508b 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
@@ -11,12 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
-#define MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
+#ifndef MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
+#define MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
 
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include "llvm/IR/DataLayout.h"
 #include "llvm/ADT/MapVector.h"
 
 namespace llvm {
@@ -38,6 +39,8 @@ namespace detail {
 /// null if the bit width is not supported.
 FloatType getFloatType(MLIRContext *context, unsigned width);
 
+} // namespace detail
+
 /// Helper class that translates an LLVM data layout to an MLIR data layout
 /// specification. Only integer, float, pointer, alloca memory space, stack
 /// alignment, and endianness entries are translated. The class also returns all
@@ -49,7 +52,22 @@ class DataLayoutImporter {
   DataLayoutImporter(MLIRContext *context,
                      const llvm::DataLayout &llvmDataLayout)
       : context(context) {
-    translateDataLayout(llvmDataLayout);
+    // Transform the data layout to its string representation and append the
+    // default data layout string specified in the language reference
+    // (https://llvm.org/docs/LangRef.html#data-layout). The translation then
+    // parses the string and ignores the default value if a specific kind occurs
+    // in both strings. Additionally, the following default values exist:
+    // - non-default address space pointer specifications default to the default
+    //   address space pointer specification
+    // - the alloca address space defaults to the default address space.
+    layoutStr = llvmDataLayout.getStringRepresentation();
+    translateDataLayoutFromStr();
+  }
+
+  DataLayoutImporter(MLIRContext *context,
+                     StringRef dataLayoutStr)
+      : layoutStr(dataLayoutStr), context(context) {
+    translateDataLayoutFromStr();
   }
 
   /// Returns the MLIR data layout specification translated from the LLVM
@@ -66,7 +84,7 @@ class DataLayoutImporter {
 
 private:
   /// Translates the LLVM `dataLayout` to an MLIR data layout specification.
-  void translateDataLayout(const llvm::DataLayout &llvmDataLayout);
+  void translateDataLayoutFromStr();
 
   /// Tries to parse the letter only prefix that identifies the specification
   /// and removes the consumed characters from the beginning of the string.
@@ -125,8 +143,7 @@ class DataLayoutImporter {
   DataLayoutSpecInterface dataLayout;
 };
 
-} // namespace detail
 } // namespace LLVM
 } // namespace mlir
 
-#endif // MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
+#endif // MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
new file mode 100644
index 0000000000000..2a01ab88116d8
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
@@ -0,0 +1,10 @@
+//===-- LLVMAttrDefs.td - Solely LLVM Attribute and Enum definitions ----*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
+include "mlir/Dialect/LLVMIR/LLVMEnums.td"
\ No newline at end of file
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 790d2e77ea874..705be61e17e76 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -13,13 +13,118 @@ include "mlir/Dialect/LLVMIR/LLVMDialect.td"
 include "mlir/Dialect/LLVMIR/LLVMInterfaces.td"
 include "mlir/IR/AttrTypeBase.td"
 include "mlir/IR/CommonAttrConstraints.td"
+include "mlir/Interfaces/DataLayoutInterfaces.td"
 
-// All of the attributes will extend this class.
-class LLVM_Attr<string name, string attrMnemonic,
-                list<Trait> traits = [],
-                string baseCppClass = "::mlir::Attribute">
-    : AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
-  let mnemonic = attrMnemonic;
+//===----------------------------------------------------------------------===//
+// LLVM_TargetAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_TargetAttr : LLVM_Attr<"Target", "target", [LLVM_TargetAttrInterface]> {
+  let mnemonic = "target";
+  let summary = "TODO";
+  let description = [{
+    TODO
+  }];
+  let parameters = (ins "StringAttr":$triple,
+                        "StringAttr":$cpu,
+                        "TargetFeaturesAttr":$target_features);
+
+  let assemblyFormat = "`<` $triple `,` $cpu `,` qualified($target_features) `>`";
+
+  let extraClassDeclaration = [{
+    std::optional<llvm::TargetMachine *> targetMachine = std::nullopt;
+
+    FailureOr<llvm::TargetMachine *> getTargetMachine();
+
+    std::optional<llvm::DataLayout> dataLayout = std::nullopt;
+    FailureOr<llvm::DataLayout> getDataLayout();
+    FailureOr<Attribute> query(DataLayoutEntryKey key);
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+// LLVM_DataLayoutAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DataLayoutAttr
+    : LLVM_Attr<"DataLayout", "data_layout", [DataLayoutSpecInterface]> {
+  let summary = "TODO";
+  let description = [{
+    TODO
+  }];
+  let parameters = (ins "StringAttr":$data_layout_str,
+                         OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
+  let builders = [
+    AttrBuilder<(ins "llvm::StringRef":$data_layout_str), [{
+      auto importer = LLVM::DataLayoutImporter($_ctxt, data_layout_str);
+      auto dataLayoutSpec = importer.getDataLayout();
+      return $_get($_ctxt, mlir::StringAttr::get($_ctxt, data_layout_str), dataLayoutSpec);
+    }]>
+  ];
+  let assemblyFormat = "`<` $data_layout_str `>`";
+  let extraClassDeclaration = [{
+    template <typename Ty>
+    DataLayoutEntryList getSpecForType() {
+      return getDataLayoutSpec().getSpecForType(TypeID::get<Ty>());
+    }
+
+    inline ::mlir::FailureOr<::mlir::Attribute>
+    queryHelper(::mlir::DataLayoutEntryKey key) const {
+      return getDataLayoutSpec().queryHelper(key);
+    }
+
+    void bucketEntriesByType(
+        ::llvm::MapVector<::mlir::TypeID, ::mlir::DataLayoutEntryList> &types,
+        ::llvm::MapVector<::mlir::StringAttr,
+                          ::mlir::DataLayoutEntryInterface> &ids) {
+      getDataLayoutSpec().bucketEntriesByType(types, ids);
+    };
+
+    ::mlir::DataLayoutSpecInterface
+    combineWith(ArrayRef<::mlir::DataLayoutSpecInterface> specs) const {
+      return getDataLayoutSpec().combineWith(specs);
+    }
+    DataLayoutEntryListRef getEntries() const { return getDataLayoutSpec().getEntries(); }
+    LogicalResult verifySpec(Location loc) {
+      return getDataLayoutSpec().verifySpec(loc);
+    }
+    StringAttr getEndiannessIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getEndiannessIdentifier(context);
+    }
+    StringAttr getDefaultMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getDefaultMemorySpaceIdentifier(context);
+    }
+    StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getAllocaMemorySpaceIdentifier(context);
+    }
+    StringAttr getManglingModeIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getManglingModeIdentifier(context);
+    }
+    StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getProgramMemorySpaceIdentifier(context);
+    }
+    StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getGlobalMemorySpaceIdentifier(context);
+    }
+    StringAttr getStackAlignmentIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getStackAlignmentIdentifier(context);
+    }
+    StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getFunctionPointerAlignmentIdentifier(context);
+    }
+    StringAttr getLegalIntWidthsIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getLegalIntWidthsIdentifier(context);
+    }
+    ::mlir::DataLayoutEntryList getSpecForType(TypeID type) const {
+      return getDataLayoutSpec().getSpecForType(type);
+    }
+    ::mlir::DataLayoutEntryInterface getSpecForIdentifier(StringAttr identifier) const {
+      return getDataLayoutSpec().getSpecForIdentifier(identifier);
+    }
+    FailureOr<Attribute> query(DataLayoutEntryKey key) const {
+      return getDataLayoutSpec().query(key);
+    }
+  }];
 }
 
 //===----------------------------------------------------------------------===//
@@ -1241,69 +1346,6 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
   let assemblyFormat = "`<` struct(params) `>`";
 }
 
-//===----------------------------------------------------------------------===//
-// TargetFeaturesAttr
-//===----------------------------------------------------------------------===//
-
-def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
-{
-  let summary = "LLVM target features attribute";
-
-  let description = [{
-    Represents the LLVM target features as a list that can be checked within
-    passes/rewrites.
-
-    Example:
-    ```mlir
-    #llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
-    ```
-
-    Then within a pass or rewrite the features active at an op can be queried:
-
-    ```c++
-    auto targetFeatures = LLVM::TargetFeaturesAttr::featuresAt(op);
-
-    if (!targetFeatures.contains("+sme-f64f64"))
-      return failure();
-    ```
-  }];
-
-  let parameters = (ins OptionalArrayRefParameter<"StringAttr">:$features);
-
-  let builders = [
-    TypeBuilder<(ins "::llvm::StringRef":$features)>,
-    TypeBuilder<(ins "::llvm::ArrayRef<::llvm::StringRef>":$features)>
-  ];
-
-  let extraClassDeclaration = [{
-    /// Checks if a feature is contained within the features list.
-    /// Note: Using a StringAttr allows doing pointer-comparisons.
-    bool contains(::mlir::StringAttr feature) const;
-    bool contains(::llvm::StringRef feature) const;
-
-    bool nullOrEmpty() const {
-      // Checks if this attribute is null, or the features are empty.
-      return !bool(*this) || getFeatures().empty();
-    }
-
-    /// Returns the list of features as an LLVM-compatible string.
-    std::string getFeaturesString() const;
-
-    /// Finds the target features on the parent FunctionOpInterface.
-    /// Note: This assumes the attribute name matches the return value of
-    /// `getAttributeName()`.
-    static TargetFeaturesAttr featuresAt(Operation* op);
-
-    /// Canonical name for this attribute within MLIR.
-    static constexpr StringLiteral getAttributeName() {
-      return StringLiteral("target_features");
-    }
-  }];
-
-  let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
-  let genVerifyDecl = 1;
-}
-
 //===----------------------------------------------------------------------===//
 // UndefAttr
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index 3ede857733242..371c202374225 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -14,7 +14,9 @@
 #ifndef MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
 #define MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
 
-#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Target/TargetMachine.h"
+#include "mlir/Interfaces/DataLayoutInterfaces.h"
 #include "mlir/IR/OpImplementation.h"
 #include <optional>
 
@@ -94,6 +96,12 @@ using linkage::Linkage;
 } // namespace LLVM
 } // namespace mlir
 
+// First obtain TargetFeaturesAttr definitions as it is used both an LLVMIR
+// interface and that interface and this attribute are turn required by another
+// LLVMIR attribute.
+#define GET_ATTRDEF_CLASSES
+#include "mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.h.inc"
+
 #include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc"
 
 #define GET_ATTRDEF_CLASSES
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
index b5ea8fc5da500..e924be32da10f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
@@ -10,6 +10,7 @@
 #define LLVMIR_DIALECT
 
 include "mlir/IR/DialectBase.td"
+include "mlir/IR/AttrTypeBase.td"
 
 def LLVM_Dialect : Dialect {
   let name = "llvm";
@@ -123,4 +124,11 @@ def LLVM_Dialect : Dialect {
   }];
 }
 
+class LLVM_Attr<string name, string attrMnemonic,
+                list<Trait> traits = [],
+                string baseCppClass = "::mlir::Attribute">
+    : AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
+  let mnemonic = attrMnemonic;
+}
+
 #endif  // LLVMIR_DIALECT
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 138170f8c8762..b7c1c6766fa60 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -14,6 +14,7 @@
 #define LLVMIR_INTERFACES
 
 include "mlir/IR/OpBase.td"
+include "mlir/Interfaces/DataLayoutInterfaces.td"
 
 def FastmathFlagsInterface : OpInterface<"FastmathFlagsInterface"> {
   let description = [{
@@ -532,4 +533,46 @@ def LLVM_DIRecursiveTypeAttrInterface
   ];
 }
 
+def LLVM_TargetAttrInterface
+  : AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
+  let description = [{
+    TODO
+
+    NEEDS TO document which TI keys it responds to.
+  }];
+  let cppNamespace = "::mlir::LLVM";
+  let methods = [
+    InterfaceMethod<
+      /*description=*/"Returns the target triple identifier.",
+      /*retTy=*/"::llvm::StringRef",
+      /*methodName=*/"getTriple",
+      /*args=*/(ins)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the target cpu identifier.",
+      /*retTy=*/"::llvm::StringRef",
+      /*methodName=*/"getCpu",
+      /*args=*/(ins)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the target features as a string.",
+      /*retTy=*/"::mlir::LLVM::TargetFeaturesAttr",
+      /*methodName=*/"getTargetFeatures",
+      /*args=*/(ins)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the target machine.",
+      /*retTy=*/"FailureOr<::llvm::TargetMachine *>",
+      /*methodName=*/"getTargetMachine",
+      /*args=*/(ins)
+    >,
+    InterfaceMethod<
+      /*description=*/"Returns the data layout associated to the target machine.",
+      /*retTy=*/"FailureOr<::llvm::DataLayout>",
+      /*methodName=*/"getDataLayout",
+      /*args=*/(ins)
+    >
+  ];
+}
+
 #endif // LLVMIR_INTERFACES
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index f4c1640098320..36a6291b5e3a8 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -14,6 +14,7 @@
 #define LLVMIR_OPS
 
 include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
+include "mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td"
 include "mlir/Dialect/LLVMIR/LLVMEnums.td"
 include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
 include "mlir/IR/EnumAttr.td"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td
new file mode 100644
index 0000000000000..2183f083103f5
--- /dev/null
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td
@@ -0,0 +1,82 @@
+//===-- LLVMAttrDefs.td - LLVM Attributes definition file --*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVMIR_TARGETFEATURESATTRDEFS
+#define LLVMIR_TARGETFEATURESATTRDEFS
+
+include "mlir/Dialect/LLVMIR/LLVMDialect.td"
+include "mlir/IR/CommonAttrConstraints.td"
+include "mlir/Interfaces/DataLayoutInterfaces.td"
+
+//===----------------------------------------------------------------------===//
+// TargetFeaturesAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features",
+    [DLTIQueryInterface]> {
+  let summary = "LLVM target features attribute";
+
+  let description = [{
+    Represents the LLVM target features as a list that can be checked within
+    passes/rewrites.
+
+    Example:
+    ```mlir
+    #llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
+    ```
+
+    Then within a pass or rewrite the features active at an op can be queried:
+
+    ```c++
+    auto targetFeatures = LLVM::TargetFeaturesAttr::featuresAt(op);
+
+    if (!targetFeatures.contains("+sme-f64f64"))
+      return failure();
+    ```
+  }];
+
+  let parameters = (ins OptionalArrayRefParameter<"StringAttr">:$features);
+
+  let builders = [
+    TypeBuilder<(ins "::llvm::StringRef":$features)>,
+    TypeBuilder<(ins "::llvm::ArrayRef<::llvm::StringRef>":$features)>
+  ];
+
+  let extraClassDeclaration = [{
+    /// Checks if a feature is contained within the features list.
+    /// Note: Using a StringAttr allows doing pointer-comparisons.
+    bool contains(::mlir::StringAttr feature) const;
+    bool contains(::llvm::StringRef feature) const;
+
+    bool nullOrEmpty() const {
+      // Checks if this attribute is null, or the features are empty.
+      return !bool(*this) || getFeatures().empty();
+    }
+
+    /// Returns the list of features as an LLVM-compatible string.
+    std::string getFeaturesString() const;
+
+    /// Finds the target features on the parent FunctionOpInterface.
+    /// Note: This assumes the attribute name matches the return value of
+    /// `getAttributeName()`.
+    static TargetFeaturesAttr featuresAt(Operation* op);
+
+    /// Canonical name for this attribute within MLIR.
+    static constexpr StringLiteral getAttributeName() {
+      return StringLiteral("target_features");
+    }
+
+    /// Returns the attribute associated with the key.
+    FailureOr<Attribute> query(DataLayoutEntryKey key);
+  }];
+
+  let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
+  let genVerifyDecl = 1;
+}
+
+#endif // LLVMIR_TARGETFEATURESATTRDEFS
diff --git a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
index 961909d5c8d27..5920c3b7b0332 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
@@ -45,6 +45,14 @@ def LLVMRequestCWrappersPass
   }];
 }
 
+def LLVMDataLayoutFromTarget : Pass<"llvm-data-layout-from-target", "::mlir::ModuleOp"> {
+  let summary = "TODO";
+  let dependentDialects = ["mlir::DLTIDialect"];
+  let description = [{
+  TODO
+  }];
+}
+
 def NVVMOptimizeForTargetPass : Pass<"llvm-optimize-for-nvvm-target"> {
   let summary = "Optimize NVVM IR";
 }
diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp
index 0c4fe27ffa58e..62ecf7d759959 100644
--- a/mlir/lib/Dialect/DLTI/DLTI.cpp
+++ b/mlir/lib/Dialect/DLTI/DLTI.cpp
@@ -657,7 +657,7 @@ void DLTIDialect::initialize() {
 LogicalResult DLTIDialect::verifyOperationAttribute(Operation *op,
                                                     NamedAttribute attr) {
   if (attr.getName() == DLTIDialect::kDataLayoutAttrName) {
-    if (!llvm::isa<DataLayoutSpecAttr>(attr.getValue())) {
+    if (!llvm::dyn_cast<DataLayoutSpecInterface>(attr.getValue())) {
       return op->emitError() << "'" << DLTIDialect::kDataLayoutAttrName
                              << "' is expected to be a #dlti.dl_spec attribute";
     }
diff --git a/mlir/lib/Dialect/DLTI/Traits.cpp b/mlir/lib/Dialect/DLTI/Traits.cpp
index 34f2dd5896083..3f6dd2900a915 100644
--- a/mlir/lib/Dialect/DLTI/Traits.cpp
+++ b/mlir/lib/Dialect/DLTI/Traits.cpp
@@ -24,7 +24,7 @@ LogicalResult mlir::impl::verifyHasDefaultDLTIDataLayoutTrait(Operation *op) {
 }
 
 DataLayoutSpecInterface mlir::impl::getDataLayoutSpec(Operation *op) {
-  return op->getAttrOfType<DataLayoutSpecAttr>(
+  return op->getAttrOfType<DataLayoutSpecInterface>(
       DLTIDialect::kDataLayoutAttrName);
 }
 
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index d987b72e98354..c3dea62df14c2 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(Transforms)
 
 add_mlir_dialect_library(MLIRLLVMDialect
+  IR/DataLayoutImporter.cpp
   IR/FunctionCallUtils.cpp
   IR/LLVMAttrs.cpp
   IR/LLVMDialect.cpp
@@ -13,6 +14,7 @@ add_mlir_dialect_library(MLIRLLVMDialect
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/LLVMIR
 
   DEPENDS
+  MLIRLLVMTargetFeaturesAttrsIncGen
   MLIRLLVMOpsIncGen
   MLIRLLVMTypesIncGen
   MLIRLLVMIntrinsicOpsIncGen
@@ -26,10 +28,19 @@ add_mlir_dialect_library(MLIRLLVMDialect
   BitReader
   BitWriter
   Core
+  MC
+  Target
+  Support
+  TargetParser
+  AllTargetsAsmParsers
+  AllTargetsCodeGens
+  AllTargetsDescs
+  AllTargetsInfos
 
   LINK_LIBS PUBLIC
   MLIRCallInterfaces
   MLIRControlFlowInterfaces
+  MLIRDLTIDialect
   MLIRDataLayoutInterfaces
   MLIRFunctionInterfaces
   MLIRInferTypeOpInterface
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
similarity index 94%
rename from mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
rename to mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
index fbad5c2fb78d9..f5fbd81503806 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "DataLayoutImporter.h"
+//#include "DataLayoutImporter.h"
+//#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
+#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinAttributes.h"
@@ -274,19 +276,7 @@ DataLayoutImporter::tryToEmplaceLegalIntWidthsEntry(StringRef token) {
   return success();
 }
 
-void DataLayoutImporter::translateDataLayout(
-    const llvm::DataLayout &llvmDataLayout) {
-  dataLayout = {};
-
-  // Transform the data layout to its string representation and append the
-  // default data layout string specified in the language reference
-  // (https://llvm.org/docs/LangRef.html#data-layout). The translation then
-  // parses the string and ignores the default value if a specific kind occurs
-  // in both strings. Additionally, the following default values exist:
-  // - non-default address space pointer specifications default to the default
-  //   address space pointer specification
-  // - the alloca address space defaults to the default address space.
-  layoutStr = llvmDataLayout.getStringRepresentation();
+void DataLayoutImporter::translateDataLayoutFromStr() {
   if (!layoutStr.empty())
     layoutStr += "-";
   layoutStr += kDefaultDataLayout;
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 915954a7f5f51..5cc11516b5df2 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
+#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/DialectImplementation.h"
@@ -18,8 +19,11 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DebugInfoMetadata.h"
-#include <optional>
+#include "llvm/Support/TargetSelect.h"
+
+#define DEBUG_TYPE "llvm-attrs"
 
 using namespace mlir;
 using namespace mlir::LLVM;
@@ -404,3 +408,73 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                         "supported for unknown key '"
                      << key << "'";
 }
+
+FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
+  if (auto stringKey = dyn_cast<StringAttr>(key))
+    if (contains(stringKey))
+      return UnitAttr::get(getContext());
+  return failure();
+}
+
+//===----------------------------------------------------------------------===//
+// LLVM_TargetAttr
+//===----------------------------------------------------------------------===//
+
+FailureOr<llvm::TargetMachine *> TargetAttr::getTargetMachine() {
+  if (targetMachine.has_value()) {
+    llvm::TargetMachine *tm = targetMachine.value();
+    if (tm != nullptr)
+      return {tm};
+    return failure();
+  }
+  llvm::InitializeAllTargets();
+  llvm::InitializeAllTargetMCs();
+
+  std::string error;
+  const llvm::Target *target =
+      llvm::TargetRegistry::lookupTarget(getTriple(), error);
+  if (!error.empty()) {
+    LLVM_DEBUG({
+      llvm::dbgs() << "Failed to retrieve the target with: `" << error << "`\n";
+    });
+    targetMachine = {nullptr};
+    return failure();
+  }
+
+  targetMachine = {target->createTargetMachine(
+      llvm::Triple(getTriple().strref()), getCpu().strref(),
+      getTargetFeatures().getFeaturesString().c_str(), {}, {})};
+
+  return {targetMachine.value()};
+}
+
+FailureOr<llvm::DataLayout> TargetAttr::getDataLayout() {
+  if (dataLayout.has_value()) {
+    return dataLayout.value();
+  }
+
+  FailureOr<llvm::TargetMachine *> targetMachine = getTargetMachine();
+  if (failed(targetMachine)) {
+    LLVM_DEBUG({
+      llvm::dbgs()
+          << "Failed to retrieve the target machine for data layout.\n";
+    });
+    dataLayout = std::nullopt;
+    return failure();
+  }
+  dataLayout = (targetMachine.value())->createDataLayout();
+  return dataLayout.value();
+}
+
+FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
+  if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
+    if (stringAttrKey.getValue() == "triple")
+      return getTriple();
+    if (stringAttrKey.getValue() == "cpu")
+      return getCpu();
+    if (stringAttrKey.getValue() == "features")
+      return getTargetFeatures();
+  }
+
+  return failure();
+}
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
index d4ff0955c5d0e..cc6289b485c55 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
@@ -7,6 +7,7 @@ add_mlir_dialect_library(MLIRLLVMIRTransforms
   LegalizeForExport.cpp
   OptimizeForNVVM.cpp
   RequestCWrappers.cpp
+  DataLayoutFromTarget.cpp
 
   DEPENDS
   MLIRLLVMPassIncGen
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
new file mode 100644
index 0000000000000..c2cccd37dd720
--- /dev/null
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
@@ -0,0 +1,62 @@
+//===- DataLayoutFromTarget.cpp - extract data layout from TargetMachine --===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Pass/Pass.h"
+#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
+
+namespace mlir {
+namespace LLVM {
+#define GEN_PASS_DEF_LLVMDATALAYOUTFROMTARGET
+#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
+} // namespace LLVM
+} // namespace mlir
+
+using namespace mlir;
+using namespace mlir::LLVM;
+
+struct DataLayoutFromTargetPass
+    : public LLVM::impl::LLVMDataLayoutFromTargetBase<DataLayoutFromTargetPass> {
+  void runOnOperation() override {
+    ModuleOp mod = getOperation();
+
+    bool passFailed = false;
+
+    mod->walk([&](ModuleOp mod) {
+      auto targetAttr =
+          mod->getAttrOfType<LLVM::TargetAttrInterface>("llvm.target");
+      if (!targetAttr)
+        return;
+
+      FailureOr<llvm::DataLayout> dataLayout = targetAttr.getDataLayout();
+      if (failed(dataLayout)) {
+        mod->emitError() << "failed to obtain llvm::DataLayout from "
+                         << targetAttr;
+        passFailed = true;
+      }
+      auto dataLayoutAttr = DataLayoutAttr::get(
+          &getContext(), dataLayout->getStringRepresentation());
+
+      StringRef dlSpecIdentifier = "dlti.dl_spec";
+      auto existingDlSpec =
+          mod->getAttrOfType<DataLayoutSpecInterface>(dlSpecIdentifier);
+      if (existingDlSpec) {
+        DataLayoutSpecInterface dataLayoutSpec =
+            existingDlSpec.combineWith({dataLayoutAttr.getDataLayoutSpec()});
+        mod->setAttr(dlSpecIdentifier, dataLayoutSpec);
+      } else {
+        mod->setAttr(dlSpecIdentifier, dataLayoutAttr);
+      }
+    });
+
+    if (passFailed) {
+      return signalPassFailure();
+    }
+  }
+};
diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt
index af22a7ff04bf0..f6d70fe05a163 100644
--- a/mlir/lib/Target/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt
@@ -3,7 +3,6 @@ add_subdirectory(Dialect)
 set(LLVM_OPTIONAL_SOURCES
   ConvertFromLLVMIR.cpp
   ConvertToLLVMIR.cpp
-  DataLayoutImporter.cpp
   DebugTranslation.cpp
   DebugImporter.cpp
   LoopAnnotationImporter.cpp
@@ -63,7 +62,6 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
   )
 
 add_mlir_translation_library(MLIRTargetLLVMIRImport
-  DataLayoutImporter.cpp
   DebugImporter.cpp
   LoopAnnotationImporter.cpp
   ModuleImport.cpp
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index bfda223fe0f5f..8b570d669a0f3 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -16,11 +16,11 @@
 #include "mlir/Target/LLVMIR/Import.h"
 
 #include "AttrKindDetail.h"
-#include "DataLayoutImporter.h"
 #include "DebugImporter.h"
 #include "LoopAnnotationImporter.h"
 
 #include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/Matchers.h"

>From 0a1903b187ac6af1f9a9b6400c17ac289bff96a1 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Thu, 26 Jun 2025 09:15:32 -0700
Subject: [PATCH 02/18] Try to fix Flang...

---
 flang/include/flang/Optimizer/Dialect/FIRType.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index ecab12de55d61..83077aef8d08d 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -13,6 +13,7 @@
 #ifndef FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
 #define FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
 
+#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"

>From eb1cbb569976729823fe9a27b2f1f100b742c8ea Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Thu, 26 Jun 2025 10:02:48 -0700
Subject: [PATCH 03/18] Fix formatting

---
 mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h       | 5 ++---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td     | 2 +-
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h                | 6 +++---
 mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp           | 2 --
 mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp | 5 +++--
 5 files changed, 9 insertions(+), 11 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
index 435528540508b..0f036f1c43492 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
@@ -17,8 +17,8 @@
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
-#include "llvm/IR/DataLayout.h"
 #include "llvm/ADT/MapVector.h"
+#include "llvm/IR/DataLayout.h"
 
 namespace llvm {
 class StringRef;
@@ -64,8 +64,7 @@ class DataLayoutImporter {
     translateDataLayoutFromStr();
   }
 
-  DataLayoutImporter(MLIRContext *context,
-                     StringRef dataLayoutStr)
+  DataLayoutImporter(MLIRContext *context, StringRef dataLayoutStr)
       : layoutStr(dataLayoutStr), context(context) {
     translateDataLayoutFromStr();
   }
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
index 2a01ab88116d8..e34375076ffd1 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
@@ -7,4 +7,4 @@
 //===----------------------------------------------------------------------===//
 
 include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
-include "mlir/Dialect/LLVMIR/LLVMEnums.td"
\ No newline at end of file
+include "mlir/Dialect/LLVMIR/LLVMEnums.td"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index 371c202374225..14645d5dee95f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -14,10 +14,10 @@
 #ifndef MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
 #define MLIR_DIALECT_LLVMIR_LLVMATTRS_H_
 
+#include "mlir/IR/OpImplementation.h"
+#include "mlir/Interfaces/DataLayoutInterfaces.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Target/TargetMachine.h"
-#include "mlir/Interfaces/DataLayoutInterfaces.h"
-#include "mlir/IR/OpImplementation.h"
 #include <optional>
 
 #include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
@@ -91,8 +91,8 @@ class TBAANodeAttr : public Attribute {
 // TODO: this shouldn't be needed after we unify the attribute generation, i.e.
 // --gen-attr-* and --gen-attrdef-*.
 using cconv::CConv;
-using tailcallkind::TailCallKind;
 using linkage::Linkage;
+using tailcallkind::TailCallKind;
 } // namespace LLVM
 } // namespace mlir
 
diff --git a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
index f5fbd81503806..988fe27e7cd8e 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
@@ -6,8 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-//#include "DataLayoutImporter.h"
-//#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/IR/Builders.h"
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
index c2cccd37dd720..f43709ab1aca5 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
@@ -7,9 +7,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Pass/Pass.h"
-#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 
 namespace mlir {
 namespace LLVM {
@@ -22,7 +22,8 @@ using namespace mlir;
 using namespace mlir::LLVM;
 
 struct DataLayoutFromTargetPass
-    : public LLVM::impl::LLVMDataLayoutFromTargetBase<DataLayoutFromTargetPass> {
+    : public LLVM::impl::LLVMDataLayoutFromTargetBase<
+          DataLayoutFromTargetPass> {
   void runOnOperation() override {
     ModuleOp mod = getOperation();
 

>From b6a07f9559bec8dc3a3264f2f5da4178b34551f4 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Thu, 26 Jun 2025 14:37:49 -0700
Subject: [PATCH 04/18] Minor fixes

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td  |  8 +++++---
 .../include/mlir/Dialect/LLVMIR/LLVMInterfaces.td |  6 +++---
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp          | 15 ++++++++-------
 .../LLVMIR/Transforms/DataLayoutFromTarget.cpp    |  1 +
 4 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 705be61e17e76..e0480f4be82ed 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -26,10 +26,12 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target", [LLVM_TargetAttrInterface]>
     TODO
   }];
   let parameters = (ins "StringAttr":$triple,
-                        "StringAttr":$cpu,
-                        "TargetFeaturesAttr":$target_features);
+                        OptionalParameter<"StringAttr">:$chip,
+                        OptionalParameter<"TargetFeaturesAttr">:$features);
 
-  let assemblyFormat = "`<` $triple `,` $cpu `,` qualified($target_features) `>`";
+  let assemblyFormat = [{`<` `triple` `=` $triple
+                         (`,` `chip` `=` $chip^)?
+                         (`,` qualified($features)^)? `>`}];
 
   let extraClassDeclaration = [{
     std::optional<llvm::TargetMachine *> targetMachine = std::nullopt;
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index b7c1c6766fa60..72facd13994f7 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -549,15 +549,15 @@ def LLVM_TargetAttrInterface
       /*args=*/(ins)
     >,
     InterfaceMethod<
-      /*description=*/"Returns the target cpu identifier.",
+      /*description=*/"Returns the target chip (i.e. \"cpu\") identifier.",
       /*retTy=*/"::llvm::StringRef",
-      /*methodName=*/"getCpu",
+      /*methodName=*/"getChip",
       /*args=*/(ins)
     >,
     InterfaceMethod<
       /*description=*/"Returns the target features as a string.",
       /*retTy=*/"::mlir::LLVM::TargetFeaturesAttr",
-      /*methodName=*/"getTargetFeatures",
+      /*methodName=*/"getFeatures",
       /*args=*/(ins)
     >,
     InterfaceMethod<
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 5cc11516b5df2..dbe91e001f1cb 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -433,7 +433,7 @@ FailureOr<llvm::TargetMachine *> TargetAttr::getTargetMachine() {
   std::string error;
   const llvm::Target *target =
       llvm::TargetRegistry::lookupTarget(getTriple(), error);
-  if (!error.empty()) {
+  if (!target || !error.empty()) {
     LLVM_DEBUG({
       llvm::dbgs() << "Failed to retrieve the target with: `" << error << "`\n";
     });
@@ -442,8 +442,8 @@ FailureOr<llvm::TargetMachine *> TargetAttr::getTargetMachine() {
   }
 
   targetMachine = {target->createTargetMachine(
-      llvm::Triple(getTriple().strref()), getCpu().strref(),
-      getTargetFeatures().getFeaturesString().c_str(), {}, {})};
+      llvm::Triple(getTriple().strref()), getChip() ? getChip().strref() : "",
+      getFeatures() ? getFeatures().getFeaturesString() : "", {}, {})};
 
   return {targetMachine.value()};
 }
@@ -467,13 +467,14 @@ FailureOr<llvm::DataLayout> TargetAttr::getDataLayout() {
 }
 
 FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
+  Attribute result;
   if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
     if (stringAttrKey.getValue() == "triple")
       return getTriple();
-    if (stringAttrKey.getValue() == "cpu")
-      return getCpu();
-    if (stringAttrKey.getValue() == "features")
-      return getTargetFeatures();
+    if (stringAttrKey.getValue() == "chip" && (result = getChip()))
+      return result;
+    if (stringAttrKey.getValue() == "features" && (result = getFeatures()))
+      return result;
   }
 
   return failure();
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
index f43709ab1aca5..06990525d87ac 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
@@ -40,6 +40,7 @@ struct DataLayoutFromTargetPass
         mod->emitError() << "failed to obtain llvm::DataLayout from "
                          << targetAttr;
         passFailed = true;
+        return;
       }
       auto dataLayoutAttr = DataLayoutAttr::get(
           &getContext(), dataLayout->getStringRepresentation());

>From ef55a799bf6fd30611de5df40d4036c445490c34 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Thu, 26 Jun 2025 14:39:43 -0700
Subject: [PATCH 05/18] Add first two tests

---
 .../data-layout-from-target-invalid.mlir      |  8 ++++
 .../LLVMIR/data-layout-from-target.mlir       | 41 +++++++++++++++++++
 2 files changed, 49 insertions(+)
 create mode 100644 mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
 create mode 100644 mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir

diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
new file mode 100644
index 0000000000000..71526663abf96
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
@@ -0,0 +1,8 @@
+// RUN: mlir-opt %s -llvm-data-layout-from-target --split-input-file --verify-diagnostics
+
+// expected-error @+1 {{failed to obtain llvm::DataLayout from #llvm.target}}
+module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
+llvm.target =
+    #llvm.target<triple="x64_86-unknown-linux",
+                 chip="lakesky"> } {
+}
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
new file mode 100644
index 0000000000000..5983a34fe1e0d
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
@@ -0,0 +1,41 @@
+// RUN: mlir-opt -llvm-data-layout-from-target -split-input-file %s | FileCheck %s
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME:   triple = "x86_64-unknown-linux"
+// CHECK-NOT:    chip =
+// CHECK-NOT:    #llvm.target_features
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux"> } {
+}
+
+// -----
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #llvm.data_layout<"[[DL_STR:.*]]">
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME:   triple = "x86_64-unknown-linux"
+// CHECK-SAME:   chip = "skylake"
+// CHECK-SAME:   #llvm.target_features<["+mmx", "+sse"]>
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake",
+                                               #llvm.target_features<["+mmx", "+sse"]>> } {
+}
+
+// -----
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec<"dlti.endianness" = "little"
+// CHECK-SAME:   index = 32
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME:   triple = "x86_64-unknown-linux"
+// CHECK-SAME:   chip = "skylake"
+// CHECK-SAME:   #llvm.target_features<["+mmx", "+sse"]>
+
+module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
+                    llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake",
+                                               #llvm.target_features<["+mmx", "+sse"]>> } {
+}

>From 9b67848c47996d6eef87338b136bc53c2734665b Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Tue, 8 Jul 2025 09:19:33 -0700
Subject: [PATCH 06/18] Update docs

---
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 30 +++++++++++++++----
 .../mlir/Dialect/LLVMIR/LLVMInterfaces.td     | 16 ++++++++--
 2 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index e0480f4be82ed..e563441d0102b 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -19,11 +19,24 @@ include "mlir/Interfaces/DataLayoutInterfaces.td"
 // LLVM_TargetAttr
 //===----------------------------------------------------------------------===//
 
-def LLVM_TargetAttr : LLVM_Attr<"Target", "target", [LLVM_TargetAttrInterface]> {
-  let mnemonic = "target";
-  let summary = "TODO";
+def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
+                                [LLVM_TargetAttrInterface]> {
+  let summary = "LLVM target info: triple, chip, features";
   let description = [{
-    TODO
+    An attribute to hold LLVM target information, specifying LLVM's target
+    `triple` string, the target `chip` string (i.e. the `cpu` string), and
+    target `features` string as an attribute. The latter two are optional.
+
+    Has facilities to obtain the corresponding `llvm::TargetMachine` and
+    `llvm::DataLayout`, given the relevant LLVM backend is loaded.
+
+    ---
+
+    Responds to DLTI-queries on the keys:
+       * A query for `"triple"` returns the `StringAttr` for the `triple`.
+       * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`, if provided.
+       * A query for `"features"` returns the `TargetFeaturesAttr`, if provided.
+         * Individual features can be queried for on this attribute.
   }];
   let parameters = (ins "StringAttr":$triple,
                         OptionalParameter<"StringAttr">:$chip,
@@ -50,9 +63,14 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target", [LLVM_TargetAttrInterface]>
 
 def LLVM_DataLayoutAttr
     : LLVM_Attr<"DataLayout", "data_layout", [DataLayoutSpecInterface]> {
-  let summary = "TODO";
+  let summary = "LLVM data layout string, exposed through DLTI";
   let description = [{
-    TODO
+    An attribute to hold a LLVM data layout string.
+
+    The LLVM data layout string is parsed and mapped to the corresponding MLIR
+    data layout specification. The `#llvm.data_layout` attribute then serves as
+    a proxy, forwarding all DLTI queries to the underlying MLIR data layout
+    specification.
   }];
   let parameters = (ins "StringAttr":$data_layout_str,
                          OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 72facd13994f7..0d2603debbc28 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -536,9 +536,19 @@ def LLVM_DIRecursiveTypeAttrInterface
 def LLVM_TargetAttrInterface
   : AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
   let description = [{
-    TODO
-
-    NEEDS TO document which TI keys it responds to.
+    Interface for attributes that describe LLVM targets.
+
+    These attributes should be able to return the specified target
+    `triple`, `chip` and `features` and are expected to be able to
+    produce the corresponding `llvm::TargetMachine` and
+    `llvm::DataLayout`. These methods can fail in case the backend
+    is not available.
+
+    Implementing attributes should provide a
+    `DLTIQueryInterface::query()` implementation which responds to
+    keys `"triple"`, `"chip"` and `"features"` by returning an
+    appropriate `StringAttr`, `StringAttr` and
+    `LLVM_TargetFeaturesAttr`.
   }];
   let cppNamespace = "::mlir::LLVM";
   let methods = [

>From 91560a50ccddf3e5b93e2229fc0c7a960a2637a2 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Wed, 9 Jul 2025 08:43:47 -0700
Subject: [PATCH 07/18] Add cmake comments and a test

---
 .../mlir/Dialect/LLVMIR/CMakeLists.txt        |  9 ++++--
 .../LLVMIR/data-layout-from-target.mlir       | 30 ++++++++++++++++++-
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index 311f1489e4e7e..f1385cdff62be 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -7,16 +7,21 @@ mlir_tablegen(LLVMOpsDialect.h.inc -gen-dialect-decls)
 mlir_tablegen(LLVMOpsDialect.cpp.inc -gen-dialect-defs)
 mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls)
 mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs)
+#For LLVMOpsAttrDefs.h.inc, see below.
 mlir_tablegen(LLVMOpsAttrDefs.cpp.inc -gen-attrdef-defs
               -attrdefs-dialect=llvm)
 add_public_tablegen_target(MLIRLLVMOpsIncGen)
 
-# FIXME: explain how this solves generated header recursive dependency
+# NB: Separate out LLVMOpsAttrDefs.h.inc generation as generating it
+#     through LLVMOps.td ends up defining LLVMTargetFeaturesAttr even
+#     though LLVMTargetFeaturesAttrDefs.* is responsible for that.
 set(LLVM_TARGET_DEFINITIONS LLVMAttrAndEnumDefs.td)
 mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls -attrdefs-dialect=llvm)
 add_public_tablegen_target(MLIRLLVMAttrsIncGen)
 
-# FIXME: explain how this solves generated header recursive dependency
+# NB: LLVMTargetFeaturesAttr is split out into its own file
+#     to break a recursive dependency: LLVMInterfaces depends
+#     on it, and other LLVMAttrs depending on LLVMInterfaces.
 set(LLVM_TARGET_DEFINITIONS LLVMTargetFeaturesAttrDefs.td)
 mlir_tablegen(LLVMTargetFeaturesAttrDefs.h.inc -gen-attrdef-decls)
 mlir_tablegen(LLVMTargetFeaturesAttrDefs.cpp.inc -gen-attrdef-defs)
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
index 5983a34fe1e0d..5eb698d6dd859 100644
--- a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
+++ b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
@@ -12,8 +12,36 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux">
 
 // -----
 
+// TODO: module attributes
+// TODO-SAME: dlti.dl_spec = #llvm.data_layout
+// TODO-SAME: llvm.target = #llvm.target<
+// TODO-SAME:   triple = "x86_64-unknown-linux"
+// TODO-NOT:   chip = "skylake"
+// TODO-SAME:   #llvm.target_features<["+mmx", "+sse"]>
+// TODO-NOT:   chip = "skylake"
+
+//module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+//                                               // Generated parser is dumb: expected 'chip'
+//                                               #llvm.target_features<["+mmx", "+sse"]>> } {
+//}
+
+// -----
+
 // CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #llvm.data_layout<"[[DL_STR:.*]]">
+// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME:   triple = "x86_64-unknown-linux"
+// CHECK-SAME:   chip = "skylake"
+// CHECK-NOT:    #llvm.target_features
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "skylake"> } {
+}
+
+// -----
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = "skylake"

>From c7b3be3f607f55764311fc3e230b0c4d27bf4129 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Wed, 23 Jul 2025 10:23:22 -0700
Subject: [PATCH 08/18] Make chip required, no caching of TargetMachine, and
 take features as a string

---
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 19 ++--------
 .../mlir/Dialect/LLVMIR/LLVMInterfaces.td     |  4 +-
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp      | 31 +++++----------
 .../LLVMIR/data-layout-from-target.mlir       | 38 +++++++++----------
 4 files changed, 34 insertions(+), 58 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index e563441d0102b..bf8e285ac61f3 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -39,19 +39,13 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
          * Individual features can be queried for on this attribute.
   }];
   let parameters = (ins "StringAttr":$triple,
-                        OptionalParameter<"StringAttr">:$chip,
-                        OptionalParameter<"TargetFeaturesAttr">:$features);
+                        "StringAttr":$chip,
+                        OptionalParameter<"StringAttr">:$features);
 
-  let assemblyFormat = [{`<` `triple` `=` $triple
-                         (`,` `chip` `=` $chip^)?
-                         (`,` qualified($features)^)? `>`}];
+  let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
 
   let extraClassDeclaration = [{
-    std::optional<llvm::TargetMachine *> targetMachine = std::nullopt;
-
-    FailureOr<llvm::TargetMachine *> getTargetMachine();
-
-    std::optional<llvm::DataLayout> dataLayout = std::nullopt;
+    FailureOr<std::unique_ptr<llvm::TargetMachine>> getTargetMachine();
     FailureOr<llvm::DataLayout> getDataLayout();
     FailureOr<Attribute> query(DataLayoutEntryKey key);
   }];
@@ -88,11 +82,6 @@ def LLVM_DataLayoutAttr
       return getDataLayoutSpec().getSpecForType(TypeID::get<Ty>());
     }
 
-    inline ::mlir::FailureOr<::mlir::Attribute>
-    queryHelper(::mlir::DataLayoutEntryKey key) const {
-      return getDataLayoutSpec().queryHelper(key);
-    }
-
     void bucketEntriesByType(
         ::llvm::MapVector<::mlir::TypeID, ::mlir::DataLayoutEntryList> &types,
         ::llvm::MapVector<::mlir::StringAttr,
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 0d2603debbc28..e07fd5982449c 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -566,13 +566,13 @@ def LLVM_TargetAttrInterface
     >,
     InterfaceMethod<
       /*description=*/"Returns the target features as a string.",
-      /*retTy=*/"::mlir::LLVM::TargetFeaturesAttr",
+      /*retTy=*/"::llvm::StringRef",
       /*methodName=*/"getFeatures",
       /*args=*/(ins)
     >,
     InterfaceMethod<
       /*description=*/"Returns the target machine.",
-      /*retTy=*/"FailureOr<::llvm::TargetMachine *>",
+      /*retTy=*/"FailureOr<std::unique_ptr<::llvm::TargetMachine>>",
       /*methodName=*/"getTargetMachine",
       /*args=*/(ins)
     >,
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index dbe91e001f1cb..50e4606fbd961 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -420,13 +420,7 @@ FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
 // LLVM_TargetAttr
 //===----------------------------------------------------------------------===//
 
-FailureOr<llvm::TargetMachine *> TargetAttr::getTargetMachine() {
-  if (targetMachine.has_value()) {
-    llvm::TargetMachine *tm = targetMachine.value();
-    if (tm != nullptr)
-      return {tm};
-    return failure();
-  }
+FailureOr<std::unique_ptr<llvm::TargetMachine>> TargetAttr::getTargetMachine() {
   llvm::InitializeAllTargets();
   llvm::InitializeAllTargetMCs();
 
@@ -435,35 +429,28 @@ FailureOr<llvm::TargetMachine *> TargetAttr::getTargetMachine() {
       llvm::TargetRegistry::lookupTarget(getTriple(), error);
   if (!target || !error.empty()) {
     LLVM_DEBUG({
-      llvm::dbgs() << "Failed to retrieve the target with: `" << error << "`\n";
+      llvm::dbgs() << "Looking up target '" << getTriple()
+                   << "' failed: " << error << "\n";
     });
-    targetMachine = {nullptr};
     return failure();
   }
 
-  targetMachine = {target->createTargetMachine(
-      llvm::Triple(getTriple().strref()), getChip() ? getChip().strref() : "",
-      getFeatures() ? getFeatures().getFeaturesString() : "", {}, {})};
-
-  return {targetMachine.value()};
+  return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
+      llvm::Triple(getTriple().strref()), getChip().strref(),
+      getFeatures() ? getFeatures().strref() : "", {}, {}));
 }
 
 FailureOr<llvm::DataLayout> TargetAttr::getDataLayout() {
-  if (dataLayout.has_value()) {
-    return dataLayout.value();
-  }
-
-  FailureOr<llvm::TargetMachine *> targetMachine = getTargetMachine();
+  FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
+      getTargetMachine();
   if (failed(targetMachine)) {
     LLVM_DEBUG({
       llvm::dbgs()
           << "Failed to retrieve the target machine for data layout.\n";
     });
-    dataLayout = std::nullopt;
     return failure();
   }
-  dataLayout = (targetMachine.value())->createDataLayout();
-  return dataLayout.value();
+  return (targetMachine.value())->createDataLayout();
 }
 
 FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
index 5eb698d6dd859..e1cd39cf87b8f 100644
--- a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
+++ b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
@@ -4,26 +4,26 @@
 // CHECK-SAME: dlti.dl_spec = #llvm.data_layout
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
-// CHECK-NOT:    chip =
-// CHECK-NOT:    #llvm.target_features
+// CHECK-SAME:   chip = ""
+// CHECK-NOT:    features =
 
-module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux"> } {
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux", chip = ""> } {
 }
 
 // -----
 
-// TODO: module attributes
-// TODO-SAME: dlti.dl_spec = #llvm.data_layout
-// TODO-SAME: llvm.target = #llvm.target<
-// TODO-SAME:   triple = "x86_64-unknown-linux"
-// TODO-NOT:   chip = "skylake"
-// TODO-SAME:   #llvm.target_features<["+mmx", "+sse"]>
-// TODO-NOT:   chip = "skylake"
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME:   triple = "x86_64-unknown-linux"
+// CHECK-SAME:   chip = ""
+// CHECK-SAME:   features = "+mmx,+sse"
+// CHECK-NOT:    chip = "skylake"
 
-//module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
-//                                               // Generated parser is dumb: expected 'chip'
-//                                               #llvm.target_features<["+mmx", "+sse"]>> } {
-//}
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = "",
+                                               features = "+mmx,+sse"> } {
+}
 
 // -----
 
@@ -32,7 +32,7 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux">
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = "skylake"
-// CHECK-NOT:    #llvm.target_features
+// CHECK-NOT:    features =
 
 module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
                                                chip = "skylake"> } {
@@ -45,11 +45,11 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = "skylake"
-// CHECK-SAME:   #llvm.target_features<["+mmx", "+sse"]>
+// CHECK-SAME:   features = "+mmx,+sse">
 
 module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
                                                chip = "skylake",
-                                               #llvm.target_features<["+mmx", "+sse"]>> } {
+                                               features = "+mmx,+sse"> } {
 }
 
 // -----
@@ -60,10 +60,10 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = "skylake"
-// CHECK-SAME:   #llvm.target_features<["+mmx", "+sse"]>
+// CHECK-SAME:   features = "+mmx,+sse"
 
 module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
                     llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
                                                chip = "skylake",
-                                               #llvm.target_features<["+mmx", "+sse"]>> } {
+                                               features = "+mmx,+sse"> } {
 }

>From fa84e7f68c8b8e0b4a32558dadbf41e8e5415ba8 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Thu, 24 Jul 2025 15:35:16 -0700
Subject: [PATCH 09/18] Resolve issues based on review

Issue 1. - features is now a StringAttr
Issue 2. - use struct for attribute parsing
Issue 3. - forgo trying to cache llvm::TargetMachine
Issue 4. - keep code that needs to link to llvm libs in mlir/Target
---
 .../mlir/Dialect/LLVMIR/CMakeLists.txt        |  18 +-
 .../mlir/Dialect/LLVMIR/DataLayoutImporter.h  |  52 ++-
 .../Dialect/LLVMIR/LLVMAttrAndEnumDefs.td     |  10 -
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 305 +++++++++++-------
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h  |  11 +-
 .../mlir/Dialect/LLVMIR/LLVMInterfaces.h      |   1 +
 .../mlir/Dialect/LLVMIR/LLVMInterfaces.td     |  31 +-
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   |   1 -
 .../LLVMIR/LLVMTargetFeaturesAttrDefs.td      |  82 -----
 mlir/include/mlir/InitAllDialects.h           |   2 +
 mlir/include/mlir/Target/LLVM/Target.h        |  30 ++
 mlir/lib/Dialect/LLVMIR/CMakeLists.txt        |   9 -
 .../Dialect/LLVMIR/IR/DataLayoutImporter.cpp  |  54 ++--
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp      |  49 +--
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp    |   1 +
 .../Transforms/DataLayoutFromTarget.cpp       |   4 +-
 mlir/lib/Target/LLVM/CMakeLists.txt           |   9 +-
 mlir/lib/Target/LLVM/Target.cpp               |  90 ++++++
 .../LLVMIR/data-layout-from-target.mlir       |   1 -
 19 files changed, 387 insertions(+), 373 deletions(-)
 delete mode 100644 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
 delete mode 100644 mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td
 create mode 100644 mlir/include/mlir/Target/LLVM/Target.h
 create mode 100644 mlir/lib/Target/LLVM/Target.cpp

diff --git a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
index f1385cdff62be..cfad07e57021f 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/include/mlir/Dialect/LLVMIR/CMakeLists.txt
@@ -7,26 +7,12 @@ mlir_tablegen(LLVMOpsDialect.h.inc -gen-dialect-decls)
 mlir_tablegen(LLVMOpsDialect.cpp.inc -gen-dialect-defs)
 mlir_tablegen(LLVMOpsEnums.h.inc -gen-enum-decls)
 mlir_tablegen(LLVMOpsEnums.cpp.inc -gen-enum-defs)
-#For LLVMOpsAttrDefs.h.inc, see below.
+mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls
+              -attrdefs-dialect=llvm)
 mlir_tablegen(LLVMOpsAttrDefs.cpp.inc -gen-attrdef-defs
               -attrdefs-dialect=llvm)
 add_public_tablegen_target(MLIRLLVMOpsIncGen)
 
-# NB: Separate out LLVMOpsAttrDefs.h.inc generation as generating it
-#     through LLVMOps.td ends up defining LLVMTargetFeaturesAttr even
-#     though LLVMTargetFeaturesAttrDefs.* is responsible for that.
-set(LLVM_TARGET_DEFINITIONS LLVMAttrAndEnumDefs.td)
-mlir_tablegen(LLVMOpsAttrDefs.h.inc -gen-attrdef-decls -attrdefs-dialect=llvm)
-add_public_tablegen_target(MLIRLLVMAttrsIncGen)
-
-# NB: LLVMTargetFeaturesAttr is split out into its own file
-#     to break a recursive dependency: LLVMInterfaces depends
-#     on it, and other LLVMAttrs depending on LLVMInterfaces.
-set(LLVM_TARGET_DEFINITIONS LLVMTargetFeaturesAttrDefs.td)
-mlir_tablegen(LLVMTargetFeaturesAttrDefs.h.inc -gen-attrdef-decls)
-mlir_tablegen(LLVMTargetFeaturesAttrDefs.cpp.inc -gen-attrdef-defs)
-add_public_tablegen_target(MLIRLLVMTargetFeaturesAttrsIncGen)
-
 set(LLVM_TARGET_DEFINITIONS LLVMTypes.td)
 mlir_tablegen(LLVMTypes.h.inc -gen-typedef-decls -typedefs-dialect=llvm)
 mlir_tablegen(LLVMTypes.cpp.inc -gen-typedef-defs -typedefs-dialect=llvm)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
index 0f036f1c43492..3f07c6a7b4726 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
@@ -11,14 +11,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
-#define MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
+#ifndef MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H_
+#define MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H_
 
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
 #include "llvm/ADT/MapVector.h"
-#include "llvm/IR/DataLayout.h"
 
 namespace llvm {
 class StringRef;
@@ -41,37 +40,30 @@ FloatType getFloatType(MLIRContext *context, unsigned width);
 
 } // namespace detail
 
-/// Helper class that translates an LLVM data layout to an MLIR data layout
-/// specification. Only integer, float, pointer, alloca memory space, stack
-/// alignment, and endianness entries are translated. The class also returns all
-/// entries from the default data layout specification found in the language
-/// reference (https://llvm.org/docs/LangRef.html#data-layout) if they are not
-/// overwritten by the provided data layout.
+/// Helper class that translates an LLVM data layout string to an MLIR data
+/// layout specification. Only integer, float, pointer, alloca memory space,
+/// stack alignment, and endianness entries are translated. The class also
+/// returns all entries from the default data layout specification found in the
+/// language reference (https://llvm.org/docs/LangRef.html#data-layout) if they
+/// are not overwritten by the provided data layout.
 class DataLayoutImporter {
 public:
-  DataLayoutImporter(MLIRContext *context,
-                     const llvm::DataLayout &llvmDataLayout)
-      : context(context) {
-    // Transform the data layout to its string representation and append the
-    // default data layout string specified in the language reference
-    // (https://llvm.org/docs/LangRef.html#data-layout). The translation then
-    // parses the string and ignores the default value if a specific kind occurs
-    // in both strings. Additionally, the following default values exist:
+  DataLayoutImporter(MLIRContext *context, StringRef dataLayoutStr)
+      : dataLayoutStr(dataLayoutStr), context(context) {
+    // Append the default data layout string specified in the language reference
+    // (https://llvm.org/docs/LangRef.html#data-layout) to the supplied data
+    // layout string. The translation then parses the string and ignores the
+    // default value if a specific kind occurs in both strings. Additionally,
+    // the following default values exist:
     // - non-default address space pointer specifications default to the default
     //   address space pointer specification
     // - the alloca address space defaults to the default address space.
-    layoutStr = llvmDataLayout.getStringRepresentation();
-    translateDataLayoutFromStr();
-  }
-
-  DataLayoutImporter(MLIRContext *context, StringRef dataLayoutStr)
-      : layoutStr(dataLayoutStr), context(context) {
-    translateDataLayoutFromStr();
+    dataLayoutSpec = dataLayoutSpecFromDataLayoutStr(dataLayoutStr);
   }
 
   /// Returns the MLIR data layout specification translated from the LLVM
   /// data layout.
-  DataLayoutSpecInterface getDataLayout() const { return dataLayout; }
+  DataLayoutSpecInterface getDataLayoutSpec() const { return dataLayoutSpec; }
 
   /// Returns the last data layout token that has been processed before
   /// the data layout translation failed.
@@ -83,7 +75,8 @@ class DataLayoutImporter {
 
 private:
   /// Translates the LLVM `dataLayout` to an MLIR data layout specification.
-  void translateDataLayoutFromStr();
+  DataLayoutSpecInterface
+  dataLayoutSpecFromDataLayoutStr(StringRef dataLayoutStr);
 
   /// Tries to parse the letter only prefix that identifies the specification
   /// and removes the consumed characters from the beginning of the string.
@@ -133,16 +126,17 @@ class DataLayoutImporter {
   /// Adds legal int widths entry if there is none yet.
   LogicalResult tryToEmplaceLegalIntWidthsEntry(StringRef token);
 
-  std::string layoutStr = {};
+  std::string dataLayoutStr = {};
+  DataLayoutSpecInterface dataLayoutSpec;
+
   StringRef lastToken = {};
   SmallVector<StringRef> unhandledTokens;
   llvm::MapVector<StringAttr, DataLayoutEntryInterface> keyEntries;
   llvm::MapVector<TypeAttr, DataLayoutEntryInterface> typeEntries;
   MLIRContext *context;
-  DataLayoutSpecInterface dataLayout;
 };
 
 } // namespace LLVM
 } // namespace mlir
 
-#endif // MLIR_LLVMIR_DATALAYOUTIMPORTER_H_
+#endif // MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H_
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
deleted file mode 100644
index e34375076ffd1..0000000000000
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrAndEnumDefs.td
+++ /dev/null
@@ -1,10 +0,0 @@
-//===-- LLVMAttrDefs.td - Solely LLVM Attribute and Enum definitions ----*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
-include "mlir/Dialect/LLVMIR/LLVMEnums.td"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index bf8e285ac61f3..10b59e8369a64 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -15,127 +15,6 @@ include "mlir/IR/AttrTypeBase.td"
 include "mlir/IR/CommonAttrConstraints.td"
 include "mlir/Interfaces/DataLayoutInterfaces.td"
 
-//===----------------------------------------------------------------------===//
-// LLVM_TargetAttr
-//===----------------------------------------------------------------------===//
-
-def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
-                                [LLVM_TargetAttrInterface]> {
-  let summary = "LLVM target info: triple, chip, features";
-  let description = [{
-    An attribute to hold LLVM target information, specifying LLVM's target
-    `triple` string, the target `chip` string (i.e. the `cpu` string), and
-    target `features` string as an attribute. The latter two are optional.
-
-    Has facilities to obtain the corresponding `llvm::TargetMachine` and
-    `llvm::DataLayout`, given the relevant LLVM backend is loaded.
-
-    ---
-
-    Responds to DLTI-queries on the keys:
-       * A query for `"triple"` returns the `StringAttr` for the `triple`.
-       * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`, if provided.
-       * A query for `"features"` returns the `TargetFeaturesAttr`, if provided.
-         * Individual features can be queried for on this attribute.
-  }];
-  let parameters = (ins "StringAttr":$triple,
-                        "StringAttr":$chip,
-                        OptionalParameter<"StringAttr">:$features);
-
-  let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
-
-  let extraClassDeclaration = [{
-    FailureOr<std::unique_ptr<llvm::TargetMachine>> getTargetMachine();
-    FailureOr<llvm::DataLayout> getDataLayout();
-    FailureOr<Attribute> query(DataLayoutEntryKey key);
-  }];
-}
-
-//===----------------------------------------------------------------------===//
-// LLVM_DataLayoutAttr
-//===----------------------------------------------------------------------===//
-
-def LLVM_DataLayoutAttr
-    : LLVM_Attr<"DataLayout", "data_layout", [DataLayoutSpecInterface]> {
-  let summary = "LLVM data layout string, exposed through DLTI";
-  let description = [{
-    An attribute to hold a LLVM data layout string.
-
-    The LLVM data layout string is parsed and mapped to the corresponding MLIR
-    data layout specification. The `#llvm.data_layout` attribute then serves as
-    a proxy, forwarding all DLTI queries to the underlying MLIR data layout
-    specification.
-  }];
-  let parameters = (ins "StringAttr":$data_layout_str,
-                         OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
-  let builders = [
-    AttrBuilder<(ins "llvm::StringRef":$data_layout_str), [{
-      auto importer = LLVM::DataLayoutImporter($_ctxt, data_layout_str);
-      auto dataLayoutSpec = importer.getDataLayout();
-      return $_get($_ctxt, mlir::StringAttr::get($_ctxt, data_layout_str), dataLayoutSpec);
-    }]>
-  ];
-  let assemblyFormat = "`<` $data_layout_str `>`";
-  let extraClassDeclaration = [{
-    template <typename Ty>
-    DataLayoutEntryList getSpecForType() {
-      return getDataLayoutSpec().getSpecForType(TypeID::get<Ty>());
-    }
-
-    void bucketEntriesByType(
-        ::llvm::MapVector<::mlir::TypeID, ::mlir::DataLayoutEntryList> &types,
-        ::llvm::MapVector<::mlir::StringAttr,
-                          ::mlir::DataLayoutEntryInterface> &ids) {
-      getDataLayoutSpec().bucketEntriesByType(types, ids);
-    };
-
-    ::mlir::DataLayoutSpecInterface
-    combineWith(ArrayRef<::mlir::DataLayoutSpecInterface> specs) const {
-      return getDataLayoutSpec().combineWith(specs);
-    }
-    DataLayoutEntryListRef getEntries() const { return getDataLayoutSpec().getEntries(); }
-    LogicalResult verifySpec(Location loc) {
-      return getDataLayoutSpec().verifySpec(loc);
-    }
-    StringAttr getEndiannessIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getEndiannessIdentifier(context);
-    }
-    StringAttr getDefaultMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getDefaultMemorySpaceIdentifier(context);
-    }
-    StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getAllocaMemorySpaceIdentifier(context);
-    }
-    StringAttr getManglingModeIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getManglingModeIdentifier(context);
-    }
-    StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getProgramMemorySpaceIdentifier(context);
-    }
-    StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getGlobalMemorySpaceIdentifier(context);
-    }
-    StringAttr getStackAlignmentIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getStackAlignmentIdentifier(context);
-    }
-    StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getFunctionPointerAlignmentIdentifier(context);
-    }
-    StringAttr getLegalIntWidthsIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getLegalIntWidthsIdentifier(context);
-    }
-    ::mlir::DataLayoutEntryList getSpecForType(TypeID type) const {
-      return getDataLayoutSpec().getSpecForType(type);
-    }
-    ::mlir::DataLayoutEntryInterface getSpecForIdentifier(StringAttr identifier) const {
-      return getDataLayoutSpec().getSpecForIdentifier(identifier);
-    }
-    FailureOr<Attribute> query(DataLayoutEntryKey key) const {
-      return getDataLayoutSpec().query(key);
-    }
-  }];
-}
-
 //===----------------------------------------------------------------------===//
 // CConvAttr
 //===----------------------------------------------------------------------===//
@@ -1355,6 +1234,190 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
   let assemblyFormat = "`<` struct(params) `>`";
 }
 
+//===----------------------------------------------------------------------===//
+// TargetFeaturesAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> {
+  let summary = "LLVM target features attribute";
+
+  let description = [{
+    Represents the LLVM target features as a list that can be checked within
+    passes/rewrites.
+
+    Example:
+    ```mlir
+    #llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
+    ```
+
+    Then within a pass or rewrite the features active at an op can be queried:
+
+    ```c++
+    auto targetFeatures = LLVM::TargetFeaturesAttr::featuresAt(op);
+
+    if (!targetFeatures.contains("+sme-f64f64"))
+      return failure();
+    ```
+  }];
+
+  let parameters = (ins OptionalArrayRefParameter<"StringAttr">:$features);
+
+  let builders = [
+    TypeBuilder<(ins "::llvm::StringRef":$features)>,
+    TypeBuilder<(ins "::llvm::ArrayRef<::llvm::StringRef>":$features)>
+  ];
+
+  let extraClassDeclaration = [{
+    /// Checks if a feature is contained within the features list.
+    /// Note: Using a StringAttr allows doing pointer-comparisons.
+    bool contains(::mlir::StringAttr feature) const;
+    bool contains(::llvm::StringRef feature) const;
+
+    bool nullOrEmpty() const {
+      // Checks if this attribute is null, or the features are empty.
+      return !bool(*this) || getFeatures().empty();
+    }
+
+    /// Returns the list of features as an LLVM-compatible string.
+    std::string getFeaturesString() const;
+
+    /// Finds the target features on the parent FunctionOpInterface.
+    /// Note: This assumes the attribute name matches the return value of
+    /// `getAttributeName()`.
+    static TargetFeaturesAttr featuresAt(Operation* op);
+
+    /// Canonical name for this attribute within MLIR.
+    static constexpr StringLiteral getAttributeName() {
+      return StringLiteral("target_features");
+    }
+  }];
+
+  let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
+  let genVerifyDecl = 1;
+}
+
+//===----------------------------------------------------------------------===//
+// LLVM_TargetAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
+                                [DLTIQueryInterface]> {
+  let summary = "LLVM target info: triple, chip, features";
+  let description = [{
+    An attribute to hold LLVM target information, specifying LLVM's target
+    `triple` string, the target `chip` string (i.e. the `cpu` string), and
+    target `features` string as an attribute. The latter two are optional.
+
+    Has facilities to obtain the corresponding `llvm::TargetMachine` and
+    `llvm::DataLayout`, given the relevant LLVM backend is loaded.
+
+    ---
+
+    Responds to DLTI-queries on the keys:
+       * A query for `"triple"` returns the `StringAttr` for the `triple`.
+       * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`.
+       * A query for `"features"` returns the `StringAttr`, if provided.
+  }];
+  let parameters = (ins "StringAttr":$triple,
+                        "StringAttr":$chip,
+                        OptionalParameter<"StringAttr", "">:$features);
+
+  let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
+
+  let extraClassDeclaration = [{
+    FailureOr<Attribute> query(DataLayoutEntryKey key);
+  }];
+}
+
+//===----------------------------------------------------------------------===//
+// LLVM_DataLayoutAttr
+//===----------------------------------------------------------------------===//
+
+def LLVM_DataLayoutAttr
+    : LLVM_Attr<"DataLayout", "data_layout", [DataLayoutSpecInterface]> {
+  let summary = "LLVM data layout string, exposed through DLTI";
+  let description = [{
+    An attribute to hold a LLVM data layout string.
+
+    The LLVM data layout string is parsed and mapped to the corresponding MLIR
+    data layout specification. The `#llvm.data_layout` attribute then serves as
+    a proxy, forwarding all DLTI queries to the underlying MLIR data layout
+    specification.
+
+    The default data layout string specified in the language reference
+    (https://llvm.org/docs/LangRef.html#data-layout) is used to derive
+    unspecified elements of the data layout string.
+  }];
+  let parameters = (ins OptionalParameter<"StringAttr", "\"\"">:$data_layout_str,
+                        OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
+  let builders = [
+    AttrBuilder<(ins "llvm::StringRef":$data_layout_str), [{
+      auto importer = LLVM::DataLayoutImporter($_ctxt, data_layout_str);
+      auto dataLayoutSpec = importer.getDataLayoutSpec();
+      return $_get($_ctxt, mlir::StringAttr::get($_ctxt, data_layout_str), dataLayoutSpec);
+    }]>
+  ];
+  let assemblyFormat = "(`<` $data_layout_str^ `>`)?";
+  let extraClassDeclaration = [{
+    // Forward all DataLayoutSpecInterface methods to the underlying
+    // DataLayoutSpecInterface.
+    template <typename Ty>
+    DataLayoutEntryList getSpecForType() {
+      return getDataLayoutSpec().getSpecForType(TypeID::get<Ty>());
+    }
+    void bucketEntriesByType(
+        ::llvm::MapVector<::mlir::TypeID, ::mlir::DataLayoutEntryList> &types,
+        ::llvm::MapVector<::mlir::StringAttr,
+                          ::mlir::DataLayoutEntryInterface> &ids) {
+      getDataLayoutSpec().bucketEntriesByType(types, ids);
+    }
+    ::mlir::DataLayoutSpecInterface
+    combineWith(ArrayRef<::mlir::DataLayoutSpecInterface> specs) const {
+      return getDataLayoutSpec().combineWith(specs);
+    }
+    DataLayoutEntryListRef getEntries() const { return getDataLayoutSpec().getEntries(); }
+    LogicalResult verifySpec(Location loc) {
+      return getDataLayoutSpec().verifySpec(loc);
+    }
+    StringAttr getEndiannessIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getEndiannessIdentifier(context);
+    }
+    StringAttr getDefaultMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getDefaultMemorySpaceIdentifier(context);
+    }
+    StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getAllocaMemorySpaceIdentifier(context);
+    }
+    StringAttr getManglingModeIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getManglingModeIdentifier(context);
+    }
+    StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getProgramMemorySpaceIdentifier(context);
+    }
+    StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getGlobalMemorySpaceIdentifier(context);
+    }
+    StringAttr getStackAlignmentIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getStackAlignmentIdentifier(context);
+    }
+    StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getFunctionPointerAlignmentIdentifier(context);
+    }
+    StringAttr getLegalIntWidthsIdentifier(MLIRContext *context) const {
+      return getDataLayoutSpec().getLegalIntWidthsIdentifier(context);
+    }
+    ::mlir::DataLayoutEntryList getSpecForType(TypeID type) const {
+      return getDataLayoutSpec().getSpecForType(type);
+    }
+    ::mlir::DataLayoutEntryInterface getSpecForIdentifier(StringAttr identifier) const {
+      return getDataLayoutSpec().getSpecForIdentifier(identifier);
+    }
+    FailureOr<Attribute> query(DataLayoutEntryKey key) const {
+      return getDataLayoutSpec().query(key);
+    }
+  }];
+}
+
 //===----------------------------------------------------------------------===//
 // UndefAttr
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index 14645d5dee95f..c5fec8d02af5d 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -16,12 +16,13 @@
 
 #include "mlir/IR/OpImplementation.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
-#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Target/TargetMachine.h"
 #include <optional>
 
 #include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
 
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/IR/DataLayout.h"
+
 namespace mlir {
 namespace LLVM {
 
@@ -96,12 +97,6 @@ using tailcallkind::TailCallKind;
 } // namespace LLVM
 } // namespace mlir
 
-// First obtain TargetFeaturesAttr definitions as it is used both an LLVMIR
-// interface and that interface and this attribute are turn required by another
-// LLVMIR attribute.
-#define GET_ATTRDEF_CLASSES
-#include "mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.h.inc"
-
 #include "mlir/Dialect/LLVMIR/LLVMAttrInterfaces.h.inc"
 
 #define GET_ATTRDEF_CLASSES
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
index d3e5408b73764..c8d2bf4d35cb4 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
@@ -13,6 +13,7 @@
 #ifndef MLIR_DIALECT_LLVMIR_LLVMINTERFACES_H_
 #define MLIR_DIALECT_LLVMIR_LLVMINTERFACES_H_
 
+#include "llvm/Target/TargetMachine.h"
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
 
 namespace mlir {
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index e07fd5982449c..54a706ddb2064 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -538,36 +538,33 @@ def LLVM_TargetAttrInterface
   let description = [{
     Interface for attributes that describe LLVM targets.
 
-    These attributes should be able to return the specified target
-    `triple`, `chip` and `features` and are expected to be able to
-    produce the corresponding `llvm::TargetMachine` and
-    `llvm::DataLayout`. These methods can fail in case the backend
-    is not available.
-
-    Implementing attributes should provide a
-    `DLTIQueryInterface::query()` implementation which responds to
-    keys `"triple"`, `"chip"` and `"features"` by returning an
-    appropriate `StringAttr`, `StringAttr` and
-    `LLVM_TargetFeaturesAttr`.
+    These attributes should be able to return the specified target `triple`,
+    `chip` and `features` and are expected to be able to produce the
+    corresponding `llvm::TargetMachine` and `llvm::DataLayout`. These methods
+    can fail in case the backend is not available.
+
+    Implementing attributes should provide a `DLTIQueryInterface::query()`
+    implementation which responds to keys `"triple"`, `"chip"` and `"features"`
+    by returning appropriate `StringAttr`s.
   }];
   let cppNamespace = "::mlir::LLVM";
   let methods = [
     InterfaceMethod<
       /*description=*/"Returns the target triple identifier.",
-      /*retTy=*/"::llvm::StringRef",
-      /*methodName=*/"getTriple",
+      /*retTy=*/"StringAttr",
+      /*methodName=*/"getTripleAttr",
       /*args=*/(ins)
     >,
     InterfaceMethod<
       /*description=*/"Returns the target chip (i.e. \"cpu\") identifier.",
-      /*retTy=*/"::llvm::StringRef",
-      /*methodName=*/"getChip",
+      /*retTy=*/"StringAttr",
+      /*methodName=*/"getChipAttr",
       /*args=*/(ins)
     >,
     InterfaceMethod<
       /*description=*/"Returns the target features as a string.",
-      /*retTy=*/"::llvm::StringRef",
-      /*methodName=*/"getFeatures",
+      /*retTy=*/"StringAttr",
+      /*methodName=*/"getFeaturesAttr",
       /*args=*/(ins)
     >,
     InterfaceMethod<
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index 36a6291b5e3a8..f4c1640098320 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -14,7 +14,6 @@
 #define LLVMIR_OPS
 
 include "mlir/Dialect/LLVMIR/LLVMAttrDefs.td"
-include "mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td"
 include "mlir/Dialect/LLVMIR/LLVMEnums.td"
 include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
 include "mlir/IR/EnumAttr.td"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td
deleted file mode 100644
index 2183f083103f5..0000000000000
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMTargetFeaturesAttrDefs.td
+++ /dev/null
@@ -1,82 +0,0 @@
-//===-- LLVMAttrDefs.td - LLVM Attributes definition file --*- tablegen -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVMIR_TARGETFEATURESATTRDEFS
-#define LLVMIR_TARGETFEATURESATTRDEFS
-
-include "mlir/Dialect/LLVMIR/LLVMDialect.td"
-include "mlir/IR/CommonAttrConstraints.td"
-include "mlir/Interfaces/DataLayoutInterfaces.td"
-
-//===----------------------------------------------------------------------===//
-// TargetFeaturesAttr
-//===----------------------------------------------------------------------===//
-
-def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features",
-    [DLTIQueryInterface]> {
-  let summary = "LLVM target features attribute";
-
-  let description = [{
-    Represents the LLVM target features as a list that can be checked within
-    passes/rewrites.
-
-    Example:
-    ```mlir
-    #llvm.target_features<["+sme", "+sve", "+sme-f64f64"]>
-    ```
-
-    Then within a pass or rewrite the features active at an op can be queried:
-
-    ```c++
-    auto targetFeatures = LLVM::TargetFeaturesAttr::featuresAt(op);
-
-    if (!targetFeatures.contains("+sme-f64f64"))
-      return failure();
-    ```
-  }];
-
-  let parameters = (ins OptionalArrayRefParameter<"StringAttr">:$features);
-
-  let builders = [
-    TypeBuilder<(ins "::llvm::StringRef":$features)>,
-    TypeBuilder<(ins "::llvm::ArrayRef<::llvm::StringRef>":$features)>
-  ];
-
-  let extraClassDeclaration = [{
-    /// Checks if a feature is contained within the features list.
-    /// Note: Using a StringAttr allows doing pointer-comparisons.
-    bool contains(::mlir::StringAttr feature) const;
-    bool contains(::llvm::StringRef feature) const;
-
-    bool nullOrEmpty() const {
-      // Checks if this attribute is null, or the features are empty.
-      return !bool(*this) || getFeatures().empty();
-    }
-
-    /// Returns the list of features as an LLVM-compatible string.
-    std::string getFeaturesString() const;
-
-    /// Finds the target features on the parent FunctionOpInterface.
-    /// Note: This assumes the attribute name matches the return value of
-    /// `getAttributeName()`.
-    static TargetFeaturesAttr featuresAt(Operation* op);
-
-    /// Canonical name for this attribute within MLIR.
-    static constexpr StringLiteral getAttributeName() {
-      return StringLiteral("target_features");
-    }
-
-    /// Returns the attribute associated with the key.
-    FailureOr<Attribute> query(DataLayoutEntryKey key);
-  }];
-
-  let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
-  let genVerifyDecl = 1;
-}
-
-#endif // LLVMIR_TARGETFEATURESATTRDEFS
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index c6fcf1a0d510b..75903a89ae0ac 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -100,6 +100,7 @@
 #include "mlir/Dialect/XeGPU/IR/XeGPU.h"
 #include "mlir/IR/Dialect.h"
 #include "mlir/Interfaces/CastInterfaces.h"
+#include "mlir/Target/LLVM/Target.h"
 #include "mlir/Target/LLVM/NVVM/Target.h"
 #include "mlir/Target/LLVM/ROCDL/Target.h"
 #include "mlir/Target/SPIRV/Target.h"
@@ -172,6 +173,7 @@ inline void registerAllDialects(DialectRegistry &registry) {
   gpu::registerBufferDeallocationOpInterfaceExternalModels(registry);
   gpu::registerValueBoundsOpInterfaceExternalModels(registry);
   LLVM::registerInlinerInterface(registry);
+  LLVM::registerLLVMTargetInterfaceExternalModels(registry);
   NVVM::registerInlinerInterface(registry);
   linalg::registerAllDialectInterfaceImplementations(registry);
   linalg::registerRuntimeVerifiableOpInterfaceExternalModels(registry);
diff --git a/mlir/include/mlir/Target/LLVM/Target.h b/mlir/include/mlir/Target/LLVM/Target.h
new file mode 100644
index 0000000000000..bb389906ed298
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVM/Target.h
@@ -0,0 +1,30 @@
+//===- Target.h - MLIR LLVM target registration -----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides registration calls for attaching the LLVM target interface.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVM_TARGET_H
+#define MLIR_TARGET_LLVM_TARGET_H
+
+namespace mlir {
+class DialectRegistry;
+class MLIRContext;
+namespace LLVM {
+/// Registers the `TargetAttrInterface` for the `#llvm.target` attribute in the
+/// given registry.
+void registerLLVMTargetInterfaceExternalModels(DialectRegistry &registry);
+
+/// Registers the `TargetAttrInterface` for the `#llvm.target` attribute in the
+/// registry associated with the given context.
+void registerLLVMTargetInterfaceExternalModels(MLIRContext &context);
+} // namespace LLVM
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVM_TARGET_H
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index c3dea62df14c2..d698a6cb43e00 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -14,7 +14,6 @@ add_mlir_dialect_library(MLIRLLVMDialect
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/Dialect/LLVMIR
 
   DEPENDS
-  MLIRLLVMTargetFeaturesAttrsIncGen
   MLIRLLVMOpsIncGen
   MLIRLLVMTypesIncGen
   MLIRLLVMIntrinsicOpsIncGen
@@ -28,14 +27,6 @@ add_mlir_dialect_library(MLIRLLVMDialect
   BitReader
   BitWriter
   Core
-  MC
-  Target
-  Support
-  TargetParser
-  AllTargetsAsmParsers
-  AllTargetsCodeGens
-  AllTargetsDescs
-  AllTargetsInfos
 
   LINK_LIBS PUBLIC
   MLIRCallInterfaces
diff --git a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
index 988fe27e7cd8e..4f210918f8ce4 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
@@ -13,7 +13,6 @@
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
 #include "mlir/Target/LLVMIR/Import.h"
-#include "llvm/IR/DataLayout.h"
 
 using namespace mlir;
 using namespace mlir::LLVM;
@@ -274,89 +273,90 @@ DataLayoutImporter::tryToEmplaceLegalIntWidthsEntry(StringRef token) {
   return success();
 }
 
-void DataLayoutImporter::translateDataLayoutFromStr() {
-  if (!layoutStr.empty())
-    layoutStr += "-";
-  layoutStr += kDefaultDataLayout;
-  StringRef layout(layoutStr);
+DataLayoutSpecInterface
+DataLayoutImporter::dataLayoutSpecFromDataLayoutStr(StringRef dataLayoutStr) {
+  std::string dataLayoutStrToParse(dataLayoutStr);
+  if (!dataLayoutStrToParse.empty())
+    dataLayoutStrToParse += "-";
+  dataLayoutStrToParse += kDefaultDataLayout;
 
   // Split the data layout string into tokens separated by a dash.
   SmallVector<StringRef> tokens;
-  layout.split(tokens, '-');
+  StringRef(dataLayoutStrToParse).split(tokens, '-');
 
   for (StringRef token : tokens) {
     lastToken = token;
     FailureOr<StringRef> prefix = tryToParseAlphaPrefix(token);
     if (failed(prefix))
-      return;
+      return {};
 
     // Parse the endianness.
     if (*prefix == "e") {
       if (failed(tryToEmplaceEndiannessEntry(
               DLTIDialect::kDataLayoutEndiannessLittle, token)))
-        return;
+        return {};
       continue;
     }
     if (*prefix == "E") {
       if (failed(tryToEmplaceEndiannessEntry(
               DLTIDialect::kDataLayoutEndiannessBig, token)))
-        return;
+        return {};
       continue;
     }
     // Parse the program address space.
     if (*prefix == "P") {
       if (failed(tryToEmplaceAddrSpaceEntry(
               token, DLTIDialect::kDataLayoutProgramMemorySpaceKey)))
-        return;
+        return {};
       continue;
     }
     // Parse the mangling mode.
     if (*prefix == "m") {
       if (failed(tryToEmplaceManglingModeEntry(
               token, DLTIDialect::kDataLayoutManglingModeKey)))
-        return;
+        return {};
       continue;
     }
     // Parse the global address space.
     if (*prefix == "G") {
       if (failed(tryToEmplaceAddrSpaceEntry(
               token, DLTIDialect::kDataLayoutGlobalMemorySpaceKey)))
-        return;
+        return {};
       continue;
     }
     // Parse the alloca address space.
     if (*prefix == "A") {
       if (failed(tryToEmplaceAddrSpaceEntry(
               token, DLTIDialect::kDataLayoutAllocaMemorySpaceKey)))
-        return;
+        return {};
       continue;
     }
     // Parse the stack alignment.
     if (*prefix == "S") {
       if (failed(tryToEmplaceStackAlignmentEntry(token)))
-        return;
+        return {};
       continue;
     }
     // Parse integer alignment specifications.
     if (*prefix == "i") {
       FailureOr<uint64_t> width = tryToParseInt(token);
       if (failed(width))
-        return;
+        return {};
 
       Type type = IntegerType::get(context, *width);
       if (failed(tryToEmplaceAlignmentEntry(type, token)))
-        return;
+        return {};
       continue;
     }
     // Parse float alignment specifications.
     if (*prefix == "f") {
       FailureOr<uint64_t> width = tryToParseInt(token);
       if (failed(width))
-        return;
+        return {};
 
       Type type = getFloatType(context, *width);
       if (failed(tryToEmplaceAlignmentEntry(type, token)))
-        return;
+        return {};
       continue;
     }
     // Parse pointer alignment specifications.
@@ -364,17 +364,17 @@ void DataLayoutImporter::translateDataLayoutFromStr() {
       FailureOr<uint64_t> space =
           token.starts_with(":") ? 0 : tryToParseInt(token);
       if (failed(space))
-        return;
+        return {};
 
       auto type = LLVMPointerType::get(context, *space);
       if (failed(tryToEmplacePointerAlignmentEntry(type, token)))
-        return;
+        return {};
       continue;
     }
     // Parse native integer widths specifications.
     if (*prefix == "n") {
       if (failed(tryToEmplaceLegalIntWidthsEntry(token)))
-        return;
+        return {};
       continue;
     }
     // Parse function pointer alignment specifications.
@@ -382,7 +382,7 @@ void DataLayoutImporter::translateDataLayoutFromStr() {
     if (prefix->starts_with("F")) {
       StringRef nextPrefix = prefix->drop_front(1);
       if (failed(tryToEmplaceFunctionPointerAlignmentEntry(nextPrefix, token)))
-        return;
+        return {};
       continue;
     }
 
@@ -397,11 +397,5 @@ void DataLayoutImporter::translateDataLayoutFromStr() {
     entries.push_back(it.second);
   for (const auto &it : keyEntries)
     entries.push_back(it.second);
-  dataLayout = DataLayoutSpecAttr::get(context, entries);
-}
-
-DataLayoutSpecInterface
-mlir::translateDataLayout(const llvm::DataLayout &dataLayout,
-                          MLIRContext *context) {
-  return DataLayoutImporter(context, dataLayout).getDataLayout();
+  return DataLayoutSpecAttr::get(context, entries);
 }
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 50e4606fbd961..64dcef8b2ccb5 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -409,59 +409,18 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
                      << key << "'";
 }
 
-FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
-  if (auto stringKey = dyn_cast<StringAttr>(key))
-    if (contains(stringKey))
-      return UnitAttr::get(getContext());
-  return failure();
-}
-
 //===----------------------------------------------------------------------===//
 // LLVM_TargetAttr
 //===----------------------------------------------------------------------===//
 
-FailureOr<std::unique_ptr<llvm::TargetMachine>> TargetAttr::getTargetMachine() {
-  llvm::InitializeAllTargets();
-  llvm::InitializeAllTargetMCs();
-
-  std::string error;
-  const llvm::Target *target =
-      llvm::TargetRegistry::lookupTarget(getTriple(), error);
-  if (!target || !error.empty()) {
-    LLVM_DEBUG({
-      llvm::dbgs() << "Looking up target '" << getTriple()
-                   << "' failed: " << error << "\n";
-    });
-    return failure();
-  }
-
-  return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
-      llvm::Triple(getTriple().strref()), getChip().strref(),
-      getFeatures() ? getFeatures().strref() : "", {}, {}));
-}
-
-FailureOr<llvm::DataLayout> TargetAttr::getDataLayout() {
-  FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
-      getTargetMachine();
-  if (failed(targetMachine)) {
-    LLVM_DEBUG({
-      llvm::dbgs()
-          << "Failed to retrieve the target machine for data layout.\n";
-    });
-    return failure();
-  }
-  return (targetMachine.value())->createDataLayout();
-}
-
 FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
-  Attribute result;
   if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
     if (stringAttrKey.getValue() == "triple")
       return getTriple();
-    if (stringAttrKey.getValue() == "chip" && (result = getChip()))
-      return result;
-    if (stringAttrKey.getValue() == "features" && (result = getFeatures()))
-      return result;
+    if (stringAttrKey.getValue() == "chip")
+      return getChip();
+    if (stringAttrKey.getValue() == "features" && getFeatures())
+      return getFeatures();
   }
 
   return failure();
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 6dcd94e6eea17..0d0e708a70e4a 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -4075,6 +4075,7 @@ void LLVMDialect::initialize() {
   // Support unknown operations because not all LLVM operations are registered.
   allowUnknownOperations();
   declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
+  declarePromisedInterface<LLVM::TargetAttrInterface, LLVM::TargetAttr>();
 }
 
 #define GET_OP_CLASSES
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
index 06990525d87ac..e3d373a4c2b89 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/DLTI/DLTI.h"
-#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/Pass/Pass.h"
 
@@ -57,8 +56,7 @@ struct DataLayoutFromTargetPass
       }
     });
 
-    if (passFailed) {
+    if (passFailed)
       return signalPassFailure();
-    }
   }
 };
diff --git a/mlir/lib/Target/LLVM/CMakeLists.txt b/mlir/lib/Target/LLVM/CMakeLists.txt
index 83fbf7a5fe5f3..ee8b9227b5643 100644
--- a/mlir/lib/Target/LLVM/CMakeLists.txt
+++ b/mlir/lib/Target/LLVM/CMakeLists.txt
@@ -1,5 +1,6 @@
-add_mlir_library(MLIRTargetLLVM
+add_mlir_dialect_library(MLIRTargetLLVM
   ModuleToObject.cpp
+  Target.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/Target/LLVM
@@ -16,6 +17,12 @@ add_mlir_library(MLIRTargetLLVM
   Passes
   Support
   Target
+  TargetParser
+  AllTargetsAsmParsers
+  AllTargetsCodeGens
+  AllTargetsDescs
+  AllTargetsInfos
+
   LINK_LIBS PUBLIC
   MLIRExecutionEngineUtils
   MLIRTargetLLVMIRExport
diff --git a/mlir/lib/Target/LLVM/Target.cpp b/mlir/lib/Target/LLVM/Target.cpp
new file mode 100644
index 0000000000000..cd0d222e707ad
--- /dev/null
+++ b/mlir/lib/Target/LLVM/Target.cpp
@@ -0,0 +1,90 @@
+//===- Target.cpp - MLIR LLVM target interface impls ------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Target/LLVM/Target.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/LLVMIR/LLVMInterfaces.h"
+
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define DEBUG_TYPE "llvm-target"
+
+using namespace mlir;
+
+namespace {
+// Implementation of the `LLVM::TargetAttrInterface` model.
+class LLVMTargetAttrImpl
+    : public LLVM::TargetAttrInterface::FallbackModel<LLVMTargetAttrImpl> {
+public:
+  FailureOr<std::unique_ptr<llvm::TargetMachine>>
+  getTargetMachine(Attribute attribute) const {
+    auto attr = llvm::cast<LLVM::TargetAttr>(attribute);
+
+    llvm::InitializeAllTargets();
+    llvm::InitializeAllTargetMCs();
+
+    std::string error;
+    const llvm::Target *target =
+        llvm::TargetRegistry::lookupTarget(attr.getTriple(), error);
+    if (!target || !error.empty()) {
+      LLVM_DEBUG({
+        llvm::dbgs() << "Looking up target '" << attr.getTriple()
+                     << "' failed: " << error << "\n";
+      });
+      return failure();
+    }
+
+    return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
+        llvm::Triple(attr.getTriple().getValue()), attr.getChip().getValue(),
+        attr.getFeatures() ? attr.getFeatures().getValue() : "", {}, {}));
+  }
+
+  FailureOr<llvm::DataLayout> getDataLayout(Attribute attribute) const {
+    auto attr = llvm::cast<LLVM::TargetAttrInterface>(attribute);
+
+    FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
+        attr.getTargetMachine();
+    if (failed(targetMachine)) {
+      LLVM_DEBUG({
+        llvm::dbgs()
+            << "Failed to retrieve the target machine for data layout.\n";
+      });
+      return failure();
+    }
+    return (targetMachine.value())->createDataLayout();
+  }
+
+  StringAttr getTripleAttr(Attribute attribute) const {
+    return llvm::cast<LLVM::TargetAttr>(attribute).getTriple();
+  }
+
+  StringAttr getChipAttr(Attribute attribute) const {
+    return llvm::cast<LLVM::TargetAttr>(attribute).getChip();
+  }
+
+  StringAttr getFeaturesAttr(Attribute attribute) const {
+    return llvm::cast<LLVM::TargetAttr>(attribute).getFeatures();
+  }
+};
+} // namespace
+
+// Register the LLVM target interface.
+void LLVM::registerLLVMTargetInterfaceExternalModels(
+    DialectRegistry &registry) {
+  registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
+    LLVM::TargetAttr::attachInterface<LLVMTargetAttrImpl>(*ctx);
+  });
+}
+
+void LLVM::registerLLVMTargetInterfaceExternalModels(MLIRContext &context) {
+  DialectRegistry registry;
+  registerLLVMTargetInterfaceExternalModels(registry);
+  context.appendDialectRegistry(registry);
+}
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
index e1cd39cf87b8f..cb83a8832d80f 100644
--- a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
+++ b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
@@ -18,7 +18,6 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = ""
 // CHECK-SAME:   features = "+mmx,+sse"
-// CHECK-NOT:    chip = "skylake"
 
 module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
                                                chip = "",

>From 53d4d168135e180bb164a6fa630ad2b966545595 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Fri, 25 Jul 2025 07:29:36 -0700
Subject: [PATCH 10/18] ModuleImport fixes

---
 mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h |  5 ++---
 mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp     | 11 +++++------
 mlir/lib/Target/LLVMIR/ModuleImport.cpp               |  7 ++++---
 3 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
index 3f07c6a7b4726..ed2b5000e2de9 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
@@ -58,7 +58,7 @@ class DataLayoutImporter {
     // - non-default address space pointer specifications default to the default
     //   address space pointer specification
     // - the alloca address space defaults to the default address space.
-    dataLayoutSpec = dataLayoutSpecFromDataLayoutStr(dataLayoutStr);
+    dataLayoutSpec = dataLayoutSpecFromDataLayoutStr();
   }
 
   /// Returns the MLIR data layout specification translated from the LLVM
@@ -75,8 +75,7 @@ class DataLayoutImporter {
 
 private:
   /// Translates the LLVM `dataLayout` to an MLIR data layout specification.
-  DataLayoutSpecInterface
-  dataLayoutSpecFromDataLayoutStr(StringRef dataLayoutStr);
+  DataLayoutSpecInterface dataLayoutSpecFromDataLayoutStr();
 
   /// Tries to parse the letter only prefix that identifies the specification
   /// and removes the consumed characters from the beginning of the string.
diff --git a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
index 4f210918f8ce4..7bd59f417e748 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
@@ -274,15 +274,14 @@ DataLayoutImporter::tryToEmplaceLegalIntWidthsEntry(StringRef token) {
 }
 
 DataLayoutSpecInterface
-DataLayoutImporter::dataLayoutSpecFromDataLayoutStr(StringRef dataLayoutStr) {
-  std::string dataLayoutStrToParse(dataLayoutStr);
-  if (!dataLayoutStrToParse.empty())
-    dataLayoutStrToParse += "-";
-  dataLayoutStrToParse += kDefaultDataLayout;
+DataLayoutImporter::dataLayoutSpecFromDataLayoutStr() {
+  if (!dataLayoutStr.empty())
+    dataLayoutStr += "-";
+  dataLayoutStr += kDefaultDataLayout;
 
   // Split the data layout string into tokens separated by a dash.
   SmallVector<StringRef> tokens;
-  StringRef(dataLayoutStrToParse).split(tokens, '-');
+  StringRef(dataLayoutStr).split(tokens, '-');
 
   for (StringRef token : tokens) {
     lastToken = token;
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 8b570d669a0f3..64132a5668215 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -1033,8 +1033,9 @@ LogicalResult ModuleImport::convertAliases() {
 
 LogicalResult ModuleImport::convertDataLayout() {
   Location loc = mlirModule.getLoc();
-  DataLayoutImporter dataLayoutImporter(context, llvmModule->getDataLayout());
-  if (!dataLayoutImporter.getDataLayout())
+  DataLayoutImporter dataLayoutImporter(
+      context, llvmModule->getDataLayout().getStringRepresentation());
+  if (!dataLayoutImporter.getDataLayoutSpec())
     return emitError(loc, "cannot translate data layout: ")
            << dataLayoutImporter.getLastToken();
 
@@ -1042,7 +1043,7 @@ LogicalResult ModuleImport::convertDataLayout() {
     emitWarning(loc, "unhandled data layout token: ") << token;
 
   mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
-                      dataLayoutImporter.getDataLayout());
+                      dataLayoutImporter.getDataLayoutSpec());
   return success();
 }
 

>From 33d70a897c115692c6903ca2e7860fd0bbc50aaa Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Fri, 25 Jul 2025 09:41:34 -0700
Subject: [PATCH 11/18] Fixes and cleanup and target dependence for test cases

---
 flang/include/flang/Optimizer/Dialect/FIRType.h     |  1 -
 .../mlir/Dialect/LLVMIR/DataLayoutImporter.h        |  9 ++++-----
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td    | 13 +++++++++++--
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h        |  2 +-
 mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td     |  8 --------
 mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h   |  1 -
 .../mlir/Dialect/LLVMIR/Transforms/Passes.td        |  7 +++++--
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp            |  4 +---
 .../LLVMIR/Transforms/DataLayoutFromTarget.cpp      |  3 +--
 mlir/lib/Target/LLVM/Target.cpp                     |  1 -
 .../LLVMIR/data-layout-from-target-invalid.mlir     |  1 +
 .../Dialect/LLVMIR/data-layout-from-target.mlir     |  1 +
 12 files changed, 25 insertions(+), 26 deletions(-)

diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index 83077aef8d08d..ecab12de55d61 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -13,7 +13,6 @@
 #ifndef FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
 #define FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
 
-#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
diff --git a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
index ed2b5000e2de9..f820833cb7a17 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H_
-#define MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H_
+#ifndef MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H
+#define MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H
 
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
@@ -38,8 +38,6 @@ namespace detail {
 /// null if the bit width is not supported.
 FloatType getFloatType(MLIRContext *context, unsigned width);
 
-} // namespace detail
-
 /// Helper class that translates an LLVM data layout string to an MLIR data
 /// layout specification. Only integer, float, pointer, alloca memory space,
 /// stack alignment, and endianness entries are translated. The class also
@@ -135,7 +133,8 @@ class DataLayoutImporter {
   MLIRContext *context;
 };
 
+} // namespace detail
 } // namespace LLVM
 } // namespace mlir
 
-#endif // MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H_
+#endif // MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 10b59e8369a64..6b3bd709a7ad0 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -15,6 +15,14 @@ include "mlir/IR/AttrTypeBase.td"
 include "mlir/IR/CommonAttrConstraints.td"
 include "mlir/Interfaces/DataLayoutInterfaces.td"
 
+// All of the attributes will extend this class.
+class LLVM_Attr<string name, string attrMnemonic,
+                list<Trait> traits = [],
+                string baseCppClass = "::mlir::Attribute">
+    : AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
+  let mnemonic = attrMnemonic;
+}
+
 //===----------------------------------------------------------------------===//
 // CConvAttr
 //===----------------------------------------------------------------------===//
@@ -1238,7 +1246,8 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
 // TargetFeaturesAttr
 //===----------------------------------------------------------------------===//
 
-def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> {
+def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
+{
   let summary = "LLVM target features attribute";
 
   let description = [{
@@ -1352,7 +1361,7 @@ def LLVM_DataLayoutAttr
                         OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
   let builders = [
     AttrBuilder<(ins "llvm::StringRef":$data_layout_str), [{
-      auto importer = LLVM::DataLayoutImporter($_ctxt, data_layout_str);
+      auto importer = LLVM::detail::DataLayoutImporter($_ctxt, data_layout_str);
       auto dataLayoutSpec = importer.getDataLayoutSpec();
       return $_get($_ctxt, mlir::StringAttr::get($_ctxt, data_layout_str), dataLayoutSpec);
     }]>
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index c5fec8d02af5d..9bbb50fb84b83 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -20,8 +20,8 @@
 
 #include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
 
-#include "llvm/Target/TargetMachine.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/Target/TargetMachine.h"
 
 namespace mlir {
 namespace LLVM {
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
index e924be32da10f..b5ea8fc5da500 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
@@ -10,7 +10,6 @@
 #define LLVMIR_DIALECT
 
 include "mlir/IR/DialectBase.td"
-include "mlir/IR/AttrTypeBase.td"
 
 def LLVM_Dialect : Dialect {
   let name = "llvm";
@@ -124,11 +123,4 @@ def LLVM_Dialect : Dialect {
   }];
 }
 
-class LLVM_Attr<string name, string attrMnemonic,
-                list<Trait> traits = [],
-                string baseCppClass = "::mlir::Attribute">
-    : AttrDef<LLVM_Dialect, name, traits, baseCppClass> {
-  let mnemonic = attrMnemonic;
-}
-
 #endif  // LLVMIR_DIALECT
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
index c8d2bf4d35cb4..d3e5408b73764 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.h
@@ -13,7 +13,6 @@
 #ifndef MLIR_DIALECT_LLVMIR_LLVMINTERFACES_H_
 #define MLIR_DIALECT_LLVMIR_LLVMINTERFACES_H_
 
-#include "llvm/Target/TargetMachine.h"
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
 
 namespace mlir {
diff --git a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
index 5920c3b7b0332..9a13d8e7ad22b 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
@@ -46,10 +46,13 @@ def LLVMRequestCWrappersPass
 }
 
 def LLVMDataLayoutFromTarget : Pass<"llvm-data-layout-from-target", "::mlir::ModuleOp"> {
-  let summary = "TODO";
+  let summary = "Derive data layout attributes from LLVM target attributes";
   let dependentDialects = ["mlir::DLTIDialect"];
   let description = [{
-  TODO
+    Checks modules for LLVM-dialect's `TargetAttrInterface`-implementing
+    attributes and derives `DataLayoutSpecInterface`-implementing data layout
+    attributes from the specified target by querying the corresponding
+    LLVM-backend.
   }];
 }
 
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 64dcef8b2ccb5..93e85c06c65bb 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -21,9 +21,7 @@
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DebugInfoMetadata.h"
-#include "llvm/Support/TargetSelect.h"
-
-#define DEBUG_TYPE "llvm-attrs"
+//#include "llvm/Support/TargetSelect.h"
 
 using namespace mlir;
 using namespace mlir::LLVM;
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
index e3d373a4c2b89..3eccadffb86ac 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
@@ -18,7 +18,6 @@ namespace LLVM {
 } // namespace mlir
 
 using namespace mlir;
-using namespace mlir::LLVM;
 
 struct DataLayoutFromTargetPass
     : public LLVM::impl::LLVMDataLayoutFromTargetBase<
@@ -41,7 +40,7 @@ struct DataLayoutFromTargetPass
         passFailed = true;
         return;
       }
-      auto dataLayoutAttr = DataLayoutAttr::get(
+      auto dataLayoutAttr = LLVM::DataLayoutAttr::get(
           &getContext(), dataLayout->getStringRepresentation());
 
       StringRef dlSpecIdentifier = "dlti.dl_spec";
diff --git a/mlir/lib/Target/LLVM/Target.cpp b/mlir/lib/Target/LLVM/Target.cpp
index cd0d222e707ad..a82256551f2b6 100644
--- a/mlir/lib/Target/LLVM/Target.cpp
+++ b/mlir/lib/Target/LLVM/Target.cpp
@@ -19,7 +19,6 @@
 using namespace mlir;
 
 namespace {
-// Implementation of the `LLVM::TargetAttrInterface` model.
 class LLVMTargetAttrImpl
     : public LLVM::TargetAttrInterface::FallbackModel<LLVMTargetAttrImpl> {
 public:
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
index 71526663abf96..1398ae3016705 100644
--- a/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
@@ -1,3 +1,4 @@
+// REQUIRES: target=x86{{.*}}
 // RUN: mlir-opt %s -llvm-data-layout-from-target --split-input-file --verify-diagnostics
 
 // expected-error @+1 {{failed to obtain llvm::DataLayout from #llvm.target}}
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
index cb83a8832d80f..e69d47d20476a 100644
--- a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
+++ b/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
@@ -1,3 +1,4 @@
+// REQUIRES: target=x86{{.*}}
 // RUN: mlir-opt -llvm-data-layout-from-target -split-input-file %s | FileCheck %s
 
 // CHECK: module attributes

>From 5c1d9851420d00420ab97e823e4998b076064083 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Fri, 25 Jul 2025 10:08:09 -0700
Subject: [PATCH 12/18] Remove commented code

---
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 93e85c06c65bb..22644c9fead01 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -21,7 +21,6 @@
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DebugInfoMetadata.h"
-//#include "llvm/Support/TargetSelect.h"
 
 using namespace mlir;
 using namespace mlir::LLVM;

>From 046733d006cf9441c6791a8e79e0768470452b86 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Mon, 18 Aug 2025 07:22:33 -0700
Subject: [PATCH 13/18] Address remaining comments

---
 mlir/include/mlir/CMakeLists.txt              |   1 +
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 112 ++----------------
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h  |   3 -
 .../mlir/Dialect/LLVMIR/LLVMDialect.td        |   1 +
 .../mlir/Dialect/LLVMIR/LLVMInterfaces.td     |  16 +--
 .../mlir/Dialect/LLVMIR/Transforms/Passes.td  |  11 --
 mlir/include/mlir/InitAllDialects.h           |   2 -
 mlir/include/mlir/InitAllPasses.h             |   2 +
 mlir/include/mlir/Target/CMakeLists.txt       |   1 +
 mlir/include/mlir/Target/LLVM/Target.h        |  30 -----
 .../include/mlir/Target/LLVMIR/CMakeLists.txt |   1 +
 .../LLVMIR/DataLayoutImporter.h               |   0
 .../Target/LLVMIR/Transforms/CMakeLists.txt   |   5 +
 .../mlir/Target/LLVMIR/Transforms/Passes.h    |  27 +++++
 .../mlir/Target/LLVMIR/Transforms/Passes.td   |  30 +++++
 mlir/lib/Dialect/DLTI/DLTI.cpp                |   2 +-
 mlir/lib/Dialect/LLVMIR/CMakeLists.txt        |   1 -
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp      |   6 +-
 mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp    |   1 -
 .../Dialect/LLVMIR/Transforms/CMakeLists.txt  |   1 -
 .../Transforms/DataLayoutFromTarget.cpp       |  61 ----------
 mlir/lib/Target/LLVM/CMakeLists.txt           |   8 +-
 mlir/lib/Target/LLVM/Target.cpp               |  89 --------------
 mlir/lib/Target/LLVMIR/CMakeLists.txt         |   3 +
 .../LLVMIR}/DataLayoutImporter.cpp            |   2 +-
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       |   2 +-
 .../Target/LLVMIR/Transforms/CMakeLists.txt   |  30 +++++
 .../LLVMIR/Transforms/TargetToDataLayout.cpp  | 104 ++++++++++++++++
 .../data-layout-from-target-invalid.mlir      |   9 --
 .../LLVMIR/target-to-data-layout-invalid.mlir |   9 ++
 .../LLVMIR/target-to-data-layout-no-init.mlir |  12 ++
 ...target.mlir => target-to-data-layout.mlir} |  20 ++--
 32 files changed, 261 insertions(+), 341 deletions(-)
 create mode 100644 mlir/include/mlir/Target/CMakeLists.txt
 delete mode 100644 mlir/include/mlir/Target/LLVM/Target.h
 create mode 100644 mlir/include/mlir/Target/LLVMIR/CMakeLists.txt
 rename mlir/include/mlir/{Dialect => Target}/LLVMIR/DataLayoutImporter.h (100%)
 create mode 100644 mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt
 create mode 100644 mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
 create mode 100644 mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
 delete mode 100644 mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
 delete mode 100644 mlir/lib/Target/LLVM/Target.cpp
 rename mlir/lib/{Dialect/LLVMIR/IR => Target/LLVMIR}/DataLayoutImporter.cpp (99%)
 create mode 100644 mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
 create mode 100644 mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
 delete mode 100644 mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
 create mode 100644 mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
 create mode 100644 mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
 rename mlir/test/Dialect/LLVMIR/{data-layout-from-target.mlir => target-to-data-layout.mlir} (76%)

diff --git a/mlir/include/mlir/CMakeLists.txt b/mlir/include/mlir/CMakeLists.txt
index 9cf3b442aa4ad..f88a35ba1efc7 100644
--- a/mlir/include/mlir/CMakeLists.txt
+++ b/mlir/include/mlir/CMakeLists.txt
@@ -4,4 +4,5 @@ add_subdirectory(Dialect)
 add_subdirectory(IR)
 add_subdirectory(Interfaces)
 add_subdirectory(Reducer)
+add_subdirectory(Target)
 add_subdirectory(Transforms)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 6b3bd709a7ad0..a8905a6bba71a 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1310,120 +1310,34 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
 //===----------------------------------------------------------------------===//
 
 def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
-                                [DLTIQueryInterface]> {
+                                [LLVM_TargetAttrInterface]> {
   let summary = "LLVM target info: triple, chip, features";
   let description = [{
     An attribute to hold LLVM target information, specifying LLVM's target
     `triple` string, the target `chip` string (i.e. the `cpu` string), and
-    target `features` string as an attribute. The latter two are optional.
-
-    Has facilities to obtain the corresponding `llvm::TargetMachine` and
-    `llvm::DataLayout`, given the relevant LLVM backend is loaded.
-
-    ---
+    target `features` string as an attribute. The latter is optional.
 
     Responds to DLTI-queries on the keys:
-       * A query for `"triple"` returns the `StringAttr` for the `triple`.
-       * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`.
-       * A query for `"features"` returns the `StringAttr`, if provided.
+      * A query for `"triple"` returns the `StringAttr` for the `triple`.
+      * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`.
+      * A query for `"features"` returns the `StringAttr`, if provided.
   }];
   let parameters = (ins "StringAttr":$triple,
                         "StringAttr":$chip,
                         OptionalParameter<"StringAttr", "">:$features);
 
-  let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
+  let assemblyFormat = [{`<`
+      `triple` `=` $triple `,`
+      `chip` `=` $chip
+      (`,` `features` `=` $features^)?
+  `>`}];
 
   let extraClassDeclaration = [{
     FailureOr<Attribute> query(DataLayoutEntryKey key);
-  }];
-}
-
-//===----------------------------------------------------------------------===//
-// LLVM_DataLayoutAttr
-//===----------------------------------------------------------------------===//
-
-def LLVM_DataLayoutAttr
-    : LLVM_Attr<"DataLayout", "data_layout", [DataLayoutSpecInterface]> {
-  let summary = "LLVM data layout string, exposed through DLTI";
-  let description = [{
-    An attribute to hold a LLVM data layout string.
-
-    The LLVM data layout string is parsed and mapped to the corresponding MLIR
-    data layout specification. The `#llvm.data_layout` attribute then serves as
-    a proxy, forwarding all DLTI queries to the underlying MLIR data layout
-    specification.
 
-    The default data layout string specified in the language reference
-    (https://llvm.org/docs/LangRef.html#data-layout) is used to derive
-    unspecified elements of the data layout string.
-  }];
-  let parameters = (ins OptionalParameter<"StringAttr", "\"\"">:$data_layout_str,
-                        OptionalParameter<"DataLayoutSpecInterface", "{}">:$data_layout_spec);
-  let builders = [
-    AttrBuilder<(ins "llvm::StringRef":$data_layout_str), [{
-      auto importer = LLVM::detail::DataLayoutImporter($_ctxt, data_layout_str);
-      auto dataLayoutSpec = importer.getDataLayoutSpec();
-      return $_get($_ctxt, mlir::StringAttr::get($_ctxt, data_layout_str), dataLayoutSpec);
-    }]>
-  ];
-  let assemblyFormat = "(`<` $data_layout_str^ `>`)?";
-  let extraClassDeclaration = [{
-    // Forward all DataLayoutSpecInterface methods to the underlying
-    // DataLayoutSpecInterface.
-    template <typename Ty>
-    DataLayoutEntryList getSpecForType() {
-      return getDataLayoutSpec().getSpecForType(TypeID::get<Ty>());
-    }
-    void bucketEntriesByType(
-        ::llvm::MapVector<::mlir::TypeID, ::mlir::DataLayoutEntryList> &types,
-        ::llvm::MapVector<::mlir::StringAttr,
-                          ::mlir::DataLayoutEntryInterface> &ids) {
-      getDataLayoutSpec().bucketEntriesByType(types, ids);
-    }
-    ::mlir::DataLayoutSpecInterface
-    combineWith(ArrayRef<::mlir::DataLayoutSpecInterface> specs) const {
-      return getDataLayoutSpec().combineWith(specs);
-    }
-    DataLayoutEntryListRef getEntries() const { return getDataLayoutSpec().getEntries(); }
-    LogicalResult verifySpec(Location loc) {
-      return getDataLayoutSpec().verifySpec(loc);
-    }
-    StringAttr getEndiannessIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getEndiannessIdentifier(context);
-    }
-    StringAttr getDefaultMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getDefaultMemorySpaceIdentifier(context);
-    }
-    StringAttr getAllocaMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getAllocaMemorySpaceIdentifier(context);
-    }
-    StringAttr getManglingModeIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getManglingModeIdentifier(context);
-    }
-    StringAttr getProgramMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getProgramMemorySpaceIdentifier(context);
-    }
-    StringAttr getGlobalMemorySpaceIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getGlobalMemorySpaceIdentifier(context);
-    }
-    StringAttr getStackAlignmentIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getStackAlignmentIdentifier(context);
-    }
-    StringAttr getFunctionPointerAlignmentIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getFunctionPointerAlignmentIdentifier(context);
-    }
-    StringAttr getLegalIntWidthsIdentifier(MLIRContext *context) const {
-      return getDataLayoutSpec().getLegalIntWidthsIdentifier(context);
-    }
-    ::mlir::DataLayoutEntryList getSpecForType(TypeID type) const {
-      return getDataLayoutSpec().getSpecForType(type);
-    }
-    ::mlir::DataLayoutEntryInterface getSpecForIdentifier(StringAttr identifier) const {
-      return getDataLayoutSpec().getSpecForIdentifier(identifier);
-    }
-    FailureOr<Attribute> query(DataLayoutEntryKey key) const {
-      return getDataLayoutSpec().query(key);
-    }
+    StringAttr getTripleAttr();
+    StringAttr getChipAttr();
+    StringAttr getFeaturesAttr();
   }];
 }
 
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index 9bbb50fb84b83..50a9fff688534 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -20,9 +20,6 @@
 
 #include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
 
-#include "llvm/IR/DataLayout.h"
-#include "llvm/Target/TargetMachine.h"
-
 namespace mlir {
 namespace LLVM {
 
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
index b5ea8fc5da500..363189c9dd158 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
@@ -27,6 +27,7 @@ def LLVM_Dialect : Dialect {
   );
 
   let extraClassDeclaration = [{
+    static StringRef getTargetAttrName() { return "llvm.target"; }
     /// Name of the data layout attributes.
     static StringRef getDataLayoutAttrName() { return "llvm.data_layout"; }
     static StringRef getNoAliasScopesAttrName() { return "noalias_scopes"; }
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 54a706ddb2064..dd3fdf6fbd95a 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -539,9 +539,7 @@ def LLVM_TargetAttrInterface
     Interface for attributes that describe LLVM targets.
 
     These attributes should be able to return the specified target `triple`,
-    `chip` and `features` and are expected to be able to produce the
-    corresponding `llvm::TargetMachine` and `llvm::DataLayout`. These methods
-    can fail in case the backend is not available.
+    `chip` and `features`.
 
     Implementing attributes should provide a `DLTIQueryInterface::query()`
     implementation which responds to keys `"triple"`, `"chip"` and `"features"`
@@ -566,18 +564,6 @@ def LLVM_TargetAttrInterface
       /*retTy=*/"StringAttr",
       /*methodName=*/"getFeaturesAttr",
       /*args=*/(ins)
-    >,
-    InterfaceMethod<
-      /*description=*/"Returns the target machine.",
-      /*retTy=*/"FailureOr<std::unique_ptr<::llvm::TargetMachine>>",
-      /*methodName=*/"getTargetMachine",
-      /*args=*/(ins)
-    >,
-    InterfaceMethod<
-      /*description=*/"Returns the data layout associated to the target machine.",
-      /*retTy=*/"FailureOr<::llvm::DataLayout>",
-      /*methodName=*/"getDataLayout",
-      /*args=*/(ins)
     >
   ];
 }
diff --git a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
index 9a13d8e7ad22b..961909d5c8d27 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/Transforms/Passes.td
@@ -45,17 +45,6 @@ def LLVMRequestCWrappersPass
   }];
 }
 
-def LLVMDataLayoutFromTarget : Pass<"llvm-data-layout-from-target", "::mlir::ModuleOp"> {
-  let summary = "Derive data layout attributes from LLVM target attributes";
-  let dependentDialects = ["mlir::DLTIDialect"];
-  let description = [{
-    Checks modules for LLVM-dialect's `TargetAttrInterface`-implementing
-    attributes and derives `DataLayoutSpecInterface`-implementing data layout
-    attributes from the specified target by querying the corresponding
-    LLVM-backend.
-  }];
-}
-
 def NVVMOptimizeForTargetPass : Pass<"llvm-optimize-for-nvvm-target"> {
   let summary = "Optimize NVVM IR";
 }
diff --git a/mlir/include/mlir/InitAllDialects.h b/mlir/include/mlir/InitAllDialects.h
index 75903a89ae0ac..c6fcf1a0d510b 100644
--- a/mlir/include/mlir/InitAllDialects.h
+++ b/mlir/include/mlir/InitAllDialects.h
@@ -100,7 +100,6 @@
 #include "mlir/Dialect/XeGPU/IR/XeGPU.h"
 #include "mlir/IR/Dialect.h"
 #include "mlir/Interfaces/CastInterfaces.h"
-#include "mlir/Target/LLVM/Target.h"
 #include "mlir/Target/LLVM/NVVM/Target.h"
 #include "mlir/Target/LLVM/ROCDL/Target.h"
 #include "mlir/Target/SPIRV/Target.h"
@@ -173,7 +172,6 @@ inline void registerAllDialects(DialectRegistry &registry) {
   gpu::registerBufferDeallocationOpInterfaceExternalModels(registry);
   gpu::registerValueBoundsOpInterfaceExternalModels(registry);
   LLVM::registerInlinerInterface(registry);
-  LLVM::registerLLVMTargetInterfaceExternalModels(registry);
   NVVM::registerInlinerInterface(registry);
   linalg::registerAllDialectInterfaceImplementations(registry);
   linalg::registerRuntimeVerifiableOpInterfaceExternalModels(registry);
diff --git a/mlir/include/mlir/InitAllPasses.h b/mlir/include/mlir/InitAllPasses.h
index dd8b292a87344..c879bc1b6d1f9 100644
--- a/mlir/include/mlir/InitAllPasses.h
+++ b/mlir/include/mlir/InitAllPasses.h
@@ -46,6 +46,7 @@
 #include "mlir/Dialect/Transform/Transforms/Passes.h"
 #include "mlir/Dialect/Vector/Transforms/Passes.h"
 #include "mlir/Dialect/XeGPU/Transforms/Passes.h"
+#include "mlir/Target/LLVMIR/Transforms/Passes.h"
 #include "mlir/Transforms/Passes.h"
 
 #include <cstdlib>
@@ -79,6 +80,7 @@ inline void registerAllPasses() {
   registerNVGPUPasses();
   registerSparseTensorPasses();
   LLVM::registerLLVMPasses();
+  LLVM::registerTargetLLVMIRTransformsPasses();
   math::registerMathPasses();
   memref::registerMemRefPasses();
   mesh::registerMeshPasses();
diff --git a/mlir/include/mlir/Target/CMakeLists.txt b/mlir/include/mlir/Target/CMakeLists.txt
new file mode 100644
index 0000000000000..39d31dc9b5e9c
--- /dev/null
+++ b/mlir/include/mlir/Target/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(LLVMIR)
diff --git a/mlir/include/mlir/Target/LLVM/Target.h b/mlir/include/mlir/Target/LLVM/Target.h
deleted file mode 100644
index bb389906ed298..0000000000000
--- a/mlir/include/mlir/Target/LLVM/Target.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===- Target.h - MLIR LLVM target registration -----------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This provides registration calls for attaching the LLVM target interface.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_TARGET_LLVM_TARGET_H
-#define MLIR_TARGET_LLVM_TARGET_H
-
-namespace mlir {
-class DialectRegistry;
-class MLIRContext;
-namespace LLVM {
-/// Registers the `TargetAttrInterface` for the `#llvm.target` attribute in the
-/// given registry.
-void registerLLVMTargetInterfaceExternalModels(DialectRegistry &registry);
-
-/// Registers the `TargetAttrInterface` for the `#llvm.target` attribute in the
-/// registry associated with the given context.
-void registerLLVMTargetInterfaceExternalModels(MLIRContext &context);
-} // namespace LLVM
-} // namespace mlir
-
-#endif // MLIR_TARGET_LLVM_TARGET_H
diff --git a/mlir/include/mlir/Target/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Target/LLVMIR/CMakeLists.txt
new file mode 100644
index 0000000000000..e31af32661164
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Transforms)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
similarity index 100%
rename from mlir/include/mlir/Dialect/LLVMIR/DataLayoutImporter.h
rename to mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt
new file mode 100644
index 0000000000000..b1a3c79b9b837
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_TARGET_DEFINITIONS Passes.td)
+mlir_tablegen(Passes.h.inc -gen-pass-decls -name TargetLLVMIRTransforms)
+add_public_tablegen_target(MLIRTargetLLVMIRTransformsIncGen)
+
+add_mlir_doc(Passes TargetLLVMIRTransforms ./ -gen-pass-doc)
diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
new file mode 100644
index 0000000000000..1e6419154108c
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
@@ -0,0 +1,27 @@
+//===- Passes.h - LLVM Target Pass Construction and Registration ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES_H
+#define MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES_H
+
+#include "mlir/Pass/Pass.h"
+
+namespace mlir {
+
+namespace LLVM {
+
+#define GEN_PASS_DECL
+#define GEN_PASS_REGISTRATION
+#include "mlir/Target/LLVMIR/Transforms/Passes.h.inc"
+
+void registerTargetLLVMPasses();
+
+} // namespace LLVM
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES_H
diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
new file mode 100644
index 0000000000000..3a7fb8cf83cfe
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
@@ -0,0 +1,30 @@
+//===-- Passes.td - LLVM Target pass definition file -------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES
+#define MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES
+
+include "mlir/Pass/PassBase.td"
+
+def LLVMTargetToDataLayout : Pass<"llvm-target-to-data-layout"> {
+  let summary = "Derive data layout attributes from LLVM target attributes";
+  let dependentDialects = ["mlir::DLTIDialect"];
+  let description = [{
+    Finds a LLVM-dialect `TargetAttrInterface`-implementing
+    attribute attached to the target op and derives `DataLayoutSpecInterface`-implementing data layout
+    attributes from the specified target's LLVM-backend.
+  }];
+  let options = [
+    Option<"initializeLLVMTargets", "initialize-llvm-targets", "bool",
+           /*default=*/"true",
+           "Whether to pre-load all available target machines, that LLVM is "
+           "configured to support, into the TargetRegistry.">
+  ];
+}
+
+#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES
diff --git a/mlir/lib/Dialect/DLTI/DLTI.cpp b/mlir/lib/Dialect/DLTI/DLTI.cpp
index 62ecf7d759959..0c4fe27ffa58e 100644
--- a/mlir/lib/Dialect/DLTI/DLTI.cpp
+++ b/mlir/lib/Dialect/DLTI/DLTI.cpp
@@ -657,7 +657,7 @@ void DLTIDialect::initialize() {
 LogicalResult DLTIDialect::verifyOperationAttribute(Operation *op,
                                                     NamedAttribute attr) {
   if (attr.getName() == DLTIDialect::kDataLayoutAttrName) {
-    if (!llvm::dyn_cast<DataLayoutSpecInterface>(attr.getValue())) {
+    if (!llvm::isa<DataLayoutSpecAttr>(attr.getValue())) {
       return op->emitError() << "'" << DLTIDialect::kDataLayoutAttrName
                              << "' is expected to be a #dlti.dl_spec attribute";
     }
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index d698a6cb43e00..2bf5103454f90 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -1,7 +1,6 @@
 add_subdirectory(Transforms)
 
 add_mlir_dialect_library(MLIRLLVMDialect
-  IR/DataLayoutImporter.cpp
   IR/FunctionCallUtils.cpp
   IR/LLVMAttrs.cpp
   IR/LLVMDialect.cpp
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 22644c9fead01..0870fa7700d11 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -11,7 +11,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "mlir/Dialect/LLVMIR/LLVMAttrs.h"
-#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/DialectImplementation.h"
@@ -19,7 +18,6 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/TypeSwitch.h"
 #include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 
 using namespace mlir;
@@ -422,3 +420,7 @@ FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
 
   return failure();
 }
+
+StringAttr TargetAttr::getTripleAttr() { return getTriple(); }
+StringAttr TargetAttr::getChipAttr() { return getChip(); }
+StringAttr TargetAttr::getFeaturesAttr() { return getFeatures(); }
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
index 0d0e708a70e4a..6dcd94e6eea17 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp
@@ -4075,7 +4075,6 @@ void LLVMDialect::initialize() {
   // Support unknown operations because not all LLVM operations are registered.
   allowUnknownOperations();
   declarePromisedInterface<DialectInlinerInterface, LLVMDialect>();
-  declarePromisedInterface<LLVM::TargetAttrInterface, LLVM::TargetAttr>();
 }
 
 #define GET_OP_CLASSES
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
index cc6289b485c55..d4ff0955c5d0e 100644
--- a/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/Transforms/CMakeLists.txt
@@ -7,7 +7,6 @@ add_mlir_dialect_library(MLIRLLVMIRTransforms
   LegalizeForExport.cpp
   OptimizeForNVVM.cpp
   RequestCWrappers.cpp
-  DataLayoutFromTarget.cpp
 
   DEPENDS
   MLIRLLVMPassIncGen
diff --git a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp b/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
deleted file mode 100644
index 3eccadffb86ac..0000000000000
--- a/mlir/lib/Dialect/LLVMIR/Transforms/DataLayoutFromTarget.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- DataLayoutFromTarget.cpp - extract data layout from TargetMachine --===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Dialect/DLTI/DLTI.h"
-#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
-#include "mlir/Pass/Pass.h"
-
-namespace mlir {
-namespace LLVM {
-#define GEN_PASS_DEF_LLVMDATALAYOUTFROMTARGET
-#include "mlir/Dialect/LLVMIR/Transforms/Passes.h.inc"
-} // namespace LLVM
-} // namespace mlir
-
-using namespace mlir;
-
-struct DataLayoutFromTargetPass
-    : public LLVM::impl::LLVMDataLayoutFromTargetBase<
-          DataLayoutFromTargetPass> {
-  void runOnOperation() override {
-    ModuleOp mod = getOperation();
-
-    bool passFailed = false;
-
-    mod->walk([&](ModuleOp mod) {
-      auto targetAttr =
-          mod->getAttrOfType<LLVM::TargetAttrInterface>("llvm.target");
-      if (!targetAttr)
-        return;
-
-      FailureOr<llvm::DataLayout> dataLayout = targetAttr.getDataLayout();
-      if (failed(dataLayout)) {
-        mod->emitError() << "failed to obtain llvm::DataLayout from "
-                         << targetAttr;
-        passFailed = true;
-        return;
-      }
-      auto dataLayoutAttr = LLVM::DataLayoutAttr::get(
-          &getContext(), dataLayout->getStringRepresentation());
-
-      StringRef dlSpecIdentifier = "dlti.dl_spec";
-      auto existingDlSpec =
-          mod->getAttrOfType<DataLayoutSpecInterface>(dlSpecIdentifier);
-      if (existingDlSpec) {
-        DataLayoutSpecInterface dataLayoutSpec =
-            existingDlSpec.combineWith({dataLayoutAttr.getDataLayoutSpec()});
-        mod->setAttr(dlSpecIdentifier, dataLayoutSpec);
-      } else {
-        mod->setAttr(dlSpecIdentifier, dataLayoutAttr);
-      }
-    });
-
-    if (passFailed)
-      return signalPassFailure();
-  }
-};
diff --git a/mlir/lib/Target/LLVM/CMakeLists.txt b/mlir/lib/Target/LLVM/CMakeLists.txt
index ee8b9227b5643..6bd97b2d054de 100644
--- a/mlir/lib/Target/LLVM/CMakeLists.txt
+++ b/mlir/lib/Target/LLVM/CMakeLists.txt
@@ -1,6 +1,5 @@
-add_mlir_dialect_library(MLIRTargetLLVM
+add_mlir_library(MLIRTargetLLVM
   ModuleToObject.cpp
-  Target.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${MLIR_MAIN_INCLUDE_DIR}/mlir/Target/LLVM
@@ -17,11 +16,6 @@ add_mlir_dialect_library(MLIRTargetLLVM
   Passes
   Support
   Target
-  TargetParser
-  AllTargetsAsmParsers
-  AllTargetsCodeGens
-  AllTargetsDescs
-  AllTargetsInfos
 
   LINK_LIBS PUBLIC
   MLIRExecutionEngineUtils
diff --git a/mlir/lib/Target/LLVM/Target.cpp b/mlir/lib/Target/LLVM/Target.cpp
deleted file mode 100644
index a82256551f2b6..0000000000000
--- a/mlir/lib/Target/LLVM/Target.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-//===- Target.cpp - MLIR LLVM target interface impls ------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "mlir/Target/LLVM/Target.h"
-#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
-#include "mlir/Dialect/LLVMIR/LLVMInterfaces.h"
-
-#include "llvm/MC/TargetRegistry.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Target/TargetMachine.h"
-
-#define DEBUG_TYPE "llvm-target"
-
-using namespace mlir;
-
-namespace {
-class LLVMTargetAttrImpl
-    : public LLVM::TargetAttrInterface::FallbackModel<LLVMTargetAttrImpl> {
-public:
-  FailureOr<std::unique_ptr<llvm::TargetMachine>>
-  getTargetMachine(Attribute attribute) const {
-    auto attr = llvm::cast<LLVM::TargetAttr>(attribute);
-
-    llvm::InitializeAllTargets();
-    llvm::InitializeAllTargetMCs();
-
-    std::string error;
-    const llvm::Target *target =
-        llvm::TargetRegistry::lookupTarget(attr.getTriple(), error);
-    if (!target || !error.empty()) {
-      LLVM_DEBUG({
-        llvm::dbgs() << "Looking up target '" << attr.getTriple()
-                     << "' failed: " << error << "\n";
-      });
-      return failure();
-    }
-
-    return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
-        llvm::Triple(attr.getTriple().getValue()), attr.getChip().getValue(),
-        attr.getFeatures() ? attr.getFeatures().getValue() : "", {}, {}));
-  }
-
-  FailureOr<llvm::DataLayout> getDataLayout(Attribute attribute) const {
-    auto attr = llvm::cast<LLVM::TargetAttrInterface>(attribute);
-
-    FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
-        attr.getTargetMachine();
-    if (failed(targetMachine)) {
-      LLVM_DEBUG({
-        llvm::dbgs()
-            << "Failed to retrieve the target machine for data layout.\n";
-      });
-      return failure();
-    }
-    return (targetMachine.value())->createDataLayout();
-  }
-
-  StringAttr getTripleAttr(Attribute attribute) const {
-    return llvm::cast<LLVM::TargetAttr>(attribute).getTriple();
-  }
-
-  StringAttr getChipAttr(Attribute attribute) const {
-    return llvm::cast<LLVM::TargetAttr>(attribute).getChip();
-  }
-
-  StringAttr getFeaturesAttr(Attribute attribute) const {
-    return llvm::cast<LLVM::TargetAttr>(attribute).getFeatures();
-  }
-};
-} // namespace
-
-// Register the LLVM target interface.
-void LLVM::registerLLVMTargetInterfaceExternalModels(
-    DialectRegistry &registry) {
-  registry.addExtension(+[](MLIRContext *ctx, LLVM::LLVMDialect *dialect) {
-    LLVM::TargetAttr::attachInterface<LLVMTargetAttrImpl>(*ctx);
-  });
-}
-
-void LLVM::registerLLVMTargetInterfaceExternalModels(MLIRContext &context) {
-  DialectRegistry registry;
-  registerLLVMTargetInterfaceExternalModels(registry);
-  context.appendDialectRegistry(registry);
-}
diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt
index f6d70fe05a163..c6d2922f566bd 100644
--- a/mlir/lib/Target/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt
@@ -1,8 +1,10 @@
 add_subdirectory(Dialect)
+add_subdirectory(Transforms)
 
 set(LLVM_OPTIONAL_SOURCES
   ConvertFromLLVMIR.cpp
   ConvertToLLVMIR.cpp
+  DataLayoutImporter.cpp
   DebugTranslation.cpp
   DebugImporter.cpp
   LoopAnnotationImporter.cpp
@@ -62,6 +64,7 @@ add_mlir_translation_library(MLIRToLLVMIRTranslationRegistration
   )
 
 add_mlir_translation_library(MLIRTargetLLVMIRImport
+  DataLayoutImporter.cpp
   DebugImporter.cpp
   LoopAnnotationImporter.cpp
   ModuleImport.cpp
diff --git a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
similarity index 99%
rename from mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
rename to mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index 7bd59f417e748..7911821d8b060 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -6,12 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Target/LLVMIR/Import.h"
 
 using namespace mlir;
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 64132a5668215..e59eb44fd8a1c 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -20,11 +20,11 @@
 #include "LoopAnnotationImporter.h"
 
 #include "mlir/Dialect/DLTI/DLTI.h"
-#include "mlir/Dialect/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/Matchers.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Tools/mlir-translate/Translation.h"
 
 #include "llvm/ADT/DepthFirstIterator.h"
diff --git a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
new file mode 100644
index 0000000000000..481ff53e01409
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
@@ -0,0 +1,30 @@
+add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
+  TargetToDataLayout.cpp
+
+  DEPENDS
+  MLIRTargetLLVMIRTransformsIncGen
+
+  LINK_COMPONENTS
+  #Core
+  #IPO
+  #IRReader
+  #Linker
+  MC
+  #Passes
+  #Support
+  Target
+  TargetParser
+  AllTargetsAsmParsers
+  AllTargetsCodeGens
+  AllTargetsDescs
+  AllTargetsInfos
+
+  LINK_LIBS PUBLIC
+  MLIRDLTIDialect
+  MLIRIR
+  MLIRLLVMDialect
+  MLIRPass
+  MLIRTargetLLVM
+  MLIRTargetLLVMIRImport
+  MLIRTransforms
+  )
diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
new file mode 100644
index 0000000000000..a5f449c579aa5
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
@@ -0,0 +1,104 @@
+//===- TargetToDataLayout.cpp - extract data layout from TargetMachine ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "mlir/Target/LLVMIR/Transforms/Passes.h"
+
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
+
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define DEBUG_TYPE "mlir-llvm-target-to-data-layout"
+
+namespace mlir {
+namespace LLVM {
+#define GEN_PASS_DEF_LLVMTARGETTODATALAYOUT
+#include "mlir/Target/LLVMIR/Transforms/Passes.h.inc"
+} // namespace LLVM
+} // namespace mlir
+
+using namespace mlir;
+
+static FailureOr<std::unique_ptr<llvm::TargetMachine>>
+getTargetMachine(LLVM::TargetAttrInterface attr) {
+  StringRef triple = attr.getTripleAttr();
+  StringRef chipAKAcpu = attr.getChipAttr();
+  StringRef features =
+      attr.getFeaturesAttr() ? attr.getFeaturesAttr().getValue() : "";
+
+  std::string error;
+  const llvm::Target *target =
+      llvm::TargetRegistry::lookupTarget(triple, error);
+  if (!target || !error.empty()) {
+    LLVM_DEBUG({
+      llvm::dbgs() << "Looking up target '" << triple << "' failed: " << error
+                   << "\n";
+    });
+    return failure();
+  }
+
+  return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
+      llvm::Triple(triple), chipAKAcpu, features, {}, {}));
+}
+
+static FailureOr<llvm::DataLayout>
+getDataLayout(LLVM::TargetAttrInterface attr) {
+  FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
+      getTargetMachine(attr);
+  if (failed(targetMachine)) {
+    LLVM_DEBUG({
+      llvm::dbgs()
+          << "Failed to retrieve the target machine for data layout.\n";
+    });
+    return failure();
+  }
+  return (targetMachine.value())->createDataLayout();
+}
+
+struct TargetToDataLayoutPass
+    : public LLVM::impl::LLVMTargetToDataLayoutBase<TargetToDataLayoutPass> {
+  using LLVM::impl::LLVMTargetToDataLayoutBase<
+      TargetToDataLayoutPass>::LLVMTargetToDataLayoutBase;
+
+  void runOnOperation() override {
+    Operation *op = getOperation();
+
+    if (initializeLLVMTargets) {
+      // Ensure that the targets, that LLVM has been configured to support,
+      // are loaded into the TargetRegistry.
+      llvm::InitializeAllTargets();
+      llvm::InitializeAllTargetMCs();
+    }
+
+    auto targetAttr = op->getAttrOfType<LLVM::TargetAttrInterface>(
+        LLVM::LLVMDialect::getTargetAttrName());
+    if (!targetAttr)
+      return;
+
+    FailureOr<llvm::DataLayout> dataLayout = getDataLayout(targetAttr);
+    if (failed(dataLayout)) {
+      op->emitError() << "failed to obtain llvm::DataLayout for " << targetAttr;
+      return signalPassFailure();
+    }
+
+    StringRef dataLayoutStr = dataLayout->getStringRepresentation();
+
+    auto importer =
+        LLVM::detail::DataLayoutImporter(&getContext(), dataLayoutStr);
+    DataLayoutSpecInterface dataLayoutSpec = importer.getDataLayoutSpec();
+
+    if (auto existingDlSpec = op->getAttrOfType<DataLayoutSpecInterface>(
+            DLTIDialect::kDataLayoutAttrName)) {
+      dataLayoutSpec = existingDlSpec.combineWith({dataLayoutSpec});
+    }
+
+    op->setAttr(DLTIDialect::kDataLayoutAttrName, dataLayoutSpec);
+  }
+};
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir b/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
deleted file mode 100644
index 1398ae3016705..0000000000000
--- a/mlir/test/Dialect/LLVMIR/data-layout-from-target-invalid.mlir
+++ /dev/null
@@ -1,9 +0,0 @@
-// REQUIRES: target=x86{{.*}}
-// RUN: mlir-opt %s -llvm-data-layout-from-target --split-input-file --verify-diagnostics
-
-// expected-error @+1 {{failed to obtain llvm::DataLayout from #llvm.target}}
-module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
-llvm.target =
-    #llvm.target<triple="x64_86-unknown-linux",
-                 chip="lakesky"> } {
-}
diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
new file mode 100644
index 0000000000000..c0ff53457d17e
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
@@ -0,0 +1,9 @@
+// REQUIRES: target=x86{{.*}}
+// RUN: mlir-opt %s -llvm-target-to-data-layout --split-input-file --verify-diagnostics
+
+// expected-error @+1 {{failed to obtain llvm::DataLayout for #llvm.target}}
+module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
+llvm.target =
+    #llvm.target<triple="x64_86-unknown-linux",
+                 chip="NON-EXISTING CHIP"> } {
+}
diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
new file mode 100644
index 0000000000000..2a9e9783eacb1
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
@@ -0,0 +1,12 @@
+// REQUIRES: target=x86{{.*}}
+// RUN: mlir-opt %s -llvm-target-to-data-layout="initialize-llvm-targets=false" --split-input-file --verify-diagnostics
+
+// Without initializing the (right) LLVM targets/backends ("initialize-llvm-targets=false"),
+// it is not possible to obtain LLVM's DataLayout for the target.
+
+// expected-error @+1 {{failed to obtain llvm::DataLayout for #llvm.target}}
+module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
+llvm.target =
+    #llvm.target<triple="x64_86-unknown-linux",
+                 chip="skylake"> } {
+}
diff --git a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
similarity index 76%
rename from mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
rename to mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
index e69d47d20476a..45bfd6a465d7c 100644
--- a/mlir/test/Dialect/LLVMIR/data-layout-from-target.mlir
+++ b/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
@@ -1,20 +1,23 @@
 // REQUIRES: target=x86{{.*}}
-// RUN: mlir-opt -llvm-data-layout-from-target -split-input-file %s | FileCheck %s
+// RUN: mlir-opt -llvm-target-to-data-layout -split-input-file %s | FileCheck %s
 
 // CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME:   "dlti.endianness" = "little"
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = ""
 // CHECK-NOT:    features =
 
-module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux", chip = ""> } {
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+                                               chip = ""> } {
 }
 
 // -----
 
 // CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME:   "dlti.endianness" = "little"
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = ""
@@ -28,7 +31,8 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
 // -----
 
 // CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME:   "dlti.endianness" = "little"
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = "skylake"
@@ -41,7 +45,8 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
 // -----
 
 // CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #llvm.data_layout
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME:   "dlti.endianness" = "little"
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"
 // CHECK-SAME:   chip = "skylake"
@@ -55,7 +60,8 @@ module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
 // -----
 
 // CHECK: module attributes
-// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec<"dlti.endianness" = "little"
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME:   "dlti.endianness" = "little"
 // CHECK-SAME:   index = 32
 // CHECK-SAME: llvm.target = #llvm.target<
 // CHECK-SAME:   triple = "x86_64-unknown-linux"

>From 68c2e06255a7b27d1906ae8a667cea626507ca26 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Mon, 18 Aug 2025 07:48:51 -0700
Subject: [PATCH 14/18] Style improvements

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td     | 6 +-----
 mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h | 6 +++---
 mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td | 6 +++---
 mlir/lib/Target/LLVM/CMakeLists.txt                  | 1 -
 mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt     | 8 --------
 5 files changed, 7 insertions(+), 20 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index a8905a6bba71a..f1e2cb8d64a4a 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1326,11 +1326,7 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
                         "StringAttr":$chip,
                         OptionalParameter<"StringAttr", "">:$features);
 
-  let assemblyFormat = [{`<`
-      `triple` `=` $triple `,`
-      `chip` `=` $chip
-      (`,` `features` `=` $features^)?
-  `>`}];
+  let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
 
   let extraClassDeclaration = [{
     FailureOr<Attribute> query(DataLayoutEntryKey key);
diff --git a/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
index f820833cb7a17..243de55461e6f 100644
--- a/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
@@ -11,8 +11,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H
-#define MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H
+#ifndef MLIR_TARGET_LLVMIR_DATALAYOUTIMPORTER_H
+#define MLIR_TARGET_LLVMIR_DATALAYOUTIMPORTER_H
 
 #include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
@@ -137,4 +137,4 @@ class DataLayoutImporter {
 } // namespace LLVM
 } // namespace mlir
 
-#endif // MLIR_DIALECT_LLVMIR_DATALAYOUTIMPORTER_H
+#endif // MLIR_TARGET_LLVMIR_DATALAYOUTIMPORTER_H
diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
index 3a7fb8cf83cfe..906f6e82efa50 100644
--- a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
@@ -15,9 +15,9 @@ def LLVMTargetToDataLayout : Pass<"llvm-target-to-data-layout"> {
   let summary = "Derive data layout attributes from LLVM target attributes";
   let dependentDialects = ["mlir::DLTIDialect"];
   let description = [{
-    Finds a LLVM-dialect `TargetAttrInterface`-implementing
-    attribute attached to the target op and derives `DataLayoutSpecInterface`-implementing data layout
-    attributes from the specified target's LLVM-backend.
+    Derive a `DataLayoutSpecInterface`-implementing data layout attribute from
+    the LLVM-backend target specified by the `TargetAttrInterface`-implementing
+    attribute attached to the target op at the name `llvm.target`.
   }];
   let options = [
     Option<"initializeLLVMTargets", "initialize-llvm-targets", "bool",
diff --git a/mlir/lib/Target/LLVM/CMakeLists.txt b/mlir/lib/Target/LLVM/CMakeLists.txt
index 6bd97b2d054de..83fbf7a5fe5f3 100644
--- a/mlir/lib/Target/LLVM/CMakeLists.txt
+++ b/mlir/lib/Target/LLVM/CMakeLists.txt
@@ -16,7 +16,6 @@ add_mlir_library(MLIRTargetLLVM
   Passes
   Support
   Target
-
   LINK_LIBS PUBLIC
   MLIRExecutionEngineUtils
   MLIRTargetLLVMIRExport
diff --git a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
index 481ff53e01409..a1867356e5b56 100644
--- a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
@@ -5,13 +5,7 @@ add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
   MLIRTargetLLVMIRTransformsIncGen
 
   LINK_COMPONENTS
-  #Core
-  #IPO
-  #IRReader
-  #Linker
   MC
-  #Passes
-  #Support
   Target
   TargetParser
   AllTargetsAsmParsers
@@ -21,10 +15,8 @@ add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
 
   LINK_LIBS PUBLIC
   MLIRDLTIDialect
-  MLIRIR
   MLIRLLVMDialect
   MLIRPass
   MLIRTargetLLVM
   MLIRTargetLLVMIRImport
-  MLIRTransforms
   )

>From 80c1f3777941a4a64e775b53a3ba65c631e3e02e Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Mon, 18 Aug 2025 13:32:25 -0700
Subject: [PATCH 15/18] Further minor fixes

---
 .../include/mlir/Target/LLVMIR/DataLayoutImporter.h | 13 +++++++------
 mlir/lib/Dialect/LLVMIR/CMakeLists.txt              |  1 -
 mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt    |  1 -
 3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
index 243de55461e6f..aa4606d71f91c 100644
--- a/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
@@ -48,11 +48,12 @@ class DataLayoutImporter {
 public:
   DataLayoutImporter(MLIRContext *context, StringRef dataLayoutStr)
       : dataLayoutStr(dataLayoutStr), context(context) {
-    // Append the default data layout string specified in the language reference
-    // (https://llvm.org/docs/LangRef.html#data-layout) to the supplied data
-    // layout string. The translation then parses the string and ignores the
-    // default value if a specific kind occurs in both strings. Additionally,
-    // the following default values exist:
+    // Translate the `dataLayoutStr`. First, append the default data layout
+    // string specified in the language reference
+    // (https://llvm.org/docs/LangRef.html#data-layout) to the supplied string.
+    // The translation then parses the string and ignores the default value if a
+    // specific kind occurs in both strings. Additionally, the following default
+    // values exist:
     // - non-default address space pointer specifications default to the default
     //   address space pointer specification
     // - the alloca address space defaults to the default address space.
@@ -72,7 +73,7 @@ class DataLayoutImporter {
   ArrayRef<StringRef> getUnhandledTokens() const { return unhandledTokens; }
 
 private:
-  /// Translates the LLVM `dataLayout` to an MLIR data layout specification.
+  /// Translate the LLVM data layout string to an MLIR data layout specification.
   DataLayoutSpecInterface dataLayoutSpecFromDataLayoutStr();
 
   /// Tries to parse the letter only prefix that identifies the specification
diff --git a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
index 2bf5103454f90..d987b72e98354 100644
--- a/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Dialect/LLVMIR/CMakeLists.txt
@@ -30,7 +30,6 @@ add_mlir_dialect_library(MLIRLLVMDialect
   LINK_LIBS PUBLIC
   MLIRCallInterfaces
   MLIRControlFlowInterfaces
-  MLIRDLTIDialect
   MLIRDataLayoutInterfaces
   MLIRFunctionInterfaces
   MLIRInferTypeOpInterface
diff --git a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
index a1867356e5b56..a0232601c5f9c 100644
--- a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
@@ -17,6 +17,5 @@ add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
   MLIRDLTIDialect
   MLIRLLVMDialect
   MLIRPass
-  MLIRTargetLLVM
   MLIRTargetLLVMIRImport
   )

>From 86aa3c4f4c3d0a7bc3ec50f9e68c4d59ea616037 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Wed, 20 Aug 2025 08:47:13 -0700
Subject: [PATCH 16/18] Address Mehdi's and Fabian's comments

---
 .../mlir/Dialect/LLVMIR/LLVMAttrDefs.td       | 12 +++----
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp      | 12 +++----
 .../LLVMIR/Transforms/TargetToDataLayout.cpp  | 32 +++++++++++--------
 3 files changed, 26 insertions(+), 30 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index f1e2cb8d64a4a..c36335239d01a 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1322,18 +1322,14 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
       * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`.
       * A query for `"features"` returns the `StringAttr`, if provided.
   }];
-  let parameters = (ins "StringAttr":$triple,
-                        "StringAttr":$chip,
-                        OptionalParameter<"StringAttr", "">:$features);
+  let parameters = (ins "StringAttr":$triple_attr,
+                        "StringAttr":$chip_attr,
+                        OptionalParameter<"StringAttr", "">:$features_attr);
 
-  let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
+  let assemblyFormat = [{`<` struct($triple_attr, $chip_attr, $features_attr) `>`}];
 
   let extraClassDeclaration = [{
     FailureOr<Attribute> query(DataLayoutEntryKey key);
-
-    StringAttr getTripleAttr();
-    StringAttr getChipAttr();
-    StringAttr getFeaturesAttr();
   }];
 }
 
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 0870fa7700d11..6b08d035daf3a 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -411,16 +411,12 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
 FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
   if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
     if (stringAttrKey.getValue() == "triple")
-      return getTriple();
+      return getTripleAttr();
     if (stringAttrKey.getValue() == "chip")
-      return getChip();
-    if (stringAttrKey.getValue() == "features" && getFeatures())
-      return getFeatures();
+      return getChipAttr();
+    if (stringAttrKey.getValue() == "features" && getFeaturesAttr())
+      return getFeaturesAttr();
   }
 
   return failure();
 }
-
-StringAttr TargetAttr::getTripleAttr() { return getTriple(); }
-StringAttr TargetAttr::getChipAttr() { return getChip(); }
-StringAttr TargetAttr::getFeaturesAttr() { return getFeatures(); }
diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
index a5f449c579aa5..47b9868c97f60 100644
--- a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
@@ -12,10 +12,13 @@
 #include "mlir/Target/LLVMIR/DataLayoutImporter.h"
 
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Target/TargetMachine.h"
 
 #define DEBUG_TYPE "mlir-llvm-target-to-data-layout"
+#define DBGS() (llvm::dbgs() << '[' << DEBUG_TYPE << "] ")
+#define LDBG(X) LLVM_DEBUG(DBGS() << X << "\n")
 
 namespace mlir {
 namespace LLVM {
@@ -37,10 +40,7 @@ getTargetMachine(LLVM::TargetAttrInterface attr) {
   const llvm::Target *target =
       llvm::TargetRegistry::lookupTarget(triple, error);
   if (!target || !error.empty()) {
-    LLVM_DEBUG({
-      llvm::dbgs() << "Looking up target '" << triple << "' failed: " << error
-                   << "\n";
-    });
+    LDBG("Looking up target '" << triple << "' failed: " << error << "\n");
     return failure();
   }
 
@@ -53,10 +53,7 @@ getDataLayout(LLVM::TargetAttrInterface attr) {
   FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
       getTargetMachine(attr);
   if (failed(targetMachine)) {
-    LLVM_DEBUG({
-      llvm::dbgs()
-          << "Failed to retrieve the target machine for data layout.\n";
-    });
+    LDBG("Failed to retrieve the target machine for data layout.\n");
     return failure();
   }
   return (targetMachine.value())->createDataLayout();
@@ -71,16 +68,23 @@ struct TargetToDataLayoutPass
     Operation *op = getOperation();
 
     if (initializeLLVMTargets) {
-      // Ensure that the targets, that LLVM has been configured to support,
-      // are loaded into the TargetRegistry.
-      llvm::InitializeAllTargets();
-      llvm::InitializeAllTargetMCs();
+      static llvm::once_flag initializeBackendsOnce;
+      llvm::call_once(initializeBackendsOnce, []() {
+        // Ensure that the targets, that LLVM has been configured to support,
+        // are loaded into the TargetRegistry.
+        llvm::InitializeAllTargets();
+        llvm::InitializeAllTargetMCs();
+      });
     }
 
     auto targetAttr = op->getAttrOfType<LLVM::TargetAttrInterface>(
         LLVM::LLVMDialect::getTargetAttrName());
-    if (!targetAttr)
-      return;
+    if (!targetAttr) {
+      op->emitError()
+          << "no TargetAttrInterface-implementing attribute at key \""
+          << LLVM::LLVMDialect::getTargetAttrName() << "\"";
+      return signalPassFailure();
+    }
 
     FailureOr<llvm::DataLayout> dataLayout = getDataLayout(targetAttr);
     if (failed(dataLayout)) {

>From 2a50feeb9257adffc4e26c82d20902778704ce9f Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Wed, 20 Aug 2025 12:13:48 -0700
Subject: [PATCH 17/18] Final fixes

---
 mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td          | 8 ++++----
 mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td        | 6 +++---
 mlir/lib/Dialect/AMX/Transforms/LegalizeForLLVMExport.cpp | 1 +
 mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp                  | 8 ++++----
 mlir/lib/RegisterAllPasses.cpp                            | 2 ++
 mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp  | 6 +++---
 6 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index c36335239d01a..138dd7703a5e7 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -1322,11 +1322,11 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
       * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`.
       * A query for `"features"` returns the `StringAttr`, if provided.
   }];
-  let parameters = (ins "StringAttr":$triple_attr,
-                        "StringAttr":$chip_attr,
-                        OptionalParameter<"StringAttr", "">:$features_attr);
+  let parameters = (ins "StringAttr":$triple,
+                        "StringAttr":$chip,
+                        OptionalParameter<"StringAttr", "">:$features);
 
-  let assemblyFormat = [{`<` struct($triple_attr, $chip_attr, $features_attr) `>`}];
+  let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
 
   let extraClassDeclaration = [{
     FailureOr<Attribute> query(DataLayoutEntryKey key);
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index dd3fdf6fbd95a..64600e86bedfb 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
@@ -550,19 +550,19 @@ def LLVM_TargetAttrInterface
     InterfaceMethod<
       /*description=*/"Returns the target triple identifier.",
       /*retTy=*/"StringAttr",
-      /*methodName=*/"getTripleAttr",
+      /*methodName=*/"getTriple",
       /*args=*/(ins)
     >,
     InterfaceMethod<
       /*description=*/"Returns the target chip (i.e. \"cpu\") identifier.",
       /*retTy=*/"StringAttr",
-      /*methodName=*/"getChipAttr",
+      /*methodName=*/"getChip",
       /*args=*/(ins)
     >,
     InterfaceMethod<
       /*description=*/"Returns the target features as a string.",
       /*retTy=*/"StringAttr",
-      /*methodName=*/"getFeaturesAttr",
+      /*methodName=*/"getFeatures",
       /*args=*/(ins)
     >
   ];
diff --git a/mlir/lib/Dialect/AMX/Transforms/LegalizeForLLVMExport.cpp b/mlir/lib/Dialect/AMX/Transforms/LegalizeForLLVMExport.cpp
index 6483af222e91b..a81ab3cc363bc 100644
--- a/mlir/lib/Dialect/AMX/Transforms/LegalizeForLLVMExport.cpp
+++ b/mlir/lib/Dialect/AMX/Transforms/LegalizeForLLVMExport.cpp
@@ -12,6 +12,7 @@
 #include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
 #include "mlir/Conversion/LLVMCommon/Pattern.h"
 #include "mlir/Dialect/AMX/AMXDialect.h"
+#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/PatternMatch.h"
 
 using namespace mlir;
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 7f39d106762ab..634efcaea794e 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -410,11 +410,11 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
 FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
   if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
     if (stringAttrKey.getValue() == "triple")
-      return getTripleAttr();
+      return getTriple();
     if (stringAttrKey.getValue() == "chip")
-      return getChipAttr();
-    if (stringAttrKey.getValue() == "features" && getFeaturesAttr())
-      return getFeaturesAttr();
+      return getChip();
+    if (stringAttrKey.getValue() == "features" && getFeatures())
+      return getFeatures();
   }
 
   return failure();
diff --git a/mlir/lib/RegisterAllPasses.cpp b/mlir/lib/RegisterAllPasses.cpp
index 1ed3a3798b0d2..c67b24226ae45 100644
--- a/mlir/lib/RegisterAllPasses.cpp
+++ b/mlir/lib/RegisterAllPasses.cpp
@@ -45,6 +45,7 @@
 #include "mlir/Dialect/Transform/Transforms/Passes.h"
 #include "mlir/Dialect/Vector/Transforms/Passes.h"
 #include "mlir/Dialect/XeGPU/Transforms/Passes.h"
+#include "mlir/Target/LLVMIR/Transforms/Passes.h"
 #include "mlir/Transforms/Passes.h"
 
 // This function may be called to register the MLIR passes with the
@@ -74,6 +75,7 @@ void mlir::registerAllPasses() {
   registerNVGPUPasses();
   registerSparseTensorPasses();
   LLVM::registerLLVMPasses();
+  LLVM::registerTargetLLVMIRTransformsPasses();
   math::registerMathPasses();
   memref::registerMemRefPasses();
   shard::registerShardPasses();
diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
index 47b9868c97f60..1a5e38a7f450f 100644
--- a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
@@ -31,10 +31,10 @@ using namespace mlir;
 
 static FailureOr<std::unique_ptr<llvm::TargetMachine>>
 getTargetMachine(LLVM::TargetAttrInterface attr) {
-  StringRef triple = attr.getTripleAttr();
-  StringRef chipAKAcpu = attr.getChipAttr();
+  StringRef triple = attr.getTriple();
+  StringRef chipAKAcpu = attr.getChip();
   StringRef features =
-      attr.getFeaturesAttr() ? attr.getFeaturesAttr().getValue() : "";
+      attr.getFeatures() ? attr.getFeatures().getValue() : "";
 
   std::string error;
   const llvm::Target *target =

>From 60f13243a637d73910f3c74a5d03cee756d79d20 Mon Sep 17 00:00:00 2001
From: Rolf Morel <rolf.morel at intel.com>
Date: Wed, 20 Aug 2025 12:21:04 -0700
Subject: [PATCH 18/18] Fix formatting

---
 mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h     | 3 ++-
 mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp            | 5 ++---
 mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp | 3 +--
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
index aa4606d71f91c..4d432df493c3f 100644
--- a/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
@@ -73,7 +73,8 @@ class DataLayoutImporter {
   ArrayRef<StringRef> getUnhandledTokens() const { return unhandledTokens; }
 
 private:
-  /// Translate the LLVM data layout string to an MLIR data layout specification.
+  /// Translate the LLVM data layout string to an MLIR data layout
+  /// specification.
   DataLayoutSpecInterface dataLayoutSpecFromDataLayoutStr();
 
   /// Tries to parse the letter only prefix that identifies the specification
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index 7911821d8b060..d8f19dae2af84 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -6,12 +6,12 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinTypes.h"
 #include "mlir/Interfaces/DataLayoutInterfaces.h"
-#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
 #include "mlir/Target/LLVMIR/Import.h"
 
 using namespace mlir;
@@ -273,8 +273,7 @@ DataLayoutImporter::tryToEmplaceLegalIntWidthsEntry(StringRef token) {
   return success();
 }
 
-DataLayoutSpecInterface
-DataLayoutImporter::dataLayoutSpecFromDataLayoutStr() {
+DataLayoutSpecInterface DataLayoutImporter::dataLayoutSpecFromDataLayoutStr() {
   if (!dataLayoutStr.empty())
     dataLayoutStr += "-";
   dataLayoutStr += kDefaultDataLayout;
diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
index 1a5e38a7f450f..b868327b4ff8c 100644
--- a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
@@ -33,8 +33,7 @@ static FailureOr<std::unique_ptr<llvm::TargetMachine>>
 getTargetMachine(LLVM::TargetAttrInterface attr) {
   StringRef triple = attr.getTriple();
   StringRef chipAKAcpu = attr.getChip();
-  StringRef features =
-      attr.getFeatures() ? attr.getFeatures().getValue() : "";
+  StringRef features = attr.getFeatures() ? attr.getFeatures().getValue() : "";
 
   std::string error;
   const llvm::Target *target =



More information about the flang-commits mailing list