Author: Yingwei Zheng Date: 2024-07-16T10:11:39+08:00 New Revision: 578cf724de56e6c6768859bb1b6a597ee5d14ea0
URL: https://github.com/llvm/llvm-project/commit/578cf724de56e6c6768859bb1b6a597ee5d14ea0 DIFF: https://github.com/llvm/llvm-project/commit/578cf724de56e6c6768859bb1b6a597ee5d14ea0.diff LOG: [RISCV] Add support for getHostCPUFeatures using hwprobe (#94352) This patch adds support for `sys::getHostCPUFeatures` using the RISC-V hardware probing interface. References: + Loongarch patch: https://github.com/llvm/llvm-project/commit/e53f41c39f3eb5052965c720d2cb517d2945fd12 + asm/hwprobe.h: https://github.com/torvalds/linux/blob/2ab79514109578fc4b6df90633d500cf281eb689/arch/riscv/include/uapi/asm/hwprobe.h + glibc support: https://inbox.sourceware.org/glibc-cvs/20240301151728.ad5963858...@sourceware.org/T/#Z2e.:..:20240301151728.AD5963858C53::40sourceware.org:1sysdeps:unix:sysv:linux:riscv:sys:hwprobe.h + __NR_riscv_hwprobe syscall tutorial: https://github.com/cyyself/hwprobe + hwprobe docs: https://docs.kernel.org/arch/riscv/hwprobe.html --------- Co-authored-by: Yangyu Chen <c...@cyyself.name> Added: Modified: clang/lib/Driver/ToolChains/Arch/RISCV.cpp llvm/docs/ReleaseNotes.rst llvm/lib/TargetParser/Host.cpp Removed: ################################################################################ diff --git a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp index c3f0251c80750..149a31f58e75d 100644 --- a/clang/lib/Driver/ToolChains/Arch/RISCV.cpp +++ b/clang/lib/Driver/ToolChains/Arch/RISCV.cpp @@ -310,8 +310,24 @@ std::string riscv::getRISCVArch(const llvm::opt::ArgList &Args, // 2. Get march (isa string) based on `-mcpu=` if (const Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { StringRef CPU = A->getValue(); - if (CPU == "native") + if (CPU == "native") { CPU = llvm::sys::getHostCPUName(); + // If the target cpu is unrecognized, use target features. + if (CPU.starts_with("generic")) { + auto FeatureMap = llvm::sys::getHostCPUFeatures(); + // hwprobe may be unavailable on older Linux versions. + if (!FeatureMap.empty()) { + std::vector<std::string> Features; + for (auto &F : FeatureMap) + Features.push_back(((F.second ? "+" : "-") + F.first()).str()); + auto ParseResult = llvm::RISCVISAInfo::parseFeatures( + Triple.isRISCV32() ? 32 : 64, Features); + if (ParseResult) + return (*ParseResult)->toString(); + } + } + } + StringRef MArch = llvm::RISCV::getMArchFromMcpu(CPU); // Bypass if target cpu's default march is empty. if (MArch != "") diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 55b3b486d705d..f803a7bb134c4 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -203,6 +203,7 @@ Changes to the RISC-V Backend * Ztso is no longer experimental. * The WCH / Nanjing Qinheng Microelectronics QingKe "XW" compressed opcodes are supported under the name "Xwchc". +* ``-mcpu=native`` now detects available features with hwprobe (RISC-V Hardware Probing Interface) on Linux 6.4 or later. Changes to the WebAssembly Backend ---------------------------------- diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp index 8d5ad91839bc4..82c1731f58f0a 100644 --- a/llvm/lib/TargetParser/Host.cpp +++ b/llvm/lib/TargetParser/Host.cpp @@ -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() { @@ -1573,8 +1573,10 @@ 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; +#endif #if __riscv_xlen == 64 return "generic-rv64"; #elif __riscv_xlen == 32 @@ -1582,7 +1584,6 @@ StringRef sys::getHostCPUName() { #else #error "Unhandled value of __riscv_xlen" #endif -#endif } #elif defined(__sparc__) #if defined(__linux__) @@ -2006,6 +2007,76 @@ const StringMap<bool> sys::getHostCPUFeatures() { return Features; } +#elif defined(__linux__) && defined(__riscv) +// struct riscv_hwprobe +struct RISCVHwProbe { + int64_t Key; + uint64_t Value; +}; +const StringMap<bool> sys::getHostCPUFeatures() { + 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, + /*pair_count=*/std::size(Query), /*cpu_count=*/0, + /*cpus=*/0, /*flags=*/0); + if (Ret != 0) + return {}; + + StringMap<bool> Features; + 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; + 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 + 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 + Features["zfa"] = ExtMask & (1ULL << 32); // RISCV_HWPROBE_EXT_ZFA + Features["ztso"] = ExtMask & (1ULL << 33); // RISCV_HWPROBE_EXT_ZTSO + 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 Features; +} #else const StringMap<bool> sys::getHostCPUFeatures() { return {}; } #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits