[Mlir-commits] [flang] [mlir] [MLIR][LLVMIR][DLTI] Add #llvm.target, #llvm.data_layout and TargetAttrInterface (PR #145899)
Rolf Morel
llvmlistbot at llvm.org
Fri Jul 25 08:53:41 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/10] [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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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/10] 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 ®istry) {
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 ®istry);
+
+/// 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 ®istry) {
+ 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/10] 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();
}
More information about the Mlir-commits
mailing list