Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -1299,14 +1300,17 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
static constexpr StringLiteral getAttributeName() {
return StringLiteral("target_features");
}

/// Returns the attribute associated with the key.
FailureOr<Attribute> query(DataLayoutEntryKey key);
}];

let assemblyFormat = "`<` `[` (`]`) : ($features^ `]`)? `>`";
let genVerifyDecl = 1;
}

//===----------------------------------------------------------------------===//
// LLVM_TargetAttr
// TargetAttr
//===----------------------------------------------------------------------===//

def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
Expand All @@ -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) `>`}];

Expand Down
6 changes: 4 additions & 2 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -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)
>
Expand Down
1 change: 0 additions & 1 deletion mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include "mlir/Pass/Pass.h"

namespace mlir {

namespace LLVM {

#define GEN_PASS_DECL
Expand Down
16 changes: 16 additions & 0 deletions mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
35 changes: 35 additions & 0 deletions mlir/include/mlir/Target/LLVMIR/Transforms/TargetUtils.h
Original file line number Diff line number Diff line change
@@ -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<std::unique_ptr<llvm::TargetMachine>>
getTargetMachine(mlir::LLVM::TargetAttrInterface attr);

/// Helper to obtain the DataLayout of the target specified by the properties of
/// the TargetAttrInterface-implementing attribute.
FailureOr<llvm::DataLayout> getDataLayout(mlir::LLVM::TargetAttrInterface attr);
} // namespace detail
} // namespace LLVM
} // namespace mlir

#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H
54 changes: 37 additions & 17 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,43 @@ TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
getAttributeName());
}

FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
auto stringKey = dyn_cast<StringAttr>(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<StringAttr>(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<InFlightDiagnostic()> emitError,
LLVM::ModFlagBehavior flagBehavior, StringAttr key,
Expand Down Expand Up @@ -402,20 +439,3 @@ 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();
}
2 changes: 2 additions & 0 deletions mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
TargetToDataLayout.cpp
TargetToTargetFeatures.cpp
TargetUtils.cpp

DEPENDS
MLIRTargetLLVMIRTransformsIncGen
Expand Down
54 changes: 6 additions & 48 deletions mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -29,35 +22,6 @@ namespace LLVM {

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<
Expand All @@ -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::TargetAttrInterface>(
LLVM::LLVMDialect::getTargetAttrName());
Expand All @@ -85,7 +42,8 @@ struct TargetToDataLayoutPass
return signalPassFailure();
}

FailureOr<llvm::DataLayout> dataLayout = getDataLayout(targetAttr);
FailureOr<llvm::DataLayout> dataLayout =
LLVM::detail::getDataLayout(targetAttr);
if (failed(dataLayout)) {
op->emitError() << "failed to obtain llvm::DataLayout for " << targetAttr;
return signalPassFailure();
Expand Down
78 changes: 78 additions & 0 deletions mlir/lib/Target/LLVMIR/Transforms/TargetToTargetFeatures.cpp
Original file line number Diff line number Diff line change
@@ -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::TargetAttr>(
LLVM::LLVMDialect::getTargetAttrName());
if (!targetAttr) {
op->emitError() << "no LLVM::TargetAttr attribute at key \""
<< LLVM::LLVMDialect::getTargetAttrName() << "\"";
return signalPassFailure();
}

FailureOr<std::unique_ptr<llvm::TargetMachine>> 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<llvm::SubtargetFeatureKV> 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);
}
};
Loading
Loading