Skip to content

Commit cfa7094

Browse files
committed
[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
1 parent 19ae9b6 commit cfa7094

File tree

13 files changed

+161
-12
lines changed

13 files changed

+161
-12
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2768,7 +2768,7 @@ def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1O
27682768
HelpText<"Provide information about a particular module file">;
27692769
def mthumb : Flag<["-"], "mthumb">, Group<m_Group>;
27702770
def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>,
2771-
HelpText<"Only supported on X86. Otherwise accepted for compatibility with GCC.">;
2771+
HelpText<"Only supported on X86 and RISC-V. Otherwise accepted for compatibility with GCC.">;
27722772
def multi__module : Flag<["-"], "multi_module">;
27732773
def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">;
27742774
def multiply__defined : Separate<["-"], "multiply_defined">;

clang/lib/Basic/Targets/RISCV.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,17 @@ void RISCV32TargetInfo::fillValidCPUList(
178178
llvm::RISCV::fillValidCPUArchList(Values, false);
179179
}
180180

181+
bool RISCV32TargetInfo::isValidTuneCPUName(StringRef Name) const {
182+
return llvm::RISCV::checkTuneCPUKind(
183+
llvm::RISCV::parseTuneCPUKind(Name, false),
184+
/*Is64Bit=*/false);
185+
}
186+
187+
void RISCV32TargetInfo::fillValidTuneCPUList(
188+
SmallVectorImpl<StringRef> &Values) const {
189+
llvm::RISCV::fillValidTuneCPUArchList(Values, false);
190+
}
191+
181192
bool RISCV64TargetInfo::isValidCPUName(StringRef Name) const {
182193
return llvm::RISCV::checkCPUKind(llvm::RISCV::parseCPUKind(Name),
183194
/*Is64Bit=*/true);
@@ -187,3 +198,14 @@ void RISCV64TargetInfo::fillValidCPUList(
187198
SmallVectorImpl<StringRef> &Values) const {
188199
llvm::RISCV::fillValidCPUArchList(Values, true);
189200
}
201+
202+
bool RISCV64TargetInfo::isValidTuneCPUName(StringRef Name) const {
203+
return llvm::RISCV::checkTuneCPUKind(
204+
llvm::RISCV::parseTuneCPUKind(Name, true),
205+
/*Is64Bit=*/true);
206+
}
207+
208+
void RISCV64TargetInfo::fillValidTuneCPUList(
209+
SmallVectorImpl<StringRef> &Values) const {
210+
llvm::RISCV::fillValidTuneCPUArchList(Values, true);
211+
}

clang/lib/Basic/Targets/RISCV.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo {
106106

107107
bool isValidCPUName(StringRef Name) const override;
108108
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
109+
bool isValidTuneCPUName(StringRef Name) const override;
110+
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
109111

110112
void setMaxAtomicWidth() override {
111113
MaxAtomicPromoteWidth = 128;
@@ -133,6 +135,8 @@ class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo {
133135

134136
bool isValidCPUName(StringRef Name) const override;
135137
void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
138+
bool isValidTuneCPUName(StringRef Name) const override;
139+
void fillValidTuneCPUList(SmallVectorImpl<StringRef> &Values) const override;
136140

137141
void setMaxAtomicWidth() override {
138142
MaxAtomicPromoteWidth = 128;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,6 +2012,20 @@ void Clang::AddRISCVTargetArgs(const ArgList &Args,
20122012
CmdArgs.push_back(ABIName.data());
20132013

20142014
SetRISCVSmallDataLimit(getToolChain(), Args, CmdArgs);
2015+
2016+
std::string TuneCPU;
2017+
2018+
if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mtune_EQ)) {
2019+
StringRef Name = A->getValue();
2020+
2021+
Name = llvm::RISCV::resolveTuneCPUAlias(Name, Triple.isArch64Bit());
2022+
TuneCPU = std::string(Name);
2023+
}
2024+
2025+
if (!TuneCPU.empty()) {
2026+
CmdArgs.push_back("-tune-cpu");
2027+
CmdArgs.push_back(Args.MakeArgString(TuneCPU));
2028+
}
20152029
}
20162030

20172031
void Clang::AddSparcTargetArgs(const ArgList &Args,

clang/test/Driver/riscv-cpus.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,37 @@
1414
// MCPU-SIFIVE7-64: "-nostdsysteminc" "-target-cpu" "sifive-7-rv64"
1515
// MCPU-SIFIVE7-64: "-target-feature" "+64bit"
1616

17+
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=rocket-rv32 | FileCheck -check-prefix=MTUNE-ROCKET32 %s
18+
// MTUNE-ROCKET32: "-tune-cpu" "rocket-rv32"
19+
20+
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=rocket-rv64 | FileCheck -check-prefix=MTUNE-ROCKET64 %s
21+
// MTUNE-ROCKET64: "-tune-cpu" "rocket-rv64"
22+
23+
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=sifive-7-rv32 | FileCheck -check-prefix=MTUNE-SIFIVE7-32 %s
24+
// MTUNE-SIFIVE7-32: "-tune-cpu" "sifive-7-rv32"
25+
26+
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=sifive-7-rv64 | FileCheck -check-prefix=MTUNE-SIFIVE7-64 %s
27+
// MTUNE-SIFIVE7-64: "-tune-cpu" "sifive-7-rv64"
28+
29+
// Check mtune alias CPU has resolved to the right CPU according XLEN.
30+
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=generic | FileCheck -check-prefix=MTUNE-GENERIC-32 %s
31+
// MTUNE-GENERIC-32: "-tune-cpu" "generic-rv32"
32+
33+
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=generic | FileCheck -check-prefix=MTUNE-GENERIC-64 %s
34+
// MTUNE-GENERIC-64: "-tune-cpu" "generic-rv64"
35+
36+
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=rocket | FileCheck -check-prefix=MTUNE-ROCKET-32 %s
37+
// MTUNE-ROCKET-32: "-tune-cpu" "rocket-rv32"
38+
39+
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=rocket | FileCheck -check-prefix=MTUNE-ROCKET-64 %s
40+
// MTUNE-ROCKET-64: "-tune-cpu" "rocket-rv64"
41+
42+
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mtune=sifive-7-series | FileCheck -check-prefix=MTUNE-SIFIVE7-SERIES-32 %s
43+
// MTUNE-SIFIVE7-SERIES-32: "-tune-cpu" "sifive-7-rv32"
44+
45+
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mtune=sifive-7-series | FileCheck -check-prefix=MTUNE-SIFIVE7-SERIES-64 %s
46+
// MTUNE-SIFIVE7-SERIES-64: "-tune-cpu" "sifive-7-rv64"
47+
1748
// mcpu with default march
1849
// RUN: %clang -target riscv64 -### -c %s 2>&1 -mcpu=sifive-u54 | FileCheck -check-prefix=MCPU-SIFIVE-U54 %s
1950
// MCPU-SIFIVE-U54: "-nostdsysteminc" "-target-cpu" "sifive-u54"
@@ -47,6 +78,20 @@
4778
// MCPU-MARCH: "-nostdsysteminc" "-target-cpu" "sifive-e31" "-target-feature" "+m" "-target-feature" "+c"
4879
// MCPU-MARCH: "-target-abi" "ilp32"
4980

81+
// Check interaction between mcpu and mtune, mtune won't affect arch related
82+
// target feature, but mcpu will.
83+
//
84+
// In this case, sifive-e31 is rv32imac, sifive-e76 is rv32imafc, so M-extension
85+
// should not enabled.
86+
//
87+
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=sifive-e31 -mtune=sifive-e76 | FileCheck -check-prefix=MTUNE-E31-MCPU-E76 %s
88+
// MTUNE-E31-MCPU-E76: "-target-cpu" "sifive-e31"
89+
// MTUNE-E31-MCPU-E76-NOT: "-target-feature" "+f"
90+
// MTUNE-E31-MCPU-E76-SAME: "-target-feature" "+m"
91+
// MTUNE-E31-MCPU-E76-SAME: "-target-feature" "+a"
92+
// MTUNE-E31-MCPU-E76-SAME: "-target-feature" "+c"
93+
// MTUNE-E31-MCPU-E76-SAME: "-tune-cpu" "sifive-e76"
94+
5095
// Check failed cases
5196

5297
// RUN: %clang -target riscv32 -### -c %s 2>&1 -mcpu=generic-rv321 | FileCheck -check-prefix=FAIL-MCPU-NAME %s

clang/test/Misc/target-invalid-cpu-note.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,11 @@
197197
// RUN: not %clang_cc1 -triple riscv64 -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix RISCV64
198198
// RISCV64: error: unknown target CPU 'not-a-cpu'
199199
// RISCV64: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-7-rv64, sifive-u54, sifive-u74
200+
201+
// RUN: not %clang_cc1 -triple riscv32 -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-RISCV32
202+
// TUNE-RISCV32: error: unknown target CPU 'not-a-cpu'
203+
// TUNE-RISCV32: note: valid target CPU values are: generic-rv32, rocket-rv32, sifive-7-rv32, sifive-e31, sifive-e76, generic, rocket, sifive-7-series
204+
205+
// RUN: not %clang_cc1 -triple riscv64 -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE-RISCV64
206+
// TUNE-RISCV64: error: unknown target CPU 'not-a-cpu'
207+
// TUNE-RISCV64: note: valid target CPU values are: generic-rv64, rocket-rv64, sifive-7-rv64, sifive-u54, sifive-u74, generic, rocket, sifive-7-series

llvm/include/llvm/Support/RISCVTargetParser.def

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
#ifndef PROC_ALIAS
2+
#define PROC_ALIAS(NAME, RV32, RV64)
3+
#endif
4+
5+
PROC_ALIAS({"generic"}, {"generic-rv32"}, {"generic-rv64"})
6+
PROC_ALIAS({"rocket"}, {"rocket-rv32"}, {"rocket-rv64"})
7+
PROC_ALIAS({"sifive-7-series"}, {"sifive-7-rv32"}, {"sifive-7-rv64"})
8+
9+
#undef PROC_ALIAS
10+
111
#ifndef PROC
212
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH)
313
#endif

llvm/include/llvm/Support/TargetParser.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,10 +160,14 @@ enum FeatureKind : unsigned {
160160
};
161161

162162
bool checkCPUKind(CPUKind Kind, bool IsRV64);
163+
bool checkTuneCPUKind(CPUKind Kind, bool IsRV64);
163164
CPUKind parseCPUKind(StringRef CPU);
165+
CPUKind parseTuneCPUKind(StringRef CPU, bool IsRV64);
164166
StringRef getMArchFromMcpu(StringRef CPU);
165167
void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
168+
void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64);
166169
bool getCPUFeaturesExceptStdExt(CPUKind Kind, std::vector<StringRef> &Features);
170+
StringRef resolveTuneCPUAlias(StringRef TuneCPU, bool IsRV64);
167171

168172
} // namespace RISCV
169173

llvm/lib/Support/TargetParser.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,13 +253,35 @@ bool checkCPUKind(CPUKind Kind, bool IsRV64) {
253253
return RISCVCPUInfo[static_cast<unsigned>(Kind)].is64Bit() == IsRV64;
254254
}
255255

256+
bool checkTuneCPUKind(CPUKind Kind, bool IsRV64) {
257+
if (Kind == CK_INVALID)
258+
return false;
259+
return RISCVCPUInfo[static_cast<unsigned>(Kind)].is64Bit() == IsRV64;
260+
}
261+
256262
CPUKind parseCPUKind(StringRef CPU) {
257263
return llvm::StringSwitch<CPUKind>(CPU)
258264
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) .Case(NAME, CK_##ENUM)
259265
#include "llvm/Support/RISCVTargetParser.def"
260266
.Default(CK_INVALID);
261267
}
262268

269+
StringRef resolveTuneCPUAlias(StringRef TuneCPU, bool IsRV64) {
270+
return llvm::StringSwitch<StringRef>(TuneCPU)
271+
#define PROC_ALIAS(NAME, RV32, RV64) .Case(NAME, IsRV64 ? StringRef(RV64) : StringRef(RV32))
272+
#include "llvm/Support/RISCVTargetParser.def"
273+
.Default(TuneCPU);
274+
}
275+
276+
CPUKind parseTuneCPUKind(StringRef TuneCPU, bool IsRV64) {
277+
TuneCPU = resolveTuneCPUAlias(TuneCPU, IsRV64);
278+
279+
return llvm::StringSwitch<CPUKind>(TuneCPU)
280+
#define PROC(ENUM, NAME, FEATURES, DEFAULT_MARCH) .Case(NAME, CK_##ENUM)
281+
#include "llvm/Support/RISCVTargetParser.def"
282+
.Default(CK_INVALID);
283+
}
284+
263285
StringRef getMArchFromMcpu(StringRef CPU) {
264286
CPUKind Kind = parseCPUKind(CPU);
265287
return RISCVCPUInfo[static_cast<unsigned>(Kind)].DefaultMarch;
@@ -272,6 +294,15 @@ void fillValidCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
272294
}
273295
}
274296

297+
void fillValidTuneCPUArchList(SmallVectorImpl<StringRef> &Values, bool IsRV64) {
298+
for (const auto &C : RISCVCPUInfo) {
299+
if (C.Kind != CK_INVALID && IsRV64 == C.is64Bit())
300+
Values.emplace_back(C.Name);
301+
}
302+
#define PROC_ALIAS(NAME, RV32, RV64) Values.emplace_back(StringRef(NAME));
303+
#include "llvm/Support/RISCVTargetParser.def"
304+
}
305+
275306
// Get all features except standard extension feature
276307
bool getCPUFeaturesExceptStdExt(CPUKind Kind,
277308
std::vector<StringRef> &Features) {

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ void RISCVAsmPrinter::emitAttributes() {
198198
StringRef CPU = TM.getTargetCPU();
199199
StringRef FS = TM.getTargetFeatureString();
200200
const RISCVTargetMachine &RTM = static_cast<const RISCVTargetMachine &>(TM);
201-
const RISCVSubtarget STI(TT, CPU, FS, /*ABIName=*/"", RTM);
201+
/* TuneCPU doesn't impact emission of ELF attributes, ELF attributes only
202+
care about arch related features, so we can set TuneCPU as CPU. */
203+
const RISCVSubtarget STI(TT, CPU, /*TuneCPU=*/CPU, FS, /*ABIName=*/"", RTM);
202204

203205
RTS.emitTargetAttributes(STI);
204206
}

llvm/lib/Target/RISCV/RISCVSubtarget.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@ using namespace llvm;
3030
void RISCVSubtarget::anchor() {}
3131

3232
RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(
33-
const Triple &TT, StringRef CPU, StringRef FS, StringRef ABIName) {
33+
const Triple &TT, StringRef CPU, StringRef TuneCPU, StringRef FS, StringRef ABIName) {
3434
// Determine default and user-specified characteristics
3535
bool Is64Bit = TT.isArch64Bit();
3636
std::string CPUName = std::string(CPU);
37+
std::string TuneCPUName = std::string(TuneCPU);
3738
if (CPUName.empty())
3839
CPUName = Is64Bit ? "generic-rv64" : "generic-rv32";
39-
ParseSubtargetFeatures(CPUName, /*TuneCPU*/ CPUName, FS);
40+
if (TuneCPUName.empty())
41+
TuneCPUName = CPUName;
42+
ParseSubtargetFeatures(CPUName, TuneCPUName, FS);
4043
if (Is64Bit) {
4144
XLenVT = MVT::i64;
4245
XLen = 64;
@@ -47,11 +50,12 @@ RISCVSubtarget &RISCVSubtarget::initializeSubtargetDependencies(
4750
return *this;
4851
}
4952

50-
RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
53+
RISCVSubtarget::RISCVSubtarget(const Triple &TT, StringRef CPU,
54+
StringRef TuneCPU, StringRef FS,
5155
StringRef ABIName, const TargetMachine &TM)
52-
: RISCVGenSubtargetInfo(TT, CPU, /*TuneCPU*/ CPU, FS),
56+
: RISCVGenSubtargetInfo(TT, CPU, TuneCPU, FS),
5357
UserReservedRegister(RISCV::NUM_TARGET_REGS),
54-
FrameLowering(initializeSubtargetDependencies(TT, CPU, FS, ABIName)),
58+
FrameLowering(initializeSubtargetDependencies(TT, CPU, TuneCPU, FS, ABIName)),
5559
InstrInfo(*this), RegInfo(getHwMode()), TLInfo(TM, *this) {
5660
CallLoweringInfo.reset(new RISCVCallLowering(*getTargetLowering()));
5761
Legalizer.reset(new RISCVLegalizerInfo(*this));

llvm/lib/Target/RISCV/RISCVSubtarget.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,13 +71,15 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
7171
/// Initializes using the passed in CPU and feature strings so that we can
7272
/// use initializer lists for subtarget initialization.
7373
RISCVSubtarget &initializeSubtargetDependencies(const Triple &TT,
74-
StringRef CPU, StringRef FS,
74+
StringRef CPU,
75+
StringRef TuneCPU,
76+
StringRef FS,
7577
StringRef ABIName);
7678

7779
public:
7880
// Initializes the data members to match that of the specified triple.
79-
RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef FS,
80-
StringRef ABIName, const TargetMachine &TM);
81+
RISCVSubtarget(const Triple &TT, StringRef CPU, StringRef TuneCPU,
82+
StringRef FS, StringRef ABIName, const TargetMachine &TM);
8183

8284
// Parses features string setting specified subtarget options. The
8385
// definition of this function is auto-generated by tblgen.

llvm/lib/Target/RISCV/RISCVTargetMachine.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,16 @@ RISCVTargetMachine::RISCVTargetMachine(const Target &T, const Triple &TT,
7575
const RISCVSubtarget *
7676
RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
7777
Attribute CPUAttr = F.getFnAttribute("target-cpu");
78+
Attribute TuneAttr = F.getFnAttribute("tune-cpu");
7879
Attribute FSAttr = F.getFnAttribute("target-features");
7980

8081
std::string CPU =
8182
CPUAttr.isValid() ? CPUAttr.getValueAsString().str() : TargetCPU;
83+
std::string TuneCPU =
84+
TuneAttr.isValid() ? TuneAttr.getValueAsString().str() : CPU;
8285
std::string FS =
8386
FSAttr.isValid() ? FSAttr.getValueAsString().str() : TargetFS;
84-
std::string Key = CPU + FS;
87+
std::string Key = CPU + TuneCPU + FS;
8588
auto &I = SubtargetMap[Key];
8689
if (!I) {
8790
// This needs to be done before we create a new subtarget since any
@@ -98,7 +101,7 @@ RISCVTargetMachine::getSubtargetImpl(const Function &F) const {
98101
}
99102
ABIName = ModuleTargetABI->getString();
100103
}
101-
I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, FS, ABIName, *this);
104+
I = std::make_unique<RISCVSubtarget>(TargetTriple, CPU, TuneCPU, FS, ABIName, *this);
102105
}
103106
return I.get();
104107
}

0 commit comments

Comments
 (0)