[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
This commit is contained in:
Rolf Morel 2025-08-20 23:00:30 +02:00 committed by GitHub
parent 2a66ce5edb
commit cbfa265e98
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 434 additions and 61 deletions

View File

@ -4,4 +4,5 @@ add_subdirectory(Dialect)
add_subdirectory(IR)
add_subdirectory(Interfaces)
add_subdirectory(Reducer)
add_subdirectory(Target)
add_subdirectory(Transforms)

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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 @@ public:
// 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

View File

@ -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"; }

View File

@ -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

View File

@ -0,0 +1 @@
add_subdirectory(LLVMIR)

View File

@ -0,0 +1 @@
add_subdirectory(Transforms)

View File

@ -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 @@ public:
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 @@ private:
/// 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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();

View File

@ -1,4 +1,5 @@
add_subdirectory(Dialect)
add_subdirectory(Transforms)
set(LLVM_OPTIONAL_SOURCES
ConvertFromLLVMIR.cpp

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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
)

View File

@ -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);
}
};

View File

@ -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"> } {
}

View File

@ -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"> } {
}

View File

@ -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"> } {
}