diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td index 138dd7703a5e7..bfce904a18d4f 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td @@ -1246,7 +1246,8 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> { // TargetFeaturesAttr //===----------------------------------------------------------------------===// -def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> +def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features", + [DLTIQueryInterface]> { let summary = "LLVM target features attribute"; @@ -1299,6 +1300,9 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> static constexpr StringLiteral getAttributeName() { return StringLiteral("target_features"); } + + /// Returns the attribute associated with the key. + FailureOr query(DataLayoutEntryKey key); }]; let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`"; @@ -1306,7 +1310,7 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features"> } //===----------------------------------------------------------------------===// -// LLVM_TargetAttr +// TargetAttr //===----------------------------------------------------------------------===// def LLVM_TargetAttr : LLVM_Attr<"Target", "target", @@ -1324,7 +1328,7 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target", }]; let parameters = (ins "StringAttr":$triple, "StringAttr":$chip, - OptionalParameter<"StringAttr", "">:$features); + OptionalParameter<"TargetFeaturesAttr", "">:$features); let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}]; diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td index 64600e86bedfb..60235bcb35561 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td @@ -560,8 +560,10 @@ def LLVM_TargetAttrInterface /*args=*/(ins) >, InterfaceMethod< - /*description=*/"Returns the target features as a string.", - /*retTy=*/"StringAttr", + /*description=*/"Returns the target features as a TargetFeaturesAttr.", + /*retTy=*/"Attribute", // NB: will be a LLVM::TargetFeaturesAttr, though + // need to work around a cyclic dependency on + // LLVMInterfaces.td and LLVMAttrDefs.td. /*methodName=*/"getFeatures", /*args=*/(ins) > diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h index 1e6419154108c..22e6fadfb37e9 100644 --- a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h +++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h @@ -12,7 +12,6 @@ #include "mlir/Pass/Pass.h" namespace mlir { - namespace LLVM { #define GEN_PASS_DECL diff --git a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td index 906f6e82efa50..c858e9f4c34cb 100644 --- a/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td +++ b/mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td @@ -27,4 +27,20 @@ def LLVMTargetToDataLayout : Pass<"llvm-target-to-data-layout"> { ]; } +def LLVMTargetToTargetFeatures : Pass<"llvm-target-to-target-features"> { + let summary = "Update attached #llvm.target's features per the described target"; + let description = [{ + Obtain the TargetMachine specified by the attached #llvm.target's attributes + and obtain from it the full list of features of the selected target. Updates + the attached #llvm.target so that its features reflect the full list of + features. + }]; + 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/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h b/mlir/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h new file mode 100644 index 0000000000000..2930733ee83d9 --- /dev/null +++ b/mlir/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h @@ -0,0 +1,35 @@ +//===- TargetUtils.h - Utils to obtain LLVM's TargetMachine and DataLayout ===// +// +// 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_TARGETUTILS_H +#define MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H + +#include "mlir/Dialect/LLVMIR/LLVMInterfaces.h" +#include "llvm/Support/Threading.h" +#include "llvm/Target/TargetMachine.h" + +namespace mlir { +namespace LLVM { +namespace detail { +/// Idempotent helper to register/initialize all backends that LLVM has been +/// configured to support. Only runs the first time it is called. +void initializeBackendsOnce(); + +/// Helper to obtain the TargetMachine specified by the properties of the +/// TargetAttrInterface-implementing attribute. +FailureOr> +getTargetMachine(mlir::LLVM::TargetAttrInterface attr); + +/// Helper to obtain the DataLayout of the target specified by the properties of +/// the TargetAttrInterface-implementing attribute. +FailureOr getDataLayout(mlir::LLVM::TargetAttrInterface attr); +} // namespace detail +} // namespace LLVM +} // namespace mlir + +#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp index 634efcaea794e..9d7a23f028cb0 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp @@ -374,6 +374,43 @@ TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) { getAttributeName()); } +FailureOr TargetFeaturesAttr::query(DataLayoutEntryKey key) { + auto stringKey = dyn_cast(key); + if (!stringKey) + return failure(); + + if (contains(stringKey)) + return UnitAttr::get(getContext()); + + if (contains((std::string("+") + stringKey.strref()).str())) + return BoolAttr::get(getContext(), true); + + if (contains((std::string("-") + stringKey.strref()).str())) + return BoolAttr::get(getContext(), false); + + return failure(); +} + +//===----------------------------------------------------------------------===// +// TargetAttr +//===----------------------------------------------------------------------===// + +FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) { + if (auto stringAttrKey = dyn_cast(key)) { + if (stringAttrKey.getValue() == "triple") + return getTriple(); + if (stringAttrKey.getValue() == "chip") + return getChip(); + if (stringAttrKey.getValue() == "features" && getFeatures()) + return getFeatures(); + } + return failure(); +} + +//===----------------------------------------------------------------------===// +// ModuleFlagAttr +//===----------------------------------------------------------------------===// + LogicalResult ModuleFlagAttr::verify(function_ref emitError, LLVM::ModFlagBehavior flagBehavior, StringAttr key, @@ -402,20 +439,3 @@ ModuleFlagAttr::verify(function_ref emitError, "supported for unknown key '" << key << "'"; } - -//===----------------------------------------------------------------------===// -// LLVM_TargetAttr -//===----------------------------------------------------------------------===// - -FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) { - if (auto stringAttrKey = dyn_cast(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/Target/LLVMIR/Transforms/CMakeLists.txt b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt index a0232601c5f9c..044da1c442049 100644 --- a/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt +++ b/mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt @@ -1,5 +1,7 @@ add_mlir_dialect_library(MLIRTargetLLVMIRTransforms TargetToDataLayout.cpp + TargetToTargetFeatures.cpp + TargetUtils.cpp DEPENDS MLIRTargetLLVMIRTransformsIncGen diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp index d41d441812039..c0f9ceb6313d0 100644 --- a/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp +++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp @@ -5,21 +5,14 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// + #include "mlir/Target/LLVMIR/Transforms/Passes.h" +#include "mlir/Target/LLVMIR/Transforms/TargetUtils.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 @@ -29,35 +22,6 @@ namespace LLVM { using namespace mlir; -static FailureOr> -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(target->createTargetMachine( - llvm::Triple(triple), chipAKAcpu, features, {}, {})); -} - -static FailureOr -getDataLayout(LLVM::TargetAttrInterface attr) { - FailureOr> 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 { using LLVM::impl::LLVMTargetToDataLayoutBase< @@ -66,15 +30,8 @@ struct TargetToDataLayoutPass 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(); - }); - } + if (initializeLLVMTargets) + LLVM::detail::initializeBackendsOnce(); auto targetAttr = op->getAttrOfType( LLVM::LLVMDialect::getTargetAttrName()); @@ -85,7 +42,8 @@ struct TargetToDataLayoutPass return signalPassFailure(); } - FailureOr dataLayout = getDataLayout(targetAttr); + FailureOr dataLayout = + LLVM::detail::getDataLayout(targetAttr); if (failed(dataLayout)) { op->emitError() << "failed to obtain llvm::DataLayout for " << targetAttr; return signalPassFailure(); diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp new file mode 100644 index 0000000000000..4a1ca46af0f2a --- /dev/null +++ b/mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp @@ -0,0 +1,78 @@ +//===- TargetToTargetFeatures.cpp - extract features 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/Target/LLVMIR/Transforms/TargetUtils.h" + +#include "mlir/Dialect/DLTI/DLTI.h" +#include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Target/LLVMIR/Import.h" + +#include "llvm/MC/MCSubtargetInfo.h" + +namespace mlir { +namespace LLVM { +#define GEN_PASS_DEF_LLVMTARGETTOTARGETFEATURES +#include "mlir/Target/LLVMIR/Transforms/Passes.h.inc" +} // namespace LLVM +} // namespace mlir + +using namespace mlir; + +struct TargetToTargetFeaturesPass + : public LLVM::impl::LLVMTargetToTargetFeaturesBase< + TargetToTargetFeaturesPass> { + using LLVM::impl::LLVMTargetToTargetFeaturesBase< + TargetToTargetFeaturesPass>::LLVMTargetToTargetFeaturesBase; + + void runOnOperation() override { + Operation *op = getOperation(); + + if (initializeLLVMTargets) + LLVM::detail::initializeBackendsOnce(); + + auto targetAttr = op->getAttrOfType( + LLVM::LLVMDialect::getTargetAttrName()); + if (!targetAttr) { + op->emitError() << "no LLVM::TargetAttr attribute at key \"" + << LLVM::LLVMDialect::getTargetAttrName() << "\""; + return signalPassFailure(); + } + + FailureOr> targetMachine = + LLVM::detail::getTargetMachine(targetAttr); + if (failed(targetMachine)) { + op->emitError() << "failed to obtain llvm::TargetMachine for " + << targetAttr; + return signalPassFailure(); + } + + llvm::MCSubtargetInfo const *subTargetInfo = + (*targetMachine)->getMCSubtargetInfo(); + + const std::vector enabledFeatures = + subTargetInfo->getEnabledProcessorFeatures(); + + auto plussedFeatures = llvm::to_vector( + llvm::map_range(enabledFeatures, [](llvm::SubtargetFeatureKV feature) { + return std::string("+") + feature.Key; + })); + + auto plussedFeaturesRefs = llvm::to_vector(llvm::map_range( + plussedFeatures, [](auto &it) { return StringRef(it.c_str()); })); + + auto fullTargetFeaturesAttr = + LLVM::TargetFeaturesAttr::get(&getContext(), plussedFeaturesRefs); + + auto updatedTargetAttr = + LLVM::TargetAttr::get(&getContext(), targetAttr.getTriple(), + targetAttr.getChip(), fullTargetFeaturesAttr); + + op->setAttr(LLVM::LLVMDialect::getTargetAttrName(), updatedTargetAttr); + } +}; diff --git a/mlir/lib/Target/LLVMIR/Transforms/TargetUtils.cpp b/mlir/lib/Target/LLVMIR/Transforms/TargetUtils.cpp new file mode 100644 index 0000000000000..f1d36228bef1f --- /dev/null +++ b/mlir/lib/Target/LLVMIR/Transforms/TargetUtils.cpp @@ -0,0 +1,71 @@ +//===- TargetUtils.cpp - utils for obtaining generic target backend info --===// +// +// 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/DebugLog.h" +#include "llvm/Support/TargetSelect.h" +#include "llvm/Target/TargetMachine.h" + +#define DEBUG_TYPE "mlir-llvm-target-utils" + +namespace mlir { +namespace LLVM { +namespace detail { +void initializeBackendsOnce() { + static const auto initOnce = [] { + // Ensure that the targets, that LLVM has been configured to support, + // are loaded into the TargetRegistry. + llvm::InitializeAllTargets(); + llvm::InitializeAllTargetMCs(); + return true; + }(); + (void)initOnce; // Dummy usage. +} + +FailureOr> +getTargetMachine(mlir::LLVM::TargetAttrInterface attr) { + StringRef triple = attr.getTriple(); + StringRef chipAKAcpu = attr.getChip(); + // NB: `TargetAttrInterface::getFeatures()` is coarsely typed to work around + // cyclic dependency issue in tablegen files. + auto featuresAttr = + llvm::cast_if_present(attr.getFeatures()); + std::string features = featuresAttr ? featuresAttr.getFeaturesString() : ""; + + 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(target->createTargetMachine( + llvm::Triple(triple), chipAKAcpu, features, {}, {})); +} + +FailureOr +getDataLayout(mlir::LLVM::TargetAttrInterface attr) { + FailureOr> targetMachine = + getTargetMachine(attr); + if (failed(targetMachine)) { + LDBG() << "Failed to retrieve the target machine for data layout.\n"; + return failure(); + } + return (targetMachine.value())->createDataLayout(); +} + +} // namespace detail +} // namespace LLVM +} // namespace mlir diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir b/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir deleted file mode 100644 index 45bfd6a465d7c..0000000000000 --- a/mlir/test/Dialect/LLVMIR/target-to-data-layout.mlir +++ /dev/null @@ -1,75 +0,0 @@ -// 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 } { -} - -// ----- - -// 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 } { -} - -// ----- - -// 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 } { -} - -// ----- - -// 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 } { -} - -// ----- - -// 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, - llvm.target = #llvm.target } { -} diff --git a/mlir/test/Target/LLVMIR/target-to-data-layout-and-target-features.mlir b/mlir/test/Target/LLVMIR/target-to-data-layout-and-target-features.mlir new file mode 100644 index 0000000000000..b6b2976860541 --- /dev/null +++ b/mlir/test/Target/LLVMIR/target-to-data-layout-and-target-features.mlir @@ -0,0 +1,137 @@ +// REQUIRES: target=x86{{.*}} + +// RUN: mlir-opt -llvm-target-to-data-layout -split-input-file %s | FileCheck --check-prefix=DATA-LAYOUT %s +// RUN: mlir-opt -llvm-target-to-target-features -split-input-file %s | FileCheck --check-prefix=TARGET-FEATURES %s + +// DATA-LAYOUT: module attributes +// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec +// DATA-LAYOUT-SAME: "dlti.endianness" = "little" +// DATA-LAYOUT-SAME: llvm.target = #llvm.target< +// DATA-LAYOUT-SAME: triple = "x86_64-unknown-linux" +// DATA-LAYOUT-SAME: chip = "" +// DATA-LAYOUT-NOT: features = + +// TARGET-FEATURES: module attributes +// TARGET-FEATURES-NOT: dlti.dl_spec +// TARGET-FEATURES-SAME: llvm.target = #llvm.target< +// TARGET-FEATURES-SAME: triple = "x86_64-unknown-linux" +// TARGET-FEATURES-SAME: chip = "" +// TARGET-FEATURES-SAME: features = <[ +// TARGET-FEATURES-SAME: +64bit +// TARGET-FEATURES-NOT: +avx +// TARGET-FEATURES-SAME: +sse +// TARGET-FEATURES-NOT: +mmx + +module attributes { llvm.target = #llvm.target } { +} + +// ----- + +// DATA-LAYOUT: module attributes +// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec +// DATA-LAYOUT-SAME: "dlti.endianness" = "little" +// DATA-LAYOUT-SAME: llvm.target = #llvm.target< +// DATA-LAYOUT-SAME: triple = "x86_64-unknown-linux" +// DATA-LAYOUT-SAME: chip = "" +// DATA-LAYOUT-SAME: features = <["+mmx", "+sse"]> + +// TARGET-FEATURES: module attributes +// TARGET-FEATURES-NOT: dlti.dl_spec +// TARGET-FEATURES-SAME: llvm.target = #llvm.target< +// TARGET-FEATURES-SAME: triple = "x86_64-unknown-linux" +// TARGET-FEATURES-SAME: chip = "" +// TARGET-FEATURES-SAME: features = <[ +// TARGET-FEATURES-SAME: +64bit +// TARGET-FEATURES-NOT: +avx +// TARGET-FEATURES-SAME: +mmx +// TARGET-FEATURES-SAME: +sse + +module attributes { llvm.target = #llvm.target> } { +} + +// ----- + +// DATA-LAYOUT: module attributes +// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec +// DATA-LAYOUT-SAME: "dlti.endianness" = "little" +// DATA-LAYOUT-SAME: llvm.target = #llvm.target< +// DATA-LAYOUT-SAME: triple = "x86_64-unknown-linux" +// DATA-LAYOUT-SAME: chip = "skylake" +// DATA-LAYOUT-NOT: features = + +// TARGET-FEATURES: module attributes +// TARGET-FEATURES-NOT: dlti.dl_spec +// TARGET-FEATURES-SAME: llvm.target = #llvm.target< +// TARGET-FEATURES-SAME: triple = "x86_64-unknown-linux" +// TARGET-FEATURES-SAME: chip = "skylake" +// TARGET-FEATURES-SAME: features = <[ +// TARGET-FEATURES-SAME: +64bit +// TARGET-FEATURES-SAME: +avx +// TARGET-FEATURES-SAME: +avx2 +// TARGET-FEATURES-NOT: +avx512f +// TARGET-FEATURES-SAME: +mmx +// TARGET-FEATURES-SAME: +sse + +module attributes { llvm.target = #llvm.target } { +} + +// ----- + +// DATA-LAYOUT: module attributes +// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec +// DATA-LAYOUT-SAME: "dlti.endianness" = "little" +// DATA-LAYOUT-SAME: llvm.target = #llvm.target< +// DATA-LAYOUT-SAME: triple = "x86_64-unknown-linux" +// DATA-LAYOUT-SAME: chip = "skylake" +// DATA-LAYOUT-SAME: features = <["-sse", "-avx"]> + +// TARGET-FEATURES: module attributes +// TARGET-FEATURES-NOT: dlti.dl_spec +// TARGET-FEATURES-SAME: llvm.target = #llvm.target< +// TARGET-FEATURES-SAME: triple = "x86_64-unknown-linux" +// TARGET-FEATURES-SAME: chip = "skylake" +// TARGET-FEATURES-SAME: features = <[ +// TARGET-FEATURES-SAME: +64bit +// TARGET-FEATURES-NOT: +avx +// TARGET-FEATURES-NOT: +avx2 +// TARGET-FEATURES-SAME: +mmx +// TARGET-FEATURES-NOT: +sse + +module attributes { llvm.target = #llvm.target> } { +} + +// ----- + +// DATA-LAYOUT: module attributes +// DATA-LAYOUT-SAME: dlti.dl_spec = #dlti.dl_spec +// DATA-LAYOUT-SAME: "dlti.endianness" = "little" +// DATA-LAYOUT-SAME: index = 32 +// DATA-LAYOUT-SAME: llvm.target = #llvm.target< +// DATA-LAYOUT-SAME: triple = "x86_64-unknown-linux" +// DATA-LAYOUT-SAME: chip = "skylake" +// DATA-LAYOUT-SAME: features = <["-mmx", "+avx512f"]> + +// TARGET-FEATURES: module attributes +// TARGET-FEATURES-SAME: #dlti.dl_spec +// TARGET-FEATURES-SAME: llvm.target = #llvm.target< +// TARGET-FEATURES-SAME: triple = "x86_64-unknown-linux" +// TARGET-FEATURES-SAME: chip = "skylake" +// TARGET-FEATURES-SAME: features = <[ +// TARGET-FEATURES-SAME: +64bit +// TARGET-FEATURES-SAME: +avx +// TARGET-FEATURES-SAME: +avx2 +// TARGET-FEATURES-SAME: +avx512f +// TARGET-FEATURES-NOT: +mmx +// TARGET-FEATURES-SAME: +sse + +module attributes { dlti.dl_spec = #dlti.dl_spec, + llvm.target = #llvm.target> } { +} diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir b/mlir/test/Target/LLVMIR/target-to-data-layout-invalid.mlir similarity index 100% rename from mlir/test/Dialect/LLVMIR/target-to-data-layout-invalid.mlir rename to mlir/test/Target/LLVMIR/target-to-data-layout-invalid.mlir diff --git a/mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir b/mlir/test/Target/LLVMIR/target-to-data-layout-no-init.mlir similarity index 100% rename from mlir/test/Dialect/LLVMIR/target-to-data-layout-no-init.mlir rename to mlir/test/Target/LLVMIR/target-to-data-layout-no-init.mlir diff --git a/mlir/test/Target/LLVMIR/target-to-target-features-dlti-query.mlir b/mlir/test/Target/LLVMIR/target-to-target-features-dlti-query.mlir new file mode 100644 index 0000000000000..9a1f49b0bca80 --- /dev/null +++ b/mlir/test/Target/LLVMIR/target-to-target-features-dlti-query.mlir @@ -0,0 +1,75 @@ +// REQUIRES: target=x86{{.*}} + +// RUN: mlir-opt -transform-interpreter -split-input-file %s --verify-diagnostics + +// Check that processor features, like AVX, are appropriated derived and queryable. + +// expected-remark @+2 {{attr associated to ["features", "+avx"] = unit}} +// expected-remark @below {{attr associated to ["features", "avx"] = true}} +module attributes { llvm.target = #llvm.target, + test.dl_spec = #dlti.dl_spec } { + func.func private @f() +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg: !transform.any_op) { + %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op + %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op + %mod = transform.apply_registered_pass "llvm-target-to-target-features" to %module : (!transform.any_op) -> !transform.any_op + %plus_avx = transform.dlti.query ["features", "+avx"] at %mod : (!transform.any_op) -> !transform.any_param + transform.debug.emit_param_as_remark %plus_avx, "attr associated to [\"features\", \"+avx\"] =" at %mod : !transform.any_param, !transform.any_op + %avx = transform.dlti.query ["features", "avx"] at %mod : (!transform.any_op) -> !transform.any_param + transform.debug.emit_param_as_remark %avx, "attr associated to [\"features\", \"avx\"] =" at %mod : !transform.any_param, !transform.any_op + transform.yield + } +} + +// ----- + +// Check that newer processor features, like AMX, are appropriated derived and queryable. + +// expected-remark @+2 {{attr associated to ["features", "+amx-bf16"] = unit}} +// expected-remark @below {{attr associated to ["features", "amx-bf16"] = true}} +module attributes { llvm.target = #llvm.target, + test.dl_spec = #dlti.dl_spec } { + func.func private @f() +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg: !transform.any_op) { + %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op + %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op + %mod = transform.apply_registered_pass "llvm-target-to-target-features" to %module : (!transform.any_op) -> !transform.any_op + %plus_avx = transform.dlti.query ["features", "+amx-bf16"] at %mod : (!transform.any_op) -> !transform.any_param + transform.debug.emit_param_as_remark %plus_avx, "attr associated to [\"features\", \"+amx-bf16\"] =" at %mod : !transform.any_param, !transform.any_op + %avx = transform.dlti.query ["features", "amx-bf16"] at %mod : (!transform.any_op) -> !transform.any_param + transform.debug.emit_param_as_remark %avx, "attr associated to [\"features\", \"amx-bf16\"] =" at %mod : !transform.any_param, !transform.any_op + transform.yield + } +} + +// ----- + +// Check that features that a processor does not have, AMX in this case, +// aren't derived and hence that querying for them will fail. + +// expected-error @+2 {{target op of failed DLTI query}} +// expected-note @below {{key "+amx-bf16" has no DLTI-mapping per attr: #llvm.target_features}} +module attributes { llvm.target = #llvm.target, + test.dl_spec = #dlti.dl_spec } { + func.func private @f() +} + +module attributes {transform.with_named_sequence} { + transform.named_sequence @__transform_main(%arg: !transform.any_op) { + %funcs = transform.structured.match ops{["func.func"]} in %arg : (!transform.any_op) -> !transform.any_op + %module = transform.get_parent_op %funcs : (!transform.any_op) -> !transform.any_op + %mod = transform.apply_registered_pass "llvm-target-to-target-features" to %module : (!transform.any_op) -> !transform.any_op + // expected-error @below {{'transform.dlti.query' op failed to apply}} + %param = transform.dlti.query ["features", "+amx-bf16"] at %mod : (!transform.any_op) -> !transform.any_param + transform.yield + } +}