From 6523e512f69d38efe8218590b501eb28737d6522 Mon Sep 17 00:00:00 2001 From: Rolf Morel Date: Thu, 26 Jun 2025 07:16:09 -0700 Subject: [PATCH 1/7] [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 traits = [], - string baseCppClass = "::mlir::Attribute"> - : AttrDef { - 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 targetMachine = std::nullopt; + + FailureOr getTargetMachine(); + + std::optional dataLayout = std::nullopt; + FailureOr getDataLayout(); + FailureOr 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 + DataLayoutEntryList getSpecForType() { + return getDataLayoutSpec().getSpecForType(TypeID::get()); + } + + 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 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 @@ -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 traits = [], + string baseCppClass = "::mlir::Attribute"> + : AttrDef { + 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 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(attr.getValue())) { + if (!llvm::dyn_cast(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( + return op->getAttrOfType( 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 +#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 emitError, "supported for unknown key '" << key << "'"; } + +FailureOr TargetFeaturesAttr::query(DataLayoutEntryKey key) { + if (auto stringKey = dyn_cast(key)) + if (contains(stringKey)) + return UnitAttr::get(getContext()); + return failure(); +} + +//===----------------------------------------------------------------------===// +// LLVM_TargetAttr +//===----------------------------------------------------------------------===// + +FailureOr 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 TargetAttr::getDataLayout() { + if (dataLayout.has_value()) { + return dataLayout.value(); + } + + FailureOr 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(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 { + void runOnOperation() override { + ModuleOp mod = getOperation(); + + bool passFailed = false; + + mod->walk([&](ModuleOp mod) { + auto targetAttr = + mod->getAttrOfType("llvm.target"); + if (!targetAttr) + return; + + FailureOr 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(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 Date: Thu, 26 Jun 2025 09:15:32 -0700 Subject: [PATCH 2/7] 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 Date: Thu, 26 Jun 2025 10:02:48 -0700 Subject: [PATCH 3/7] 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 #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 { + : public LLVM::impl::LLVMDataLayoutFromTargetBase< + DataLayoutFromTargetPass> { void runOnOperation() override { ModuleOp mod = getOperation(); From b6a07f9559bec8dc3a3264f2f5da4178b34551f4 Mon Sep 17 00:00:00 2001 From: Rolf Morel Date: Thu, 26 Jun 2025 14:37:49 -0700 Subject: [PATCH 4/7] 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 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 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 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 TargetAttr::getDataLayout() { } FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) { + Attribute result; if (auto stringAttrKey = dyn_cast(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 Date: Thu, 26 Jun 2025 14:39:43 -0700 Subject: [PATCH 5/7] 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, +llvm.target = + #llvm.target } { +} 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 } { +} + +// ----- + +// 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> } { +} + +// ----- + +// 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, + llvm.target = #llvm.target> } { +} From 9b67848c47996d6eef87338b136bc53c2734665b Mon Sep 17 00:00:00 2001 From: Rolf Morel Date: Tue, 8 Jul 2025 09:19:33 -0700 Subject: [PATCH 6/7] 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 Date: Wed, 9 Jul 2025 08:43:47 -0700 Subject: [PATCH 7/7] 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 // ----- +// 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> } { +//} + +// ----- + // 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 } { +} + +// ----- + +// 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"