-
Notifications
You must be signed in to change notification settings - Fork 11.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV] Add support for getHostCPUFeatures using hwprobe #94352
Changes from 17 commits
ff839be
a2fa6e3
f3f61d6
212ddab
8a40b9e
0176960
8c01bdd
753d1af
835bd26
3f6d0d6
6c63389
2e4f615
fc8998f
7563384
622bd65
7ce92bb
6be7eea
33c063e
a515f3b
ad887bc
208a172
4acb528
adbb036
6b6fd88
513d9f5
558bc0c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -83,8 +83,13 @@ void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple, | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// and other features (ex. mirco architecture feature) from mcpu | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
StringRef CPU = A->getValue(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (CPU == "native") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (CPU == "native") { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
CPU = llvm::sys::getHostCPUName(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
llvm::StringMap<bool> HostFeatures; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (llvm::sys::getHostCPUFeatures(HostFeatures)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
for (auto &F : HostFeatures) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Features.push_back(((F.second ? "+" : "-") + F.first()).str()); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we also need to update riscv::getRISCVArch? There's analogous logic there for getting features from mcpu native. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wangpc-pp @topperc llvm-project/llvm/utils/TableGen/RISCVTargetDefEmitter.cpp Lines 90 to 123 in ba60d8a
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No, I think there isn't. You may need to write a helper via There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See llvm-project/clang/lib/Driver/ToolChains/Arch/RISCV.cpp Lines 72 to 78 in 0f5fa35
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
getRISCFeaturesFromMcpu(D, A, Triple, CPU, Features); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -452,7 +452,7 @@ StringRef sys::detail::getHostCPUNameForRISCV(StringRef ProcCpuinfoContent) { | |
return StringSwitch<const char *>(UArch) | ||
.Case("sifive,u74-mc", "sifive-u74") | ||
.Case("sifive,bullet0", "sifive-u74") | ||
.Default("generic"); | ||
.Default(""); | ||
} | ||
|
||
StringRef sys::detail::getHostCPUNameForBPF() { | ||
|
@@ -1575,16 +1575,17 @@ StringRef sys::getHostCPUName() { | |
#if defined(__linux__) | ||
std::unique_ptr<llvm::MemoryBuffer> P = getProcCpuinfoContent(); | ||
StringRef Content = P ? P->getBuffer() : ""; | ||
return detail::getHostCPUNameForRISCV(Content); | ||
#else | ||
StringRef Name = detail::getHostCPUNameForRISCV(Content); | ||
if (!Name.empty()) | ||
return Name; | ||
dtcxzyw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#endif | ||
#if __riscv_xlen == 64 | ||
return "generic-rv64"; | ||
#elif __riscv_xlen == 32 | ||
return "generic-rv32"; | ||
#else | ||
#error "Unhandled value of __riscv_xlen" | ||
#endif | ||
#endif | ||
} | ||
#elif defined(__sparc__) | ||
#if defined(__linux__) | ||
|
@@ -2002,6 +2003,76 @@ bool sys::getHostCPUFeatures(StringMap<bool> &Features) { | |
|
||
return true; | ||
} | ||
#elif defined(__linux__) && defined(__riscv) | ||
// struct riscv_hwprobe | ||
struct RISCVHwProbe { | ||
int64_t Key; | ||
uint64_t Value; | ||
}; | ||
bool sys::getHostCPUFeatures(StringMap<bool> &Features) { | ||
RISCVHwProbe Query[]{{/*RISCV_HWPROBE_KEY_BASE_BEHAVIOR=*/3, 0}, | ||
{/*RISCV_HWPROBE_KEY_IMA_EXT_0=*/4, 0}}; | ||
int Ret = syscall(/*__NR_riscv_hwprobe=*/258, /*pairs=*/Query, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider this a purely stylistic comment. We should probably be using either the vDSO symbol or the glibc shim. In either case, we'd have a weak symbol which could possibly be nullptr, and need to return early. In this use case, the difference likely doesn't matter, but if we reuse this code, the lack of caching provided by vDSO could be problematic. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Currently
I don't think there are any opportunities to reuse the result. I didn't use the glibc call |
||
/*pair_count=*/std::size(Query), /*cpu_count=*/0, | ||
/*cpus=*/0, /*flags=*/0); | ||
if (Ret != 0) | ||
return false; | ||
|
||
uint64_t BaseMask = Query[0].Value; | ||
// Check whether RISCV_HWPROBE_BASE_BEHAVIOR_IMA is set. | ||
if (BaseMask & 1) { | ||
Features["i"] = true; | ||
Features["m"] = true; | ||
Features["a"] = true; | ||
} | ||
|
||
uint64_t ExtMask = Query[1].Value; | ||
dtcxzyw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Features["f"] = ExtMask & (1 << 0); // RISCV_HWPROBE_IMA_FD | ||
Features["d"] = ExtMask & (1 << 0); // RISCV_HWPROBE_IMA_FD | ||
Features["c"] = ExtMask & (1 << 1); // RISCV_HWPROBE_IMA_C | ||
Features["v"] = ExtMask & (1 << 2); // RISCV_HWPROBE_IMA_V | ||
dtcxzyw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Features["zba"] = ExtMask & (1 << 3); // RISCV_HWPROBE_EXT_ZBA | ||
Features["zbb"] = ExtMask & (1 << 4); // RISCV_HWPROBE_EXT_ZBB | ||
Features["zbs"] = ExtMask & (1 << 5); // RISCV_HWPROBE_EXT_ZBS | ||
Features["zicboz"] = ExtMask & (1 << 6); // RISCV_HWPROBE_EXT_ZICBOZ | ||
Features["zbc"] = ExtMask & (1 << 7); // RISCV_HWPROBE_EXT_ZBC | ||
Features["zbkb"] = ExtMask & (1 << 8); // RISCV_HWPROBE_EXT_ZBKB | ||
Features["zbkc"] = ExtMask & (1 << 9); // RISCV_HWPROBE_EXT_ZBKC | ||
Features["zbkx"] = ExtMask & (1 << 10); // RISCV_HWPROBE_EXT_ZBKX | ||
Features["zknd"] = ExtMask & (1 << 11); // RISCV_HWPROBE_EXT_ZKND | ||
Features["zkne"] = ExtMask & (1 << 12); // RISCV_HWPROBE_EXT_ZKNE | ||
Features["zknh"] = ExtMask & (1 << 13); // RISCV_HWPROBE_EXT_ZKNH | ||
Features["zksed"] = ExtMask & (1 << 14); // RISCV_HWPROBE_EXT_ZKSED | ||
Features["zksh"] = ExtMask & (1 << 15); // RISCV_HWPROBE_EXT_ZKSH | ||
Features["zkt"] = ExtMask & (1 << 16); // RISCV_HWPROBE_EXT_ZKT | ||
Features["zvbb"] = ExtMask & (1 << 17); // RISCV_HWPROBE_EXT_ZVBB | ||
Features["zvbc"] = ExtMask & (1 << 18); // RISCV_HWPROBE_EXT_ZVBC | ||
Features["zvkb"] = ExtMask & (1 << 19); // RISCV_HWPROBE_EXT_ZVKB | ||
Features["zvkg"] = ExtMask & (1 << 20); // RISCV_HWPROBE_EXT_ZVKG | ||
Features["zvkned"] = ExtMask & (1 << 21); // RISCV_HWPROBE_EXT_ZVKNED | ||
Features["zvknha"] = ExtMask & (1 << 22); // RISCV_HWPROBE_EXT_ZVKNHA | ||
Features["zvknhb"] = ExtMask & (1 << 23); // RISCV_HWPROBE_EXT_ZVKNHB | ||
Features["zvksed"] = ExtMask & (1 << 24); // RISCV_HWPROBE_EXT_ZVKSED | ||
Features["zvksh"] = ExtMask & (1 << 25); // RISCV_HWPROBE_EXT_ZVKSH | ||
Features["zvkt"] = ExtMask & (1 << 26); // RISCV_HWPROBE_EXT_ZVKT | ||
Features["zfh"] = ExtMask & (1 << 27); // RISCV_HWPROBE_EXT_ZFH | ||
Features["zfhmin"] = ExtMask & (1 << 28); // RISCV_HWPROBE_EXT_ZFHMIN | ||
Features["zihintntl"] = ExtMask & (1 << 29); // RISCV_HWPROBE_EXT_ZIHINTNTL | ||
Features["zvfh"] = ExtMask & (1 << 30); // RISCV_HWPROBE_EXT_ZVFH | ||
Features["zvfhmin"] = ExtMask & (1ULL << 31); // RISCV_HWPROBE_EXT_ZVFHMIN | ||
topperc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Features["zfa"] = ExtMask & (1ULL << 32); // RISCV_HWPROBE_EXT_ZFA | ||
// TODO: set ztso when it is no longer experimental. | ||
// Features["ztso"] = ExtMask & (1ULL << 33); // RISCV_HWPROBE_EXT_ZTSO | ||
dtcxzyw marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Features["zacas"] = ExtMask & (1ULL << 34); // RISCV_HWPROBE_EXT_ZACAS | ||
Features["zicond"] = ExtMask & (1ULL << 35); // RISCV_HWPROBE_EXT_ZICOND | ||
Features["zihintpause"] = | ||
ExtMask & (1ULL << 36); // RISCV_HWPROBE_EXT_ZIHINTPAUSE | ||
|
||
// TODO: set unaligned-scalar-mem if RISCV_HWPROBE_KEY_MISALIGNED_PERF returns | ||
// RISCV_HWPROBE_MISALIGNED_FAST. | ||
|
||
return true; | ||
} | ||
#else | ||
bool sys::getHostCPUFeatures(StringMap<bool> &Features) { return false; } | ||
#endif | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Open discussion here:
CPU
may fail and returngeneric
. Should we failback to usegetHostCPUFeatures
ifgetHostCPUName
fails? Or we should usegetHostCPUFeatures
all the time?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think hwprobe is more reliable than cpu name because some RV cpus are not recognized by LLVM (e.g., T-head's cores). However, cpu name is still useful even if
getHostCPUFeatures
returns true because it may provide scheduling model.