Skip to content

Commit 4b84223

Browse files
authored
[MLIR][LLVMIR][DLTI] Pass to update #llvm.target's features per relevant backend (#154938)
Modifies `#llvm.target<..., features = $FEATURES>` so that `$FEATURES` is now an `#llvm.target_features<[...]>` attribute (rather than a `StringAttr`). This enables the attribute to respond to DLTI queries for the different target features. The pass updates the `$FEATURES` attribute of the target attr at name `llvm.target` in accordance with the (Sub)Target's features that the relevant LLVM backend knows about. --- DEMO: ```mlir module attributes {llvm.target = #llvm.target<triple = "x86_64-unknown-linux", chip = "skylake"> } { } ``` by way of `-llvm-target-to-target-features` turns into: ```mlir module attributes {llvm.target = #llvm.target<triple = "x86_64-unknown-linux", chip = "skylake", features = <["+64bit", "+64bit-mode", "+adx", "+aes", "+allow-light-256-bit", "+avx", "+avx2", "+bmi", "+bmi2", "+clflushopt", "+cmov", "+crc32", "+cx16", "+cx8", "+ermsb", "+f16c", "+false-deps-popcnt", "+fast-15bytenop", "+fast-gather", "+fast-scalar-fsqrt", "+fast-shld-rotate", "+fast-variable-crosslane-shuffle", "+fast-variable-perlane-shuffle", "+fast-vector-fsqrt", "+fma", "+fsgsbase", "+fxsr", "+idivq-to-divl", "+invpcid", "+lzcnt", "+macrofusion", "+mmx", "+movbe", "+no-bypass-delay-blend", "+no-bypass-delay-mov", "+no-bypass-delay-shuffle", "+nopl", "+pclmul", "+popcnt", "+prfchw", "+rdrnd", "+rdseed", "+sahf", "+slow-3ops-lea", "+sse", "+sse2", "+sse3", "+sse4.1", "+sse4.2", "+ssse3", "+vzeroupper", "+x87", "+xsave", "+xsavec", "+xsaveopt", "+xsaves"]>>} { } ```
1 parent e423334 commit 4b84223

File tree

15 files changed

+468
-146
lines changed

15 files changed

+468
-146
lines changed

mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,8 @@ def LLVM_VScaleRangeAttr : LLVM_Attr<"VScaleRange", "vscale_range"> {
12461246
// TargetFeaturesAttr
12471247
//===----------------------------------------------------------------------===//
12481248

1249-
def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
1249+
def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features",
1250+
[DLTIQueryInterface]>
12501251
{
12511252
let summary = "LLVM target features attribute";
12521253

@@ -1299,14 +1300,17 @@ def LLVM_TargetFeaturesAttr : LLVM_Attr<"TargetFeatures", "target_features">
12991300
static constexpr StringLiteral getAttributeName() {
13001301
return StringLiteral("target_features");
13011302
}
1303+
1304+
/// Returns the attribute associated with the key.
1305+
FailureOr<Attribute> query(DataLayoutEntryKey key);
13021306
}];
13031307

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

13081312
//===----------------------------------------------------------------------===//
1309-
// LLVM_TargetAttr
1313+
// TargetAttr
13101314
//===----------------------------------------------------------------------===//
13111315

13121316
def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
@@ -1324,7 +1328,7 @@ def LLVM_TargetAttr : LLVM_Attr<"Target", "target",
13241328
}];
13251329
let parameters = (ins "StringAttr":$triple,
13261330
"StringAttr":$chip,
1327-
OptionalParameter<"StringAttr", "">:$features);
1331+
OptionalParameter<"TargetFeaturesAttr", "">:$features);
13281332

13291333
let assemblyFormat = [{`<` struct($triple, $chip, $features) `>`}];
13301334

mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,8 +560,10 @@ def LLVM_TargetAttrInterface
560560
/*args=*/(ins)
561561
>,
562562
InterfaceMethod<
563-
/*description=*/"Returns the target features as a string.",
564-
/*retTy=*/"StringAttr",
563+
/*description=*/"Returns the target features as a TargetFeaturesAttr.",
564+
/*retTy=*/"Attribute", // NB: will be a LLVM::TargetFeaturesAttr, though
565+
// need to work around a cyclic dependency on
566+
// LLVMInterfaces.td and LLVMAttrDefs.td.
565567
/*methodName=*/"getFeatures",
566568
/*args=*/(ins)
567569
>

