mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-11-10 12:38:28 +00:00
Add support to the driver for CLI flags that select which CPU to target, which CPU to tune performance for, and which CPU features to enable. - `--target-cpu` selects the architecture of CPU to target, similar to `-march` on x86. This combines `-march` with `armv*` strings and `-mcpu` on Arm for specific CPU names. Similarly for RISC-V (if/when we support and test it), etc. Notably, `--target-cpu=native` targets the current native CPU. - `--target-cpu-tune` maps to `-mtune`. This is expected to be rarely if ever desirable, and I'm open to removing it, but if folks are relying on this for performance I didn't want to hide the option. - `--target-cpu-features` allows a "standard" (for LLVM) comma-separated list of LLVM subtarget features, including `+feature` and `-feature` syntax. These flags, when provided, establish the default baseline for CPU targeting and control how on-demand runtimes are built. They can be changed or overridden by additional Clang flags when using `--clang-arg`. A critical part of this is building runtimes on demand using these features. For that, we need to do some amount of canonicalization (re-using Clang's canonicalization to ensure consistent behavior), and extend the runtimes cache features to recognize these customizations. Note that only the top-level Carbon flags impact runtimes, any particular Clang arguments are only used by the specific compiles that receive those arguments. There is some nascent RISC-V support here, but it is incomplete and only minimally tested. Still, it seemed better to record the parts we could test than remove them. Assisted-by: Antigravity with Gemini
157 lines
5.0 KiB
C++
157 lines
5.0 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "toolchain/driver/codegen_options.h"
|
|
|
|
#include <string>
|
|
|
|
#include "llvm/Support/Error.h"
|
|
#include "llvm/Support/FormatVariadic.h"
|
|
#include "llvm/TargetParser/AArch64TargetParser.h"
|
|
#include "llvm/TargetParser/RISCVISAInfo.h"
|
|
#include "llvm/TargetParser/RISCVTargetParser.h"
|
|
#include "llvm/TargetParser/Triple.h"
|
|
|
|
namespace Carbon {
|
|
|
|
auto CodegenOptions::Build(CommandLine::CommandBuilder& b) -> void {
|
|
b.AddStringOption(
|
|
{
|
|
.name = "target",
|
|
.help = R"""(
|
|
Select a target platform. Uses the LLVM target syntax. Also known as a "triple"
|
|
for historical reasons.
|
|
|
|
This corresponds to the `target` flag to Clang and accepts the same strings
|
|
documented there:
|
|
https://clang.llvm.org/docs/CrossCompilation.html#target-triple
|
|
)""",
|
|
},
|
|
[&](auto& arg_b) {
|
|
arg_b.Default(host);
|
|
arg_b.Set(&target);
|
|
});
|
|
|
|
b.AddStringOption(
|
|
{
|
|
.name = "target-cpu",
|
|
.value_name = "CPU",
|
|
.help = R"""(
|
|
Select a target CPU or architecture level.
|
|
|
|
Accepts CPU names (such as `znver4`, `apple-m1`, `spacemit-x60`, or `native`) as
|
|
well as architecture strings or profiles (such as `x86-64-v3`, `armv9-a`,
|
|
`rv64gc`, or `rva22u64`). This corresponds to Clang's `-march` and `-mcpu`
|
|
flags, selecting the appropriate underlying flag for the target architecture.
|
|
)""",
|
|
},
|
|
[&](auto& arg_b) { arg_b.Set(&target_cpu); });
|
|
|
|
b.AddStringOption(
|
|
{
|
|
.name = "target-cpu-tune",
|
|
.value_name = "CPU",
|
|
.help = R"""(
|
|
Select a target CPU to tune code generation for without enabling new
|
|
instruction set extensions.
|
|
|
|
Accepts CPU names (such as `znver4`, `apple-m1`, `spacemit-x60`, `generic`, or
|
|
`native`). This corresponds to Clang's `-mtune` flag.
|
|
)""",
|
|
},
|
|
[&](auto& arg_b) { arg_b.Set(&target_cpu_tune); });
|
|
|
|
b.AddStringOption(
|
|
{
|
|
.name = "target-cpu-features",
|
|
.value_name = "FEATURES",
|
|
.help = R"""(
|
|
Select target CPU features to enable or disable.
|
|
|
|
Accepts a comma-separated list of LLVM target feature names, optionally prefixed
|
|
with `+` to enable or `-` to disable (such as `+avx2,-fma` or `sve,crc`). Bare
|
|
feature names without a prefix are enabled.
|
|
)""",
|
|
},
|
|
[&](auto& arg_b) { arg_b.Set(&target_cpu_features); });
|
|
}
|
|
|
|
static auto AppendTargetCpuClangArgs(llvm::StringRef target,
|
|
llvm::StringRef target_cpu,
|
|
llvm::SmallVectorImpl<std::string>& args)
|
|
-> void {
|
|
if (target_cpu.empty()) {
|
|
return;
|
|
}
|
|
|
|
llvm::Triple triple(target);
|
|
if (triple.isX86()) {
|
|
// On x86, Clang uses `-march=` for both microarchitecture levels (such as
|
|
// `x86-64-v3`) and specific CPUs (such as `znver4` or `native`), and does
|
|
// not support `-mcpu=`.
|
|
args.push_back(llvm::formatv("-march={0}", target_cpu).str());
|
|
return;
|
|
}
|
|
|
|
if (triple.isAArch64()) {
|
|
auto [base, _] = target_cpu.split('+');
|
|
bool is_arch =
|
|
llvm::AArch64::parseArch(base) != nullptr || base.starts_with("armv");
|
|
args.push_back(
|
|
llvm::formatv(is_arch ? "-march={0}" : "-mcpu={0}", target_cpu).str());
|
|
return;
|
|
}
|
|
|
|
if (triple.isRISCV()) {
|
|
auto isa_info = llvm::RISCVISAInfo::parseArchString(
|
|
target_cpu, /*EnableExperimentalExtension=*/true);
|
|
bool is_arch = static_cast<bool>(isa_info);
|
|
if (!isa_info) {
|
|
llvm::consumeError(isa_info.takeError());
|
|
is_arch =
|
|
!llvm::RISCV::parseCPU(target_cpu, triple.isRISCV64()) &&
|
|
(target_cpu.starts_with("rv32") || target_cpu.starts_with("rv64") ||
|
|
target_cpu.starts_with("rva") || target_cpu.starts_with("rvb") ||
|
|
target_cpu.starts_with("rvi") || target_cpu.starts_with("rvm"));
|
|
}
|
|
args.push_back(
|
|
llvm::formatv(is_arch ? "-march={0}" : "-mcpu={0}", target_cpu).str());
|
|
return;
|
|
}
|
|
|
|
args.push_back(llvm::formatv("-mcpu={0}", target_cpu).str());
|
|
}
|
|
|
|
auto CodegenOptions::AppendClangArgs(
|
|
llvm::SmallVectorImpl<std::string>& args) const -> void {
|
|
AppendTargetCpuClangArgs(target, target_cpu, args);
|
|
if (!target_cpu_tune.empty()) {
|
|
args.push_back(llvm::formatv("-mtune={0}", target_cpu_tune).str());
|
|
}
|
|
if (!target_cpu_features.empty()) {
|
|
llvm::SmallVector<llvm::StringRef> features;
|
|
target_cpu_features.split(features, ',', /*MaxSplit=*/-1,
|
|
/*KeepEmpty=*/false);
|
|
for (llvm::StringRef feature : features) {
|
|
args.push_back("-Xclang");
|
|
args.push_back("-target-feature");
|
|
args.push_back("-Xclang");
|
|
if (feature.size() > 1 &&
|
|
(feature.starts_with('+') || feature.starts_with('-'))) {
|
|
args.push_back(feature.str());
|
|
} else {
|
|
args.push_back(llvm::formatv("+{0}", feature).str());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
auto CodegenOptions::GetClangArgs() const -> llvm::SmallVector<std::string> {
|
|
llvm::SmallVector<std::string> args;
|
|
AppendClangArgs(args);
|
|
return args;
|
|
}
|
|
|
|
} // namespace Carbon
|