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);

Reply via email to