Skip to content

Commit

Permalink
CPU feature logging
Browse files Browse the repository at this point in the history
Signed-off-by: Benoit Jacob <[email protected]>
  • Loading branch information
bjacob committed Oct 3, 2024
1 parent 718b4fd commit cacd566
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 109 deletions.
16 changes: 16 additions & 0 deletions compiler/plugins/target/LLVMCPU/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,21 @@ iree_compiler_cc_library(
],
)

iree_compiler_cc_library(
name = "ResolveCPUAndCPUFeatures",
srcs = [
"ResolveCPUAndCPUFeatures.cpp",
],
hdrs = [
"ResolveCPUAndCPUFeatures.h",
],
deps = [
"@llvm-project//llvm:Support",
"@llvm-project//llvm:Target",
"@llvm-project//llvm:TargetParser",
],
)

iree_compiler_cc_library(
name = "LLVMTargetOptions",
srcs = [
Expand All @@ -109,6 +124,7 @@ iree_compiler_cc_library(
"LLVMTargetOptions.h",
],
deps = [
":ResolveCPUAndCPUFeatures",
"//compiler/src/iree/compiler/Utils",
"@llvm-project//llvm:Analysis",
"@llvm-project//llvm:Core",
Expand Down
15 changes: 15 additions & 0 deletions compiler/plugins/target/LLVMCPU/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ iree_cc_library(
PUBLIC
)

iree_cc_library(
NAME
ResolveCPUAndCPUFeatures
HDRS
"ResolveCPUAndCPUFeatures.h"
SRCS
"ResolveCPUAndCPUFeatures.cpp"
DEPS
LLVMSupport
LLVMTarget
LLVMTargetParser
PUBLIC
)

iree_cc_library(
NAME
LLVMTargetOptions
Expand All @@ -97,6 +111,7 @@ iree_cc_library(
SRCS
"LLVMTargetOptions.cpp"
DEPS
::ResolveCPUAndCPUFeatures
LLVMAnalysis
LLVMCore
LLVMMC
Expand Down
125 changes: 28 additions & 97 deletions compiler/plugins/target/LLVMCPU/LLVMTargetOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@

#include "compiler/plugins/target/LLVMCPU/LLVMTargetOptions.h"

#include <mutex>

#include "compiler/plugins/target/LLVMCPU/ResolveCPUAndCPUFeatures.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/TargetTransformInfo.h"
Expand All @@ -19,88 +18,11 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TargetParser/RISCVTargetParser.h"
#include "llvm/TargetParser/SubtargetFeature.h"
#include "llvm/TargetParser/Triple.h"
#include "llvm/TargetParser/X86TargetParser.h"
#include "mlir/IR/Builders.h"

namespace mlir::iree_compiler::IREE::HAL {

namespace {

bool resolveCPUAndCPUFeatures(llvm::StringRef inCpu,
llvm::StringRef inCpuFeatures,
const llvm::Triple &triple, std::string &outCpu,
std::string &outCpuFeatures) {
// Resolve "host"
if (inCpu == "host" || inCpuFeatures == "host") {
// If either Cpu or CpuFeatures is "host", the other must be either also
// host or the default value.
bool isCpuHostOrDefault =
inCpu.empty() || inCpu == "host" || inCpu == "generic";
bool isCpuFeaturesHostOrDefault =
inCpuFeatures.empty() || inCpuFeatures == "host";
if (!(isCpuHostOrDefault && isCpuFeaturesHostOrDefault)) {
llvm::errs()
<< "error: If either cpu or CpuFeatures is `host`, the other must "
"be either also `host` or the default value\n";
return false;
}
outCpu = triple.isX86() ? llvm::sys::getHostCPUName().str() : "";
llvm::SubtargetFeatures features;
for (auto &feature : llvm::sys::getHostCPUFeatures()) {
features.AddFeature(feature.first(), feature.second);
}
outCpuFeatures = features.getString();
} else {
outCpu = inCpu;
outCpuFeatures = inCpuFeatures;
}

// Target-specific CPU feature tweaks that we need unconditionally.
if (triple.isAArch64()) {
llvm::SubtargetFeatures targetCpuFeatures(outCpuFeatures);
// x18 is platform-reserved per the Aarch64 procedure call specification.
targetCpuFeatures.AddFeature("reserve-x18", true);
outCpuFeatures = targetCpuFeatures.getString();
}

if (outCpu.empty() || inCpu == "host" || inCpu == "generic" ||
inCpu.starts_with("generic-")) {
return true;
}
// If CPU is non-host and non-generic then we need to populate the
// corresponding features.
llvm::SubtargetFeatures targetCpuFeatures(outCpuFeatures);
auto addCpuFeatures = [&](const auto &getFeaturesForCPU,
auto &cpuFeatureList) {
getFeaturesForCPU(outCpu, cpuFeatureList, false);
for (const auto &feature : cpuFeatureList) {
targetCpuFeatures.AddFeature(feature);
}
};
if (triple.isX86()) {
llvm::SmallVector<llvm::StringRef> cpuFeatureList;
addCpuFeatures(llvm::X86::getFeaturesForCPU, cpuFeatureList);
} else if (triple.isRISCV64()) {
llvm::SmallVector<std::string> cpuFeatureList;
addCpuFeatures(llvm::RISCV::getFeaturesForCPU, cpuFeatureList);
} else {
llvm::errs()
<< "error: Resolution of target CPU to target CPU features is not "
"implemented on "
"this target architecture. Pass explicit CPU features "
"instead of a CPU "
"on this architecture, or implement that.\n";
return false;
}
outCpuFeatures = targetCpuFeatures.getString();
return true;
}

} // namespace

LLVMTarget::LLVMTarget() {
// LLVM loop optimization options.
pipelineTuningOptions.LoopInterleaving = DEFAULT_LOOP_INTERLEAVING;
Expand All @@ -122,14 +44,14 @@ LLVMTarget::LLVMTarget() {
llvmTargetOptions.UniqueSectionNames = true;
}

std::optional<LLVMTarget> LLVMTarget::create(std::string_view triple,
std::string_view cpu,
std::string_view cpuFeatures,
bool requestLinkEmbedded) {
std::optional<LLVMTarget> LLVMTarget::create(
std::string_view triple, std::string_view cpu, std::string_view cpuFeatures,
std::string_view loggingUnspecifiedTargetCPU, bool requestLinkEmbedded) {
LLVMTarget target;
target.linkEmbedded = requestLinkEmbedded;

target.triple = triple;
target.triple = (triple.empty() || triple == "host")
? llvm::sys::getProcessTriple()
: triple;
llvm::Triple targetTriple(target.triple);
// Special casing if linkEmbedded.
if (targetTriple.isWasm()) {
Expand All @@ -142,10 +64,13 @@ std::optional<LLVMTarget> LLVMTarget::create(std::string_view triple,
targetTriple.setEnvironment(llvm::Triple::EnvironmentType::EABI);
targetTriple.setOS(llvm::Triple::OSType::UnknownOS);
targetTriple.setObjectFormat(llvm::Triple::ObjectFormatType::ELF);
target.triple = targetTriple.str();
}
if (!resolveCPUAndCPUFeatures(cpu, cpuFeatures, llvm::Triple(triple),
target.cpu, target.cpuFeatures)) {
target.triple = targetTriple.str();
target.cpu = cpu;
target.cpuFeatures = cpuFeatures;
if (!resolveCPUAndCPUFeatures(llvm::Triple(triple), target.cpu,
target.cpuFeatures,
loggingUnspecifiedTargetCPU)) {
// Something bad happened, and our target might not be what the user expects
// but we need to continue to avoid breaking existing users. Hopefully
// resolveCPUAndCPUFeatures logged a helpful error already.
Expand All @@ -155,10 +80,10 @@ std::optional<LLVMTarget> LLVMTarget::create(std::string_view triple,
}

std::optional<LLVMTarget> LLVMTarget::createForHost() {
auto target =
LLVMTarget::create(llvm::sys::getProcessTriple(), /*cpu=*/"host",
/*cpuFeatures=*/"host",
/*requestLinkEmbedded=*/true);
auto target = LLVMTarget::create(
llvm::sys::getProcessTriple(), /*cpu=*/"host",
/*cpuFeatures=*/"host", /*loggingUnspecifiedTargetCPU=*/"",
/*requestLinkEmbedded=*/true);
if (target)
target->populateDefaultsFromTargetMachine();
return target;
Expand Down Expand Up @@ -333,9 +258,8 @@ LLVMTarget::loadFromConfigAttr(Location loc, DictionaryAttr config,
"accompanied by 'target_triple'";
return {};
}
std::optional<LLVMTarget> maybeTarget =
LLVMTarget::create(*triple, cpu ? *cpu : "generic",
cpuFeatures ? *cpuFeatures : "", linkEmbedded);
std::optional<LLVMTarget> maybeTarget = LLVMTarget::create(
*triple, cpu.value_or(""), cpuFeatures.value_or(""), "", linkEmbedded);
if (!maybeTarget) {
return {};
}
Expand Down Expand Up @@ -588,6 +512,12 @@ void LLVMCPUTargetCLOptions::bindOptions(OptionsBinder &binder) {
llvm::cl::cat(category),
llvm::cl::desc("LLVM target machine CPU features; use 'host' for your "
"host native CPU."));
binder.opt<std::string>(
"iree-llvmcpu-logging-unspecified-target-cpu",
loggingUnspecifiedTargetCPU, llvm::cl::cat(category),
llvm::cl::desc(
"Warning behavior on unspecified target CPU. Accepted values: "
" (meaning no logging), \"warn\", \"fatal"));
binder.opt<bool>(
"iree-llvmcpu-link-embedded", linkEmbedded, llvm::cl::cat(category),
llvm::cl::desc("Links binaries into a platform-agnostic ELF to be "
Expand Down Expand Up @@ -670,8 +600,9 @@ LLVMTargetOptions LLVMCPUTargetCLOptions::getTargetOptions() {
targetTriple = llvm::sys::getProcessTriple();
}

std::optional<LLVMTarget> maybeTarget = LLVMTarget::create(
targetTriple, targetCPU, targetCPUFeatures, linkEmbedded);
std::optional<LLVMTarget> maybeTarget =
LLVMTarget::create(targetTriple, targetCPU, targetCPUFeatures,
loggingUnspecifiedTargetCPU, linkEmbedded);
if (maybeTarget) {
targetOptions.target = *maybeTarget;
} else {
Expand Down
26 changes: 14 additions & 12 deletions compiler/plugins/target/LLVMCPU/LLVMTargetOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,11 @@ struct LLVMTarget {
void storeToConfigAttrs(MLIRContext *context,
SmallVector<NamedAttribute> &config) const;

static std::optional<LLVMTarget> create(std::string_view triple,
std::string_view cpu,
std::string_view cpuFeatures,
bool requestLinkEmbedded);
static std::optional<LLVMTarget>
create(std::string_view triple, std::string_view cpu,
std::string_view cpuFeatures,
std::string_view loggingUnspecifiedTargetCPU,
bool requestLinkEmbedded);

static std::optional<LLVMTarget> createForHost();

Expand Down Expand Up @@ -170,25 +171,26 @@ createTargetMachine(const LLVMTarget &target);
// Parse into LLVMTargetOptions using getTargetOptions().
struct LLVMCPUTargetCLOptions {
// Target invariant flags.
std::string systemLinkerPath = "";
std::string embeddedLinkerPath = "";
std::string wasmLinkerPath = "";
std::string systemLinkerPath;
std::string embeddedLinkerPath;
std::string wasmLinkerPath;
bool keepLinkerArtifacts = false;

// Default device options.
std::string targetTriple = "";
std::string targetCPU = "generic";
std::string targetCPUFeatures = "";
std::string targetTriple;
std::string targetCPU;
std::string loggingUnspecifiedTargetCPU;
std::string targetCPUFeatures;
bool linkEmbedded = LLVMTarget::DEFAULT_LINK_EMBEDDED;
bool linkStatic = LLVMTarget::DEFAULT_LINK_STATIC;
std::string staticLibraryOutputPath = "";
std::string staticLibraryOutputPath;
bool debugSymbols = LLVMTarget::DEFAULT_DEBUG_SYMBOLS;
bool llvmLoopInterleaving = LLVMTarget::DEFAULT_LOOP_INTERLEAVING;
bool llvmLoopVectorization = LLVMTarget::DEFAULT_LOOP_VECTORIZATION;
bool llvmLoopUnrolling = LLVMTarget::DEFAULT_LOOP_UNROLLING;
bool llvmSLPVectorization = LLVMTarget::DEFAULT_SLP_VECTORIZATION;
SanitizerKind sanitizerKind = LLVMTarget::DEFAULT_SANITIZER_KIND;
std::string targetABI = "";
std::string targetABI;
llvm::FloatABI::ABIType targetFloatABI = LLVMTarget::DEFAULT_FLOAT_ABI;
std::string targetDataLayout = LLVMTarget::DEFAULT_DATA_LAYOUT;
unsigned targetVectorWidthInBytes = LLVMTarget::DEFAULT_VECTOR_WIDTH_IN_BYTES;
Expand Down
Loading

0 comments on commit cacd566

Please sign in to comment.