Skip to content
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

Merged
merged 26 commits into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ff839be
[RISCV] Add support for getHostCPUFeatures using hwprobe
dtcxzyw Jun 4, 2024
a2fa6e3
[RISCV] Address review comments.
dtcxzyw Jun 4, 2024
f3f61d6
[RISCV] Check IMA
dtcxzyw Jun 10, 2024
212ddab
[Clang][RISCV] Add clang -mcpu=native support
dtcxzyw Jun 10, 2024
8a40b9e
[RISCV] Fix generic targets
dtcxzyw Jun 22, 2024
0176960
[RISCV] Fix typo. NFC.
dtcxzyw Jun 22, 2024
8c01bdd
[RISCV] Fix missing return statement
dtcxzyw Jun 24, 2024
753d1af
[RISCV] Mark ztso as experimental
dtcxzyw Jun 24, 2024
835bd26
Revert "[RISCV] Mark ztso as experimental"
dtcxzyw Jun 24, 2024
3f6d0d6
Merge branch 'main' into rv-native-hwprobe
dtcxzyw Jun 24, 2024
6c63389
[RISCV] Update release notes. NFC.
dtcxzyw Jun 24, 2024
2e4f615
Merge branch 'main' into rv-native-hwprobe
dtcxzyw Jun 24, 2024
fc8998f
[RISCV] Remove ztso support.
dtcxzyw Jun 24, 2024
7563384
[RISCV] Detect target features in `riscv::getRISCVArch`
dtcxzyw Jun 27, 2024
622bd65
Revert "[RISCV] Detect target features in `riscv::getRISCVArch`"
dtcxzyw Jun 27, 2024
7ce92bb
Merge branch 'main' into rv-native-hwprobe
dtcxzyw Jul 7, 2024
6be7eea
[RISCV][Driver] Remove `Args.MakeArgString`
dtcxzyw Jul 7, 2024
33c063e
Merge branch 'main' into rv-native-hwprobe
dtcxzyw Jul 10, 2024
a515f3b
[RISCV] Format code. NFC.
dtcxzyw Jul 10, 2024
ad887bc
Reland `[RISCV] Add support for getHostCPUFeatures using hwprobe`
dtcxzyw Jul 10, 2024
208a172
[RISCV] Set ztso
dtcxzyw Jul 10, 2024
4acb528
Merge branch 'main' into rv-native-hwprobe
dtcxzyw Jul 13, 2024
adbb036
[RISCV] Fix compilation error
dtcxzyw Jul 13, 2024
6b6fd88
[RISCV] Fallback when hwprobe is unavailable
dtcxzyw Jul 13, 2024
513d9f5
Merge branch 'main' into rv-native-hwprobe
dtcxzyw Jul 15, 2024
558bc0c
[RISCV][Clang] Address review comments.
dtcxzyw Jul 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion clang/lib/Driver/ToolChains/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Copy link
Contributor

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 return generic. Should we failback to use getHostCPUFeatures if getHostCPUName fails? Or we should use getHostCPUFeatures all the time?

Copy link
Member Author

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.

for (auto &F : HostFeatures)
Features.push_back(((F.second ? "+" : "-") + F.first()).str());
}
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wangpc-pp @topperc
Are there any equivalents of the helper printMArch?

// We can generate march string from target features as what has been described
// in RISC-V ISA specification (version 20191213) 'Chapter 27. ISA Extension
// Naming Conventions'.
//
// This is almost the same as RISCVFeatures::parseFeatureBits, except that we
// get feature name from feature records instead of feature bits.
static void printMArch(raw_ostream &OS, const std::vector<Record *> &Features) {
RISCVISAUtils::OrderedExtensionMap Extensions;
unsigned XLen = 0;
// Convert features to FeatureVector.
for (auto *Feature : Features) {
StringRef FeatureName = getExtensionName(Feature);
if (Feature->isSubClassOf("RISCVExtension")) {
unsigned Major = Feature->getValueAsInt("MajorVersion");
unsigned Minor = Feature->getValueAsInt("MinorVersion");
Extensions[FeatureName.str()] = {Major, Minor};
} else if (FeatureName == "64bit") {
assert(XLen == 0 && "Already determined XLen");
XLen = 64;
} else if (FeatureName == "32bit") {
assert(XLen == 0 && "Already determined XLen");
XLen = 32;
}
}
assert(XLen != 0 && "Unable to determine XLen");
OS << "rv" << XLen;
ListSeparator LS("_");
for (auto const &Ext : Extensions)
OS << LS << Ext.first << Ext.second.Major << 'p' << Ext.second.Minor;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wangpc-pp @topperc Are there any equivalents of the helper printMArch?

No, I think there isn't. You may need to write a helper via RISCVISAInfo::parseFeatures and RISCVISAInfo::toString().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See

void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
const ArgList &Args,
std::vector<StringRef> &Features) {
StringRef MArch = getRISCVArch(Args, Triple);
if (!getArchFeatures(D, MArch, Features, Args))
return;
.


getRISCFeaturesFromMcpu(D, A, Triple, CPU, Features);

Expand Down
1 change: 1 addition & 0 deletions llvm/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ Changes to the RISC-V Backend
* B (the collection of the Zba, Zbb, Zbs extensions) is supported.
* Added smcdeleg, ssccfg, smcsrind, and sscsrind extensions to -march.
* ``-mcpu=syntacore-scr3-rv32`` and ``-mcpu=syntacore-scr3-rv64`` were added.
* ``-mcpu=native`` now detects available features with hwprobe (RISC-V Hardware Probing Interface) on Linux 6.4 or later.

Changes to the WebAssembly Backend
----------------------------------
Expand Down
79 changes: 75 additions & 4 deletions llvm/lib/TargetParser/Host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down Expand Up @@ -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__)
Expand Down Expand Up @@ -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,
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently sys::getHostCPUFeatures has three callers:

  • clang -> riscv::getRISCVTargetFeatures
  • llvm-tools -> codegen::getFeaturesStr
  • JIT users -> JITTargetMachineBuilder::detectHost

I don't think there are any opportunities to reuse the result.
BTW, #85790 may benefit from the vDSO symbol, but it implements caching itself.

I didn't use the glibc call __riscv_hwprobe since sys/hwprobe.h was unavailable on my RV board :(

/*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
Expand Down
Loading