mlir/include/mlir/Target/LLVMIR/Transforms/Passes.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "mlir/Pass/Pass.h"
1313

1414
namespace mlir {
15-
1615
namespace LLVM {
1716

1817
#define GEN_PASS_DECL

mlir/include/mlir/Target/LLVMIR/Transforms/Passes.td

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,20 @@ def LLVMTargetToDataLayout : Pass<"llvm-target-to-data-layout"> {
2727
];
2828
}
2929

30+
def LLVMTargetToTargetFeatures : Pass<"llvm-target-to-target-features"> {
31+
let summary = "Update attached #llvm.target's features per the described target";
32+
let description = [{
33+
Obtain the TargetMachine specified by the attached #llvm.target's attributes
34+
and obtain from it the full list of features of the selected target. Updates
35+
the attached #llvm.target so that its features reflect the full list of
36+
features.
37+
}];
38+
let options = [
39+
Option<"initializeLLVMTargets", "initialize-llvm-targets", "bool",
40+
/*default=*/"true",
41+
"Whether to pre-load all available target machines, that LLVM is "
42+
"configured to support, into the TargetRegistry.">
43+
];
44+
}
45+
3046
#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_PASSES
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//===- TargetUtils.h - Utils to obtain LLVM's TargetMachine and DataLayout ===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H
10+
#define MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H
11+
12+
#include "mlir/Dialect/LLVMIR/LLVMInterfaces.h"
13+
#include "llvm/Support/Threading.h"
14+
#include "llvm/Target/TargetMachine.h"
15+
16+
namespace mlir {
17+
namespace LLVM {
18+
namespace detail {
19+
/// Idempotent helper to register/initialize all backends that LLVM has been
20+
/// configured to support. Only runs the first time it is called.
21+
void initializeBackendsOnce();
22+
23+
/// Helper to obtain the TargetMachine specified by the properties of the
24+
/// TargetAttrInterface-implementing attribute.
25+
FailureOr<std::unique_ptr<llvm::TargetMachine>>
26+
getTargetMachine(mlir::LLVM::TargetAttrInterface attr);
27+
28+
/// Helper to obtain the DataLayout of the target specified by the properties of
29+
/// the TargetAttrInterface-implementing attribute.
30+
FailureOr<llvm::DataLayout> getDataLayout(mlir::LLVM::TargetAttrInterface attr);
31+
} // namespace detail
32+
} // namespace LLVM
33+
} // namespace mlir
34+
35+
#endif // MLIR_TARGET_LLVMIR_TRANSFORMS_TARGETUTILS_H

mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,43 @@ TargetFeaturesAttr TargetFeaturesAttr::featuresAt(Operation *op) {
374374
getAttributeName());
375375
}
376376

377+
FailureOr<Attribute> TargetFeaturesAttr::query(DataLayoutEntryKey key) {
378+
auto stringKey = dyn_cast<StringAttr>(key);
379+
if (!stringKey)
380+
return failure();
381+
382+
if (contains(stringKey))
383+
return UnitAttr::get(getContext());
384+
385+
if (contains((std::string("+") + stringKey.strref()).str()))
386+
return BoolAttr::get(getContext(), true);
387+
388+
if (contains((std::string("-") + stringKey.strref()).str()))
389+
return BoolAttr::get(getContext(), false);
390+
391+
return failure();
392+
}
393+
394+
//===----------------------------------------------------------------------===//
395+
// TargetAttr
396+
//===----------------------------------------------------------------------===//
397+
398+
FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
399+
if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
400+
if (stringAttrKey.getValue() == "triple")
401+
return getTriple();
402+
if (stringAttrKey.getValue() == "chip")
403+
return getChip();
404+
if (stringAttrKey.getValue() == "features" && getFeatures())
405+
return getFeatures();
406+
}
407+
return failure();
408+
}
409+
410+
//===----------------------------------------------------------------------===//
411+
// ModuleFlagAttr
412+
//===----------------------------------------------------------------------===//
413+
377414
LogicalResult
378415
ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
379416
LLVM::ModFlagBehavior flagBehavior, StringAttr key,
@@ -402,20 +439,3 @@ ModuleFlagAttr::verify(function_ref<InFlightDiagnostic()> emitError,
402439
"supported for unknown key '"
403440
<< key << "'";
404441
}
405-
406-
//===----------------------------------------------------------------------===//
407-
// LLVM_TargetAttr
408-
//===----------------------------------------------------------------------===//
409-
410-
FailureOr<::mlir::Attribute> TargetAttr::query(DataLayoutEntryKey key) {
411-
if (auto stringAttrKey = dyn_cast<StringAttr>(key)) {
412-
if (stringAttrKey.getValue() == "triple")
413-
return getTriple();
414-
if (stringAttrKey.getValue() == "chip")
415-
return getChip();
416-
if (stringAttrKey.getValue() == "features" && getFeatures())
417-
return getFeatures();
418-
}
419-
420-
return failure();
421-
}

mlir/lib/Target/LLVMIR/Transforms/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
add_mlir_dialect_library(MLIRTargetLLVMIRTransforms
22
TargetToDataLayout.cpp
3+
TargetToTargetFeatures.cpp
4+
TargetUtils.cpp
35

46
DEPENDS
57
MLIRTargetLLVMIRTransformsIncGen

mlir/lib/Target/LLVMIR/Transforms/TargetToDataLayout.cpp

Lines changed: 6 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,14 @@
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
8+
89
#include "mlir/Target/LLVMIR/Transforms/Passes.h"
10+
#include "mlir/Target/LLVMIR/Transforms/TargetUtils.h"
911

1012
#include "mlir/Dialect/DLTI/DLTI.h"
1113
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
1214
#include "mlir/Target/LLVMIR/Import.h"
1315

14-
#include "llvm/MC/TargetRegistry.h"
15-
#include "llvm/Support/Debug.h"
16-
#include "llvm/Support/TargetSelect.h"
17-
#include "llvm/Target/TargetMachine.h"
18-
19-
#define DEBUG_TYPE "mlir-llvm-target-to-data-layout"
20-
#define DBGS() (llvm::dbgs() << '[' << DEBUG_TYPE << "] ")
21-
#define LDBG(X) LLVM_DEBUG(DBGS() << X << "\n")
22-
2316
namespace mlir {
2417
namespace LLVM {
2518
#define GEN_PASS_DEF_LLVMTARGETTODATALAYOUT
@@ -29,35 +22,6 @@ namespace LLVM {
2922

3023
using namespace mlir;
3124

32-
static FailureOr<std::unique_ptr<llvm::TargetMachine>>
33-
getTargetMachine(LLVM::TargetAttrInterface attr) {
34-
StringRef triple = attr.getTriple();
35-
StringRef chipAKAcpu = attr.getChip();
36-
StringRef features = attr.getFeatures() ? attr.getFeatures().getValue() : "";
37-
38-
std::string error;
39-
const llvm::Target *target =
40-
llvm::TargetRegistry::lookupTarget(triple, error);
41-
if (!target || !error.empty()) {
42-
LDBG("Looking up target '" << triple << "' failed: " << error << "\n");
43-
return failure();
44-
}
45-
46-
return std::unique_ptr<llvm::TargetMachine>(target->createTargetMachine(
47-
llvm::Triple(triple), chipAKAcpu, features, {}, {}));
48-
}
49-
50-
static FailureOr<llvm::DataLayout>
51-
getDataLayout(LLVM::TargetAttrInterface attr) {
52-
FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
53-
getTargetMachine(attr);
54-
if (failed(targetMachine)) {
55-
LDBG("Failed to retrieve the target machine for data layout.\n");
56-
return failure();
57-
}
58-
return (targetMachine.value())->createDataLayout();
59-
}
60-
6125
struct TargetToDataLayoutPass
6226
: public LLVM::impl::LLVMTargetToDataLayoutBase<TargetToDataLayoutPass> {
6327
using LLVM::impl::LLVMTargetToDataLayoutBase<
@@ -66,15 +30,8 @@ struct TargetToDataLayoutPass
6630
void runOnOperation() override {
6731
Operation *op = getOperation();
6832

69-
if (initializeLLVMTargets) {
70-
static llvm::once_flag initializeBackendsOnce;
71-
llvm::call_once(initializeBackendsOnce, []() {
72-
// Ensure that the targets, that LLVM has been configured to support,
73-
// are loaded into the TargetRegistry.
74-
llvm::InitializeAllTargets();
75-
llvm::InitializeAllTargetMCs();
76-
});
77-
}
33+
if (initializeLLVMTargets)
34+
LLVM::detail::initializeBackendsOnce();
7835

7936
auto targetAttr = op->getAttrOfType<LLVM::TargetAttrInterface>(
8037
LLVM::LLVMDialect::getTargetAttrName());
@@ -85,7 +42,8 @@ struct TargetToDataLayoutPass
8542
return signalPassFailure();
8643
}
8744

88-
FailureOr<llvm::DataLayout> dataLayout = getDataLayout(targetAttr);
45+
FailureOr<llvm::DataLayout> dataLayout =
46+
LLVM::detail::getDataLayout(targetAttr);
8947
if (failed(dataLayout)) {
9048
op->emitError() << "failed to obtain llvm::DataLayout for " << targetAttr;
9149
return signalPassFailure();
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
//===- TargetToTargetFeatures.cpp - extract features from TargetMachine ---===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "mlir/Target/LLVMIR/Transforms/Passes.h"
10+
#include "mlir/Target/LLVMIR/Transforms/TargetUtils.h"
11+
12+
#include "mlir/Dialect/DLTI/DLTI.h"
13+
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
14+
#include "mlir/Target/LLVMIR/Import.h"
15+
16+
#include "llvm/MC/MCSubtargetInfo.h"
17+
18+
namespace mlir {
19+
namespace LLVM {
20+
#define GEN_PASS_DEF_LLVMTARGETTOTARGETFEATURES
21+
#include "mlir/Target/LLVMIR/Transforms/Passes.h.inc"
22+
} // namespace LLVM
23+
} // namespace mlir
24+
25+
using namespace mlir;
26+
27+
struct TargetToTargetFeaturesPass
28+
: public LLVM::impl::LLVMTargetToTargetFeaturesBase<
29+
TargetToTargetFeaturesPass> {
30+
using LLVM::impl::LLVMTargetToTargetFeaturesBase<
31+
TargetToTargetFeaturesPass>::LLVMTargetToTargetFeaturesBase;
32+
33+
void runOnOperation() override {
34+
Operation *op = getOperation();
35+
36+
if (initializeLLVMTargets)
37+
LLVM::detail::initializeBackendsOnce();
38+
39+
auto targetAttr = op->getAttrOfType<LLVM::TargetAttr>(
40+
LLVM::LLVMDialect::getTargetAttrName());
41+
if (!targetAttr) {
42+
op->emitError() << "no LLVM::TargetAttr attribute at key \""
43+
<< LLVM::LLVMDialect::getTargetAttrName() << "\"";
44+
return signalPassFailure();
45+
}
46+
47+
FailureOr<std::unique_ptr<llvm::TargetMachine>> targetMachine =
48+
LLVM::detail::getTargetMachine(targetAttr);
49+
if (failed(targetMachine)) {
50+
op->emitError() << "failed to obtain llvm::TargetMachine for "
51+
<< targetAttr;
52+
return signalPassFailure();
53+
}
54+
55+
llvm::MCSubtargetInfo const *subTargetInfo =
56+
(*targetMachine)->getMCSubtargetInfo();
57+
58+
const std::vector<llvm::SubtargetFeatureKV> enabledFeatures =
59+
subTargetInfo->getEnabledProcessorFeatures();
60+
61+
auto plussedFeatures = llvm::to_vector(
62+
llvm::map_range(enabledFeatures, [](llvm::SubtargetFeatureKV feature) {
63+
return std::string("+") + feature.Key;
64+
}));
65+
66+
auto plussedFeaturesRefs = llvm::to_vector(llvm::map_range(
67+
plussedFeatures, [](auto &it) { return StringRef(it.c_str()); }));
68+
69+
auto fullTargetFeaturesAttr =
70+
LLVM::TargetFeaturesAttr::get(&getContext(), plussedFeaturesRefs);
71+
72+
auto updatedTargetAttr =
73+
LLVM::TargetAttr::get(&getContext(), targetAttr.getTriple(),
74+
targetAttr.getChip(), fullTargetFeaturesAttr);
75+
76+
op->setAttr(LLVM::LLVMDialect::getTargetAttrName(), updatedTargetAttr);
77+
}
78+
};

0 commit comments

Comments
 (0)