https://gcc.gnu.org/g:0381c77496a780faf319d1d7acaebaa19b7413be
commit r15-11342-g0381c77496a780faf319d1d7acaebaa19b7413be Author: Yi Chen <[email protected]> Date: Tue Jun 30 10:26:09 2026 +0000 libstdc++: Add Hygon x86 RNG instructions support to std::random_device Adapt std::random_device to use the Hygon x86 hardware RNG instructions RDRAND and RDSEED, bringing Hygon C86 platforms to parity with Intel and AMD. Prior to this change Hygon was absent from the CPUID vendor allowlists that gate RDRAND/RDSEED in random_device::_M_init, so std::random_device fell through to a software RNG. Hygon C86 CPUs report the HygonGenuine vendor signature (CPUID leaf 0 ebx 0x6f677948) and support both RDRAND and RDSEED. Add signature_HYGON_ebx to the RDSEED and RDRAND vendor allowlists in random_device::_M_init, matching the existing ebx-only Intel/AMD pattern. With this, the explicit "rdseed" and "rdrand" token paths select sources on Hygon in exactly the same order as on Intel/AMD. For the default device (the "default" token, which == any) Hygon prefers RDRAND, the higher-throughput instruction, suited to bulk generation; RDSEED provides higher-entropy seed material at lower throughput and remains fully accessible via the explicit "rdseed" token and the "hw"/"hardware" tokens. Choosing RDRAND for the Hygon default therefore favors throughput for the common case while preserving RDSEED access for security-sensitive callers, and the entropy() guarantee is unchanged (32 bits per call for both paths). The default policy is handled by a dedicated check at the top of _M_init, kept separate from the explicit-token paths so their selection order stays identical to Intel/AMD. The existing RDSEED-first default policy is retained for Intel and AMD; their behavior is entirely unchanged. Tested on Hygon C86 7185: random_device("default"), ("rdrand") and ("rdseed") all succeed; entropy() returns 32 for each; the existing 94087.cc test, which exercises the default-token path, passes on Hygon. * src/c++11/random.cc (random_device::_M_init): Add signature_HYGON_ebx to the RDSEED and RDRAND CPUID vendor allowlists. For the default device on Hygon, prefer RDRAND via a dedicated check at the top of the function. Signed-off-by: Yi Chen <[email protected]> (cherry picked from commit 770147194498eb1d3cec75397ab43e3a298f2774) Diff: --- libstdc++-v3/src/c++11/random.cc | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc index 9badabbdfc32..53dcafa3a338 100644 --- a/libstdc++-v3/src/c++11/random.cc +++ b/libstdc++-v3/src/c++11/random.cc @@ -390,14 +390,35 @@ namespace std _GLIBCXX_VISIBILITY(default) } #endif // _GLIBCXX_USE_CRT_RAND_S +#ifdef USE_RDRAND + // For the default device on Hygon prefer RDRAND (faster than RDSEED for + // bulk generation); an explicit "rdseed" token still selects rdseed below. + if (which == any) + { + unsigned int eax, ebx, ecx, edx; + if (__get_cpuid_max(0, &ebx) > 0 && ebx == signature_HYGON_ebx) + { + // CPUID.01H:ECX.RDRAND[bit 30] + __cpuid(1, eax, ebx, ecx, edx); + if (ecx & bit_RDRND) + { + _M_func = &__x86_rdrand; + return; + } + } + } +#endif // USE_RDRAND + #ifdef USE_RDSEED if (which & rdseed) { unsigned int eax, ebx, ecx, edx; // Check availability of cpuid and, for now at least, also the - // CPU signature for Intel and AMD. + // CPU signature for Intel, AMD and Hygon. if (__get_cpuid_max(0, &ebx) > 0 - && (ebx == signature_INTEL_ebx || ebx == signature_AMD_ebx)) + && (ebx == signature_INTEL_ebx + || ebx == signature_AMD_ebx + || ebx == signature_HYGON_ebx)) { // CPUID.(EAX=07H, ECX=0H):EBX.RDSEED[bit 18] __cpuid_count(7, 0, eax, ebx, ecx, edx); @@ -425,9 +446,11 @@ namespace std _GLIBCXX_VISIBILITY(default) { unsigned int eax, ebx, ecx, edx; // Check availability of cpuid and, for now at least, also the - // CPU signature for Intel and AMD. + // CPU signature for Intel, AMD and Hygon. if (__get_cpuid_max(0, &ebx) > 0 - && (ebx == signature_INTEL_ebx || ebx == signature_AMD_ebx)) + && (ebx == signature_INTEL_ebx + || ebx == signature_AMD_ebx + || ebx == signature_HYGON_ebx)) { // CPUID.01H:ECX.RDRAND[bit 30] __cpuid(1, eax, ebx, ecx, edx);
