forked from OSchip/llvm-project
[RISCV] Add -mtune support
- The goal of this patch is improve option compatible with RISCV-V GCC, -mcpu support on GCC side will sent patch in next few days. - -mtune only affect the pipeline model and non-arch/extension related target feature, e.g. instruction fusion; in td file it called TuneFeatures, which is introduced by X86 back-end[1]. - -mtune accept all valid option for -mcpu and extra alias processor option, e.g. `generic`, `rocket` and `sifive-7-series`, the purpose is option compatible with RISCV-V GCC. - Processor alias for -mtune will resolve according the current target arch, rv32 or rv64, e.g. `rocket` will resolve to `rocket-rv32` or `rocket-rv64`. - Interaction between -mcpu and -mtune: * -mtune has higher priority than -mcpu for pipeline model and TuneFeatures. [1] https://reviews.llvm.org/D85165 Reviewed By: luismarques Differential Revision: https://reviews.llvm.org/D89025
This commit is contained in:
parent
19ae9b6e21
commit
cfa7094e49
|
@ -2768,7 +2768,7 @@ def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1O
|
|||
HelpText<"Provide information about a particular module file">;
|
||||
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
|
||||
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>,
|
||||
HelpText<"Only supported on X86. Otherwise accepted for compatibility with GCC.">;
|
||||
HelpText<"Only supported on X86 and RISC-V. Otherwise accepted for compatibility with GCC.">;
|
||||
def multi__module : Flag<["-"], "multi_module">;
|
||||
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
|
||||
def multiply__defined : Separate<["-"], "multiply_defined">;
|
||||
|
|
|
@ -178,6 +178,17 @@ void RISCV32TargetInfo::fillValidCPUList(
|
|||
llvm::RISCV::fillValidCPUArchList(Values, false);
|
||||
}
|
||||
|
||||
bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
|
||||
return llvm::RISCV::checkTuneCPUKind(
|
||||
llvm::RISCV::parseTuneCPUKind(Name, false),
|
||||
/*Is64Bit=*/false);
|
||||
}
|
||||
|
||||
void RISCV32TargetInfo::fillValidTuneCPUList(
|
||||
SmallVectorImpl<StringRef> &Values) const {
|
||||
llvm::RISCV::fillValidTuneCPUArchList(Values, false);
|
||||
}
|
||||
|
||||
bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
|
||||
return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
|
||||
/*Is64Bit=*/true);
|
||||
|
@ -187,3 +198,14 @@ void RISCV64TargetInfo::fillValidCPUList(
|
|||
SmallVectorImpl<StringRef> &Values) const {
|
||||
llvm::RISCV::fillValidCPUArchList(Values, true);
|
||||
}
|
||||
|
||||
bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
|
||||
return llvm::RISCV::checkTuneCPUKind(
|
||||
llvm::RISCV::parseTuneCPUKind(Name, true),
|
||||
/*Is64Bit=*/true);
|
||||
}
|
||||
|
||||
void RISCV64TargetInfo::fillValidTuneCPUList(
|
||||
SmallVectorImpl<StringRef> &Values) const {
|
||||
llvm::RISCV::fillValidTuneCPUArchList(Values, true);
|
||||
}
|
||||
|
|
|
@ -106,6 +106,8 @@ public:
|
|||
|
||||
bool isValidCPUName(StringRef Name) const override;
|
||||
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
|
||||
bool isValidTuneCPUName(StringRef Name) const override;
|
||||
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
|
||||
|
||||
void setMaxAtomicWidth() override {
|
||||
MaxAtomicPromoteWidth = 128;
|
||||
|
@ -133,6 +135,8 @@ public:
|
|||
|
||||
bool isValidCPUName(StringRef Name) const override;
|
||||
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
|
||||
bool isValidTuneCPUName(StringRef Name) const override;
|
||||
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
|
||||
|
||||
void setMaxAtomicWidth() override {
|
||||
MaxAtomicPromoteWidth = 128;
|
||||
|
|
|
@ -2012,6 +2012,20 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
|
|||
CmdArgs.push_back(ABIName.data());
|
||||
|
||||
SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
|
||||
|
||||
std::string TuneCPU;
|
||||
|
||||
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
|
||||
StringRef Name = A->getValue();
|
||||
|
||||
Name = llvm::RISCV::resolveTuneCPUAlias(Name, Triple.isArch64Bit());
|
||||
TuneCPU = std::string(Name);
|
||||
}
|
||||
|
||||
if (!TuneCPU.empty()) {
|
||||
CmdArgs.push_back("-tune-cpu");
|
||||
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
|
||||
}
|
||||
}
|
||||
|
||||
void Clang::AddSparcTargetArgs(const ArgList &Args,
|
||||
|
|
|
@ -14,6 +14,37 @@
|
|||
// MCPU-SIFIVE7-64: "-nostdsysteminc" "-target-cpu" "sifive-7-rv64"
|
||||
// MCPU-SIFIVE7-64: "-target-feature" "+64bit"
|
||||
|
||||
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=rocket-rv32 | FileCheck -check-prefix=MTUNE-ROCKET32 %s
|
||||
// MTUNE-ROCKET32: "-tune-cpu" "rocket-rv32"
|
||||
|
||||
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=rocket-rv64 | FileCheck -check-prefix=MTUNE-ROCKET64 %s
|
||||
// MTUNE-ROCKET64: "-tune-cpu" "rocket-rv64"
|
||||
|
||||
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=sifive-7-rv32 | FileCheck -check-prefix=MTUNE-SIFIVE7-32 %s
|
||||
// MTUNE-SIFIVE7-32: "-tune-cpu" "sifive-7-rv32"
|
||||
|
||||
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=sifive-7-rv64 | FileCheck -check-prefix=MTUNE-SIFIVE7-64 %s
|
||||
// MTUNE-SIFIVE7-64: "-tune-cpu" "sifive-7-rv64"
|
||||
|
||||
// Check mtune alias CPU has resolved to the right CPU according XLEN.
|
||||
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=generic | FileCheck -check-prefix=MTUNE-GENERIC-32 %s
|
||||
// MTUNE-GENERIC-32: "-tune-cpu" "generic-rv32"
|
||||
|
||||
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=generic | FileCheck -check-prefix=MTUNE-GENERIC-64 %s
|
||||
// MTUNE-GENERIC-64: "-tune-cpu" "generic-rv64"
|
||||
|
||||
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=rocket | FileCheck -check-prefix=MTUNE-ROCKET-32 %s
|
||||
// MTUNE-ROCKET-32: "-tune-cpu" "rocket-rv32"
|
||||
|
||||
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=rocket | FileCheck -check-prefix=MTUNE-ROCKET-64 %s
|
||||
// MTUNE-ROCKET-64: "-tune-cpu" "rocket-rv64"
|
||||
|
||||
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=sifive-7-series | FileCheck -check-prefix=MTUNE-SIFIVE7-SERIES-32 %s
|
||||
// MTUNE-SIFIVE7-SERIES-32: "-tune-cpu" "sifive-7-rv32"
|
||||
|
||||
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=sifive-7-series | FileCheck -check-prefix=MTUNE-SIFIVE7-SERIES-64 %s
|
||||
// MTUNE-SIFIVE7-SERIES-64: "-tune-cpu" "sifive-7-rv64"
|
||||
|
||||
// mcpu with default march
|
||||
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mcpu=sifive-u54 | FileCheck -check-prefix=MCPU-SIFIVE-U54 %s
|
||||
// MCPU-SIFIVE-U54: "-nostdsysteminc" "-target-cpu" "sifive-u54"
|
||||
|
@ -47,6 +78,20 @@
|
|||
// MCPU-MARCH: "-nostdsysteminc" "-target-cpu" "sifive-e31" "-target-feature" "+m" "-target-feature" "+c"
|
||||
// MCPU-MARCH: "-target-abi" "ilp32"
|
||||
|
||||
// Check interaction between mcpu and mtune, mtune won't affect arch related
|
||||
// target feature, but mcpu will.
|
||||
//
|
||||
// In this case, sifive-e31 is rv32imac, sifive-e76 is rv32imafc, so M-extension
|
||||
// should not enabled.
|
||||
//
|
||||
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=sifive-e31 -mtune=sifive-e76 | FileCheck -check-prefix=MTUNE-E31-MCPU-E76 %s
|
||||
// MTUNE-E31-MCPU-E76: "-target-cpu" "sifive-e31"
|
||||
// MTUNE-E31-MCPU-E76-NOT: "-target-feature" "+f"
|
||||
// MTUNE-E31-MCPU-E76-SAME: "-target-feature" "+m"
|
||||
// MTUNE-E31-MCPU-E76-SAME: "-target-feature" "+a"
|
||||
// MTUNE-E31-MCPU-E76-SAME: "-target-feature" "+c"
|
||||
// MTUNE-E31-MCPU-E76-SAME: "-tune-cpu" "sifive-e76"
|
||||
|
||||
// Check failed cases
|
||||
|
||||
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=generic-rv321 | FileCheck -check-prefix=FAIL-MCPU-NAME %s
|
||||
|
|
|
@ -197,3 +197,11 @@
|
|||
// RUN: not %clang_cc1 -triple riscv64 -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix RISCV64
|
||||
// RISCV64: error: unknown target CPU 'not-a-cpu'
|
||||
// RISCV64: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-7-rv64, sifive-u54, sifive-u74
|
||||
|
||||
// RUN: not %clang_cc1 -triple riscv32 -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-RISCV32
|
||||
// TUNE-RISCV32: error: unknown target CPU 'not-a-cpu'
|
||||
// TUNE-RISCV32: note: valid target CPU values are: generic-rv32, rocket-rv32, sifive-7-rv32, sifive-e31, sifive-e76, generic, rocket, sifive-7-series
|
||||
|
||||
// RUN: not %clang_cc1 -triple riscv64 -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-RISCV64
|
||||
// TUNE-RISCV64: error: unknown target CPU 'not-a-cpu'
|
||||
// TUNE-RISCV64: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-7-rv64, sifive-u54, sifive-u74, generic, rocket, sifive-7-series
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
#ifndef PROC_ALIAS
|
||||
#define PROC_ALIAS(NAME, RV32, RV64)
|
||||
#endif
|
||||
|
||||
PROC_ALIAS({"generic"}, {"generic-rv32"}, {"generic-rv64"})
|
||||
PROC_ALIAS({"rocket"}, {"rocket-rv32"}, {"rocket-rv64"})
|
||||
PROC_ALIAS({"sifive-7-series"}, {"sifive-7-rv32"}, {"sifive-7-rv64"})
|
||||
|
||||
#undef PROC_ALIAS
|
||||
|
||||
#ifndef PROC
|
||||
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH)
|
||||
#endif
|
||||
|
|
|
@ -160,10 +160,14 @@ enum FeatureKind : unsigned {
|
|||
};
|
||||
|
||||
bool checkCPUKind(CPUKind Kind, bool IsRV64);
|
||||
bool checkTuneCPUKind(CPUKind Kind, bool IsRV64);
|
||||
CPUKind parseCPUKind(StringRef CPU);
|
||||
CPUKind parseTuneCPUKind(StringRef CPU, bool IsRV64);
|
||||
StringRef getMArchFromMcpu(StringRef CPU);
|
||||
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
|
||||
void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
|
||||
bool getCPUFeaturesExceptStdExt(CPUKind Kind, std::vector<StringRef> &Features);
|
||||
StringRef resolveTuneCPUAlias(StringRef TuneCPU, bool IsRV64);
|
||||
|
||||
} // namespace RISCV
|
||||
|
||||
|
|
|
@ -253,6 +253,12 @@ bool checkCPUKind(CPUKind Kind, bool IsRV64) {
|
|||
return RISCVCPUInfo[static_cast<unsigned>(Kind)].is64Bit() == IsRV64;
|
||||
}
|
||||
|
||||
bool checkTuneCPUKind(CPUKind Kind, bool IsRV64) {
|
||||
if (Kind == CK_INVALID)
|
||||
return false;
|
||||
return RISCVCPUInfo[static_cast<unsigned>(Kind)].is64Bit() == IsRV64;
|
||||
}
|
||||
|
||||
CPUKind parseCPUKind(StringRef CPU) {
|
||||
return llvm::StringSwitch<CPUKind>(CPU)
|
||||
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) .Case(NAME, CK_##ENUM)
|
||||
|
@ -260,6 +266,22 @@ CPUKind parseCPUKind(StringRef CPU) {
|
|||
.Default(CK_INVALID);
|
||||
}
|
||||
|
||||
StringRef resolveTuneCPUAlias(StringRef TuneCPU, bool IsRV64) {
|
||||
return llvm::StringSwitch<StringRef>(TuneCPU)
|
||||
#define PROC_ALIAS(NAME, RV32, RV64) .Case(NAME, IsRV64 ? StringRef(RV64) : StringRef(RV32))
|
||||
#include "llvm/Support/RISCVTargetParser.def"
|
||||
.Default(TuneCPU);
|
||||
}
|
||||
|
||||
CPUKind parseTuneCPUKind(StringRef TuneCPU, bool IsRV64) {
|
||||
TuneCPU = resolveTuneCPUAlias(TuneCPU, IsRV64);
|
||||
|
||||
return llvm::StringSwitch<CPUKind>(TuneCPU)
|
||||
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) .Case(NAME, CK_##ENUM)
|
||||
#include "llvm/Support/RISCVTargetParser.def"
|
||||
.Default(CK_INVALID);
|
||||
}
|
||||
|
||||
StringRef getMArchFromMcpu(StringRef CPU) {
|
||||
CPUKind Kind = parseCPUKind(CPU);
|
||||
return RISCVCPUInfo[static_cast<unsigned>(Kind)].DefaultMarch;
|
||||
|
@ -272,6 +294,15 @@ void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
|
|||
}
|
||||
}
|
||||
|
||||
void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
|
||||
for (const auto &C : RISCVCPUInfo) {
|
||||
if (C.Kind != CK_INVALID && IsRV64 == C.is64Bit())
|
||||
Values.emplace_back(C.Name);
|
||||
}
|
||||
#define PROC_ALIAS(NAME, RV32, RV64) Values.emplace_back(StringRef(NAME));
|
||||
#include "llvm/Support/RISCVTargetParser.def"
|
||||
}
|
||||
|
||||
// Get all features except standard extension feature
|
||||
bool getCPUFeaturesExceptStdExt(CPUKind Kind,
|
||||
std::vector<StringRef> &Features) {
|
||||
|
|
|
@ -198,7 +198,9 @@ void RISCVAsmPrinter::emitAttributes() {
|
|||
StringRef CPU = TM.getTargetCPU();
|
||||
StringRef FS = TM.getTargetFeatureString();
|
||||
const RISCVTargetMachine &RTM = static_cast<const RISCVTargetMachine &>(TM);
|
||||
const RISCVSubtarget STI(TT, CPU, FS, /*ABIName=*/"", RTM);
|
||||
/* TuneCPU doesn't impact emission of ELF attributes, ELF attributes only
|
||||
care about arch related features, so we can set TuneCPU as CPU. */
|
||||
const RISCVSubtarget STI(TT, CPU, /*TuneCPU=*/CPU, FS, /*ABIName=*/"", RTM);
|
||||
|
||||
RTS.emitTargetAttributes(STI);
|
||||
}
|
||||
|
|
|
@ -30,13 +30,16 @@ using namespace llvm;
|
|||
void RISCVSubtarget::anchor() {}
|
||||
|
||||
RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(
|
||||
const Triple &TT, StringRef CPU, StringRef FS, StringRef ABIName) {
|
||||
const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, StringRef ABIName) {
|
||||
// Determine default and user-specified characteristics
|
||||
bool Is64Bit = TT.isArch64Bit();
|
||||
std::string CPUName = std::string(CPU);
|
||||
std::string TuneCPUName = std::string(TuneCPU);
|
||||
if (CPUName.empty())
|
||||
CPUName = Is64Bit ? "generic-rv64" : "generic-rv32";
|
||||
ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS);
|
||||
if (TuneCPUName.empty())
|
||||
TuneCPUName = CPUName;
|
||||
ParseSubtargetFeatures(CPUName, TuneCPUName, FS);
|
||||
if (Is64Bit) {
|
||||
XLenVT = MVT::i64;
|
||||
XLen = 64;
|
||||
|
@ -47,11 +50,12 @@ RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(
|
|||
return *this;
|
||||
}
|
||||
|
||||
RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
||||
RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU,
|
||||
StringRef TuneCPU, StringRef FS,
|
||||
StringRef ABIName, const TargetMachine &TM)
|
||||
: RISCVGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
|
||||
: RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS),
|
||||
UserReservedRegister(RISCV::NUM_TARGET_REGS),
|
||||
FrameLowering(initializeSubtargetDependencies(TT, CPU, FS, ABIName)),
|
||||
FrameLowering(initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
|
||||
InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {
|
||||
CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering()));
|
||||
Legalizer.reset(new RISCVLegalizerInfo(*this));
|
||||
|
|
|
@ -71,13 +71,15 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
|
|||
/// Initializes using the passed in CPU and feature strings so that we can
|
||||
/// use initializer lists for subtarget initialization.
|
||||
RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
|
||||
StringRef CPU, StringRef FS,
|
||||
StringRef CPU,
|
||||
StringRef TuneCPU,
|
||||
StringRef FS,
|
||||
StringRef ABIName);
|
||||
|
||||
public:
|
||||
// Initializes the data members to match that of the specified triple.
|
||||
RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
|
||||
StringRef ABIName, const TargetMachine &TM);
|
||||
RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
|
||||
StringRef FS, StringRef ABIName, const TargetMachine &TM);
|
||||
|
||||
// Parses features string setting specified subtarget options. The
|
||||
// definition of this function is auto-generated by tblgen.
|
||||
|
|
|
@ -75,13 +75,16 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
|
|||
const RISCVSubtarget *
|
||||
RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
|
||||
Attribute CPUAttr = F.getFnAttribute("target-cpu");
|
||||
Attribute TuneAttr = F.getFnAttribute("tune-cpu");
|
||||
Attribute FSAttr = F.getFnAttribute("target-features");
|
||||
|
||||
std::string CPU =
|
||||
CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
|
||||
std::string TuneCPU =
|
||||
TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
|
||||
std::string FS =
|
||||
FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
|
||||
std::string Key = CPU + FS;
|
||||
std::string Key = CPU + TuneCPU + FS;
|
||||
auto &I = SubtargetMap[Key];
|
||||
if (!I) {
|
||||
// This needs to be done before we create a new subtarget since any
|
||||
|
@ -98,7 +101,7 @@ RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
|
|||
}
|
||||
ABIName = ModuleTargetABI->getString();
|
||||
}
|
||||
I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, FS, ABIName, *this);
|
||||
I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS, ABIName, *this);
|
||||
}
|
||||
return I.get();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue