[Mlir-commits] [mlir] cbfa265 - [MLIR][LLVMIR][DLTI] Add `LLVM::TargetAttrInterface` and `#llvm.target` attr (#145899)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Wed Aug 20 14:00:33 PDT 2025
Author: Rolf Morel
Date: 2025-08-20T22:00:30+01:00
New Revision: cbfa265e989ca65b0625ba2ce9059774b2ddad42
URL: https://github.com/llvm/llvm-project/commit/cbfa265e989ca65b0625ba2ce9059774b2ddad42
DIFF: https://github.com/llvm/llvm-project/commit/cbfa265e989ca65b0625ba2ce9059774b2ddad42.diff
LOG: [MLIR][LLVMIR][DLTI] Add `LLVM::TargetAttrInterface` and `#llvm.target` attr (#145899)
Adds the `#llvm.target<triple = $TRIPLE, chip = $CHIP, features =
$FEATURES>` attribute and along with a `-llvm-target-to-data-layout`
pass to derive a MLIR data layout from the LLVM data layout string
(using the existing `DataLayoutImporter`). The attribute implements the
relevant DLTI-interfaces, to expose the `triple`, `chip` (AKA `cpu`) and
`features` on `#llvm.target` and the full `DataLayoutSpecInterface`. The
pass combines the generated `#dlti.dl_spec` with an existing `dl_spec`
in case one is already present, e.g. a `dl_spec` which is there to
specify size of the `index` type.
Adds a `TargetAttrInterface` which can be implemented by all attributes
representing LLVM targets.
Similar to the Draft PR https://github.com/llvm/llvm-project/pull/78073.
RFC on which this PR is based:
https://discourse.llvm.org/t/mandatory-data-layout-in-the-llvm-dialect/85875
Added:
mlir/include/mlir/Target/CMakeLists.txt
mlir/include/mlir/Target/LLVMIR/CMakeLists.txt
mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt
mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
Modified:
mlir/include/mlir/CMakeLists.txt
mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
mlir/lib/Dialect/DLTI/Traits.cpp
mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
mlir/lib/RegisterAllPasses.cpp
mlir/lib/Target/LLVMIR/CMakeLists.txt
mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
mlir/lib/Target/LLVMIR/ModuleImport.cpp
Removed:
mlir/lib/Target/LLVMIR/DataLayoutImporter.h
################################################################################
diff --git a/mlir/include/mlir/CMakeLists.txt b/mlir/include/mlir/CMakeLists.txt
index 9cf3b442aa4ad..f88a35ba1efc7 100644
--- a/mlir/include/mlir/CMakeLists.txt
+++ b/mlir/include/mlir/CMakeLists.txt
@@ -4,4 +4,5 @@ add_subdirectory(Dialect)
add_subdirectory(IR)
add_subdirectory(Interfaces)
add_subdirectory(Reducer)
+add_subdirectory(Target)
add_subdirectory(Transforms)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
index 790d2e77ea874..138dd7703a5e7 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
@@ -13,6 +13,7 @@ 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,
@@ -1304,6 +1305,34 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
let genVerifyDecl = 1;
}
+//===----------------------------------------------------------------------===//
+// 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 is optional.
+
+ Responds to DLTI-queries on the keys:
+ * A query for `"triple"` returns the `StringAttr` for the `triple`.
+ * A query for `"chip"` returns the `StringAttr` for the `chip`/`cpu`.
+ * A query for `"features"` returns the `StringAttr`, if provided.
+ }];
+ let parameters = (ins "StringAttr":$triple,
+ "StringAttr":$chip,
+ OptionalParameter<"StringAttr", "">:$features);
+
+ let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
+
+ let extraClassDeclaration = [{
+ FailureOr<Attribute> query(DataLayoutEntryKey key);
+ }];
+}
+
//===----------------------------------------------------------------------===//
// UndefAttr
//===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
index 3ede857733242..1ceeb7e4ba2a5 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
@@ -16,6 +16,7 @@
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/OpImplementation.h"
+#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include <optional>
#include "mlir/Dialect/LLVMIR/LLVMOpsEnums.h.inc"
@@ -89,8 +90,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/include/mlir/Dialect/LLVMIR/LLVMDialect.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
index 107bf3edb657a..ab0462f945a33 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMDialect.td
@@ -27,6 +27,7 @@ def LLVM_Dialect : Dialect {
);
let extraClassDeclaration = [{
+ static StringRef getTargetAttrName() { return "llvm.target"; }
/// Name of the data layout attributes.
static StringRef getDataLayoutAttrName() { return "llvm.data_layout"; }
static StringRef getNoAliasScopesAttrName() { return "noalias_scopes"; }
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
index 138170f8c8762..64600e86bedfb 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,39 @@ def LLVM_DIRecursiveTypeAttrInterface
];
}
+def LLVM_TargetAttrInterface
+ : AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
+ let description = [{
+ Interface for attributes that describe LLVM targets.
+
+ These attributes should be able to return the specified target `triple`,
+ `chip` and `features`.
+
+ 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=*/"StringAttr",
+ /*methodName=*/"getTriple",
+ /*args=*/(ins)
+ >,
+ InterfaceMethod<
+ /*description=*/"Returns the target chip (i.e. \"cpu\") identifier.",
+ /*retTy=*/"StringAttr",
+ /*methodName=*/"getChip",
+ /*args=*/(ins)
+ >,
+ InterfaceMethod<
+ /*description=*/"Returns the target features as a string.",
+ /*retTy=*/"StringAttr",
+ /*methodName=*/"getFeatures",
+ /*args=*/(ins)
+ >
+ ];
+}
+
#endif // LLVMIR_INTERFACES
diff --git a/mlir/include/mlir/Target/CMakeLists.txt b/mlir/include/mlir/Target/CMakeLists.txt
new file mode 100644
index 0000000000000..39d31dc9b5e9c
--- /dev/null
+++ b/mlir/include/mlir/Target/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(LLVMIR)
diff --git a/mlir/include/mlir/Target/LLVMIR/CMakeLists.txt b/mlir/include/mlir/Target/LLVMIR/CMakeLists.txt
new file mode 100644
index 0000000000000..e31af32661164
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/CMakeLists.txt
@@ -0,0 +1 @@
+add_subdirectory(Transforms)
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
similarity index 71%
rename from mlir/lib/Target/LLVMIR/DataLayoutImporter.h
rename to mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
index 88ceaf1a74e62..4d432df493c3f 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.h
+++ b/mlir/include/mlir/Target/LLVMIR/DataLayoutImporter.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
-#define MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
+#ifndef MLIR_TARGET_LLVMIR_DATALAYOUTIMPORTER_H
+#define MLIR_TARGET_LLVMIR_DATALAYOUTIMPORTER_H
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/IR/BuiltinAttributes.h"
@@ -38,23 +38,31 @@ namespace detail {
/// null if the bit width is not supported.
FloatType getFloatType(MLIRContext *context, unsigned width);
-/// 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) {
- translateDataLayout(llvmDataLayout);
+ DataLayoutImporter(MLIRContext *context, StringRef dataLayoutStr)
+ : dataLayoutStr(dataLayoutStr), context(context) {
+ // Translate the `dataLayoutStr`. First, append the default data layout
+ // string specified in the language reference
+ // (https://llvm.org/docs/LangRef.html#data-layout) to the supplied string.
+ // The translation then parses the string and ignores the default value if a
+ // specific kind occurs in both strings. Additionally, the following default
+ // values exist:
+ // - non-default address space pointer specifications default to the default
+ // address space pointer specification
+ // - the alloca address space defaults to the default address space.
+ dataLayoutSpec = dataLayoutSpecFromDataLayoutStr();
}
/// 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.
@@ -65,8 +73,9 @@ class DataLayoutImporter {
ArrayRef<StringRef> getUnhandledTokens() const { return unhandledTokens; }
private:
- /// Translates the LLVM `dataLayout` to an MLIR data layout specification.
- void translateDataLayout(const llvm::DataLayout &llvmDataLayout);
+ /// Translate the LLVM data layout string to an MLIR data layout
+ /// specification.
+ DataLayoutSpecInterface dataLayoutSpecFromDataLayoutStr();
/// Tries to parse the letter only prefix that identifies the specification
/// and removes the consumed characters from the beginning of the string.
@@ -116,17 +125,18 @@ 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 detail
} // namespace LLVM
} // namespace mlir
-#endif // MLIR_LIB_TARGET_LLVMIR_DATALAYOUTIMPORTER_H_
+#endif // MLIR_TARGET_LLVMIR_DATALAYOUTIMPORTER_H
diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt
new file mode 100644
index 0000000000000..b1a3c79b9b837
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_TARGET_DEFINITIONS Passes.td)
+mlir_tablegen(Passes.h.inc -gen-pass-decls -name TargetLLVMIRTransforms)
+add_public_tablegen_target(MLIRTargetLLVMIRTransformsIncGen)
+
+add_mlir_doc(Passes TargetLLVMIRTransforms ./ -gen-pass-doc)
diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
new file mode 100644
index 0000000000000..1e6419154108c
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
@@ -0,0 +1,27 @@
+//===- Passes.h - LLVM Target Pass Construction and Registration ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES_H
+#define MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES_H
+
+#include "mlir/Pass/Pass.h"
+
+namespace mlir {
+
+namespace LLVM {
+
+#define GEN_PASS_DECL
+#define GEN_PASS_REGISTRATION
+#include "mlir/Target/LLVMIR/Transforms/Passes.h.inc"
+
+void registerTargetLLVMPasses();
+
+} // namespace LLVM
+} // namespace mlir
+
+#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES_H
diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
new file mode 100644
index 0000000000000..906f6e82efa50
--- /dev/null
+++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
@@ -0,0 +1,30 @@
+//===-- Passes.td - LLVM Target pass definition file -------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES
+#define MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES
+
+include "mlir/Pass/PassBase.td"
+
+def LLVMTargetToDataLayout : Pass<"llvm-target-to-data-layout"> {
+ let summary = "Derive data layout attributes from LLVM target attributes";
+ let dependentDialects = ["mlir::DLTIDialect"];
+ let description = [{
+ Derive a `DataLayoutSpecInterface`-implementing data layout attribute from
+ the LLVM-backend target specified by the `TargetAttrInterface`-implementing
+ attribute attached to the target op at the name `llvm.target`.
+ }];
+ let options = [
+ Option<"initializeLLVMTargets", "initialize-llvm-targets", "bool",
+ /*default=*/"true",
+ "Whether to pre-load all available target machines, that LLVM is "
+ "configured to support, into the TargetRegistry.">
+ ];
+}
+
+#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES
diff --git a/mlir/lib/Dialect/DLTI/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/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
index 1e02bfe62f379..634efcaea794e 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
@@ -402,3 +402,20 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
"supported for unknown key '"
<< key << "'";
}
+
+//===----------------------------------------------------------------------===//
+// LLVM_TargetAttr
+//===----------------------------------------------------------------------===//
+
+FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
+ if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
+ if (stringAttrKey.getValue() == "triple")
+ return getTriple();
+ if (stringAttrKey.getValue() == "chip")
+ return getChip();
+ if (stringAttrKey.getValue() == "features" && getFeatures())
+ return getFeatures();
+ }
+
+ return failure();
+}
diff --git a/mlir/lib/RegisterAllPasses.cpp b/mlir/lib/RegisterAllPasses.cpp
index 1ed3a3798b0d2..c67b24226ae45 100644
--- a/mlir/lib/RegisterAllPasses.cpp
+++ b/mlir/lib/RegisterAllPasses.cpp
@@ -45,6 +45,7 @@
#include "mlir/Dialect/Transform/Transforms/Passes.h"
#include "mlir/Dialect/Vector/Transforms/Passes.h"
#include "mlir/Dialect/XeGPU/Transforms/Passes.h"
+#include "mlir/Target/LLVMIR/Transforms/Passes.h"
#include "mlir/Transforms/Passes.h"
// This function may be called to register the MLIR passes with the
@@ -74,6 +75,7 @@ void mlir::registerAllPasses() {
registerNVGPUPasses();
registerSparseTensorPasses();
LLVM::registerLLVMPasses();
+ LLVM::registerTargetLLVMIRTransformsPasses();
math::registerMathPasses();
memref::registerMemRefPasses();
shard::registerShardPasses();
diff --git a/mlir/lib/Target/LLVMIR/CMakeLists.txt b/mlir/lib/Target/LLVMIR/CMakeLists.txt
index 9ea5c6835e8ef..d39b35526daf9 100644
--- a/mlir/lib/Target/LLVMIR/CMakeLists.txt
+++ b/mlir/lib/Target/LLVMIR/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(Dialect)
+add_subdirectory(Transforms)
set(LLVM_OPTIONAL_SOURCES
ConvertFromLLVMIR.cpp
diff --git a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
index fbad5c2fb78d9..8bd07cd4e2ed9 100644
--- a/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
+++ b/mlir/lib/Target/LLVMIR/DataLayoutImporter.cpp
@@ -6,13 +6,14 @@
//
//===----------------------------------------------------------------------===//
-#include "DataLayoutImporter.h"
+#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
#include "mlir/Dialect/DLTI/DLTI.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "mlir/Target/LLVMIR/Import.h"
+
#include "llvm/IR/DataLayout.h"
using namespace mlir;
@@ -274,101 +275,88 @@ 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();
- if (!layoutStr.empty())
- layoutStr += "-";
- layoutStr += kDefaultDataLayout;
- StringRef layout(layoutStr);
+DataLayoutSpecInterface DataLayoutImporter::dataLayoutSpecFromDataLayoutStr() {
+ if (!dataLayoutStr.empty())
+ dataLayoutStr += "-";
+ dataLayoutStr += kDefaultDataLayout;
// Split the data layout string into tokens separated by a dash.
SmallVector<StringRef> tokens;
- layout.split(tokens, '-');
+ StringRef(dataLayoutStr).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.
@@ -376,17 +364,17 @@ void DataLayoutImporter::translateDataLayout(
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.
@@ -394,7 +382,7 @@ void DataLayoutImporter::translateDataLayout(
if (prefix->starts_with("F")) {
StringRef nextPrefix = prefix->drop_front(1);
if (failed(tryToEmplaceFunctionPointerAlignmentEntry(nextPrefix, token)))
- return;
+ return {};
continue;
}
@@ -409,11 +397,12 @@ void DataLayoutImporter::translateDataLayout(
entries.push_back(it.second);
for (const auto &it : keyEntries)
entries.push_back(it.second);
- dataLayout = DataLayoutSpecAttr::get(context, entries);
+ return DataLayoutSpecAttr::get(context, entries);
}
DataLayoutSpecInterface
mlir::translateDataLayout(const llvm::DataLayout &dataLayout,
MLIRContext *context) {
- return DataLayoutImporter(context, dataLayout).getDataLayout();
+ return DataLayoutImporter(context, dataLayout.getStringRepresentation())
+ .getDataLayoutSpec();
}
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 6325480e63657..40726365cd06e 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -16,7 +16,6 @@
#include "mlir/Target/LLVMIR/Import.h"
#include "AttrKindDetail.h"
-#include "DataLayoutImporter.h"
#include "DebugImporter.h"
#include "LoopAnnotationImporter.h"
@@ -25,6 +24,7 @@
#include "mlir/IR/Builders.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
+#include "mlir/Target/LLVMIR/DataLayoutImporter.h"
#include "mlir/Tools/mlir-translate/Translation.h"
#include "llvm/ADT/DepthFirstIterator.h"
@@ -1045,8 +1045,9 @@ LogicalResult ModuleImport::convertIFuncs() {
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();
@@ -1054,7 +1055,7 @@ LogicalResult ModuleImport::convertDataLayout() {
emitWarning(loc, "unhandled data layout token: ") << token;
mlirModule->setAttr(DLTIDialect::kDataLayoutAttrName,
- dataLayoutImporter.getDataLayout());
+ dataLayoutImporter.getDataLayoutSpec());
return success();
}
diff --git a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
new file mode 100644
index 0000000000000..a0232601c5f9c
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
@@ -0,0 +1,21 @@
+add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
+ TargetToDataLayout.cpp
+
+ DEPENDS
+ MLIRTargetLLVMIRTransformsIncGen
+
+ LINK_COMPONENTS
+ MC
+ Target
+ TargetParser
+ AllTargetsAsmParsers
+ AllTargetsCodeGens
+ AllTargetsDescs
+ AllTargetsInfos
+
+ LINK_LIBS PUBLIC
+ MLIRDLTIDialect
+ MLIRLLVMDialect
+ MLIRPass
+ MLIRTargetLLVMIRImport
+ )
diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
new file mode 100644
index 0000000000000..d41d441812039
--- /dev/null
+++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
@@ -0,0 +1,104 @@
+//===- TargetToDataLayout.cpp - extract data layout from TargetMachine ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#include "mlir/Target/LLVMIR/Transforms/Passes.h"
+
+#include "mlir/Dialect/DLTI/DLTI.h"
+#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Target/LLVMIR/Import.h"
+
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Target/TargetMachine.h"
+
+#define DEBUG_TYPE "mlir-llvm-target-to-data-layout"
+#define DBGS() (llvm::dbgs() << '[' << DEBUG_TYPE << "] ")
+#define LDBG(X) LLVM_DEBUG(DBGS() << X << "\n")
+
+namespace mlir {
+namespace LLVM {
+#define GEN_PASS_DEF_LLVMTARGETTODATALAYOUT
+#include "mlir/Target/LLVMIR/Transforms/Passes.h.inc"
+} // namespace LLVM
+} // namespace mlir
+
+using namespace mlir;
+
+static FailureOr<std::unique_ptr<llvm::TargetMachine>>
+getTargetMachine(LLVM::TargetAttrInterface attr) {
+ StringRef triple = attr.getTriple();
+ StringRef chipAKAcpu = attr.getChip();
+ StringRef features = attr.getFeatures() ? attr.getFeatures().getValue() : "";
+
+ std::string error;
+ const llvm::Target *target =
+ llvm::TargetRegistry::lookupTarget(triple, error);
+ if (!target || !error.empty()) {
+ LDBG("Looking up target '" << triple << "' failed: " << error << "\n");
+ return failure();
+ }
+
+ return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
+ llvm::Triple(triple), chipAKAcpu, features, {}, {}));
+}
+
+static FailureOr<llvm::DataLayout>
+getDataLayout(LLVM::TargetAttrInterface attr) {
+ FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
+ getTargetMachine(attr);
+ if (failed(targetMachine)) {
+ LDBG("Failed to retrieve the target machine for data layout.\n");
+ return failure();
+ }
+ return (targetMachine.value())->createDataLayout();
+}
+
+struct TargetToDataLayoutPass
+ : public LLVM::impl::LLVMTargetToDataLayoutBase<TargetToDataLayoutPass> {
+ using LLVM::impl::LLVMTargetToDataLayoutBase<
+ TargetToDataLayoutPass>::LLVMTargetToDataLayoutBase;
+
+ void runOnOperation() override {
+ Operation *op = getOperation();
+
+ if (initializeLLVMTargets) {
+ static llvm::once_flag initializeBackendsOnce;
+ llvm::call_once(initializeBackendsOnce, []() {
+ // Ensure that the targets, that LLVM has been configured to support,
+ // are loaded into the TargetRegistry.
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllTargetMCs();
+ });
+ }
+
+ auto targetAttr = op->getAttrOfType<LLVM::TargetAttrInterface>(
+ LLVM::LLVMDialect::getTargetAttrName());
+ if (!targetAttr) {
+ op->emitError()
+ << "no TargetAttrInterface-implementing attribute at key \""
+ << LLVM::LLVMDialect::getTargetAttrName() << "\"";
+ return signalPassFailure();
+ }
+
+ FailureOr<llvm::DataLayout> dataLayout = getDataLayout(targetAttr);
+ if (failed(dataLayout)) {
+ op->emitError() << "failed to obtain llvm::DataLayout for " << targetAttr;
+ return signalPassFailure();
+ }
+
+ DataLayoutSpecInterface dataLayoutSpec =
+ mlir::translateDataLayout(dataLayout.value(), &getContext());
+
+ if (auto existingDlSpec = op->getAttrOfType<DataLayoutSpecInterface>(
+ DLTIDialect::kDataLayoutAttrName)) {
+ dataLayoutSpec = existingDlSpec.combineWith({dataLayoutSpec});
+ }
+
+ op->setAttr(DLTIDialect::kDataLayoutAttrName, dataLayoutSpec);
+ }
+};
diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
new file mode 100644
index 0000000000000..c0ff53457d17e
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir
@@ -0,0 +1,9 @@
+// REQUIRES: target=x86{{.*}}
+// RUN: mlir-opt %s -llvm-target-to-data-layout --split-input-file --verify-diagnostics
+
+// expected-error @+1 {{failed to obtain llvm::DataLayout for #llvm.target}}
+module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
+llvm.target =
+ #llvm.target<triple="x64_86-unknown-linux",
+ chip="NON-EXISTING CHIP"> } {
+}
diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
new file mode 100644
index 0000000000000..2a9e9783eacb1
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir
@@ -0,0 +1,12 @@
+// REQUIRES: target=x86{{.*}}
+// RUN: mlir-opt %s -llvm-target-to-data-layout="initialize-llvm-targets=false" --split-input-file --verify-diagnostics
+
+// Without initializing the (right) LLVM targets/backends ("initialize-llvm-targets=false"),
+// it is not possible to obtain LLVM's DataLayout for the target.
+
+// expected-error @+1 {{failed to obtain llvm::DataLayout for #llvm.target}}
+module attributes { dlti.dl_spec = #dlti.dl_spec<index = 32>,
+llvm.target =
+ #llvm.target<triple="x64_86-unknown-linux",
+ chip="skylake"> } {
+}
diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
new file mode 100644
index 0000000000000..45bfd6a465d7c
--- /dev/null
+++ b/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir
@@ -0,0 +1,75 @@
+// REQUIRES: target=x86{{.*}}
+// RUN: mlir-opt -llvm-target-to-data-layout -split-input-file %s | FileCheck %s
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME: "dlti.endianness" = "little"
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME: triple = "x86_64-unknown-linux"
+// CHECK-SAME: chip = ""
+// CHECK-NOT: features =
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+ chip = ""> } {
+}
+
+// -----
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME: "dlti.endianness" = "little"
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME: triple = "x86_64-unknown-linux"
+// CHECK-SAME: chip = ""
+// CHECK-SAME: features = "+mmx,+sse"
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+ chip = "",
+ features = "+mmx,+sse"> } {
+}
+
+// -----
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME: "dlti.endianness" = "little"
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME: triple = "x86_64-unknown-linux"
+// CHECK-SAME: chip = "skylake"
+// CHECK-NOT: features =
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+ chip = "skylake"> } {
+}
+
+// -----
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME: "dlti.endianness" = "little"
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME: triple = "x86_64-unknown-linux"
+// CHECK-SAME: chip = "skylake"
+// CHECK-SAME: features = "+mmx,+sse">
+
+module attributes { llvm.target = #llvm.target<triple = "x86_64-unknown-linux",
+ chip = "skylake",
+ features = "+mmx,+sse"> } {
+}
+
+// -----
+
+// CHECK: module attributes
+// CHECK-SAME: dlti.dl_spec = #dlti.dl_spec
+// CHECK-SAME: "dlti.endianness" = "little"
+// CHECK-SAME: index = 32
+// CHECK-SAME: llvm.target = #llvm.target<
+// CHECK-SAME: triple = "x86_64-unknown-linux"
+// CHECK-SAME: chip = "skylake"
+// 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",
+ features = "+mmx,+sse"> } {
+}
More information about the Mlir-commits
mailing list