public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] libstdc++: Add support for POWER9 DARN instruction to std::random_device
@ 2021-10-19 16:47 Jonathan Wakely
  2021-10-20  9:12 ` Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2021-10-19 16:47 UTC (permalink / raw)
  To: libstdc++, gcc-patches; +Cc: Bill Schmidt, Segher Boessenkool

[-- Attachment #1: Type: text/plain, Size: 1696 bytes --]

The ISA-3.0 instruction set includes DARN ("deliver a random number")
which can be used similar to the existing support for RDRAND and RDSEED.

libstdc++-v3/ChangeLog:

	* src/c++11/random.cc (USE_DARN): Define.
	(__ppc_darn): New function to use POWER9 DARN instruction.
	(Which): Add 'darn' enumerator.
	(which_source): Check for __ppc_darn.
	(random_device::_M_init): Support "darn" and "hw" tokens.
	(random_device::_M_getentropy): Add darn to switch.
	* testsuite/26_numerics/random/random_device/cons/token.cc:
	Check "darn" token.
	* testsuite/26_numerics/random/random_device/entropy.cc:
	Likewise.

Tested powerpc64le-linux (power8 and power9) and x86_64-linux.

The new "darn" (power-specific) and "hw" (x86 and power)
strings should be documented, but I'll do that if this gets committed.

Most of this patch is just "more of the same", similar to the existing
code for RDRAND and RDSEED on x86, but the parts of the patch I'd like
more eyes on are:


+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
+# define USE_DARN 1
 #endif

 #include <cerrno>


and:


@@ -135,6 +137,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
 #endif
 #endif

+#ifdef USE_DARN
+    unsigned int
+    __attribute__((target("power9")))
+    __ppc_darn(void*)
+    {
+      return __builtin_darn_32();
+    }
+#endif
+


and:

@@ -346,6 +375,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif // USE_RDRAND

+#ifdef USE_DARN
+    if (which & darn)
+      {
+       if (__builtin_cpu_supports("darn"))
+         {
+           _M_func = &__ppc_darn;
+           return;
+         }
+      }
+#endif // USE_DARN
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
     if (which & device_file)
     {


[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 5301 bytes --]

commit 5cfef2d435b5cb3b3e959e14e4b1edde8edea473
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Oct 19 12:53:00 2021

    libstdc++: Add support for POWER9 DARN instruction to std::random_device
    
    The ISA-3.0 instruction set includes DARN ("deliver a random number")
    which can be used similar to the existing support for RDRAND and RDSEED.
    
    libstdc++-v3/ChangeLog:
    
            * src/c++11/random.cc (USE_DARN): Define.
            (__ppc_darn): New function to use POWER9 DARN instruction.
            (Which): Add 'darn' enumerator.
            (which_source): Check for __ppc_darn.
            (random_device::_M_init): Support "darn" and "hw" tokens.
            (random_device::_M_getentropy): Add darn to switch.
            * testsuite/26_numerics/random/random_device/cons/token.cc:
            Check "darn" token.
            * testsuite/26_numerics/random/random_device/entropy.cc:
            Likewise.

diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc
index 4b64bde00ea..96d59799c2c 100644
--- a/libstdc++-v3/src/c++11/random.cc
+++ b/libstdc++-v3/src/c++11/random.cc
@@ -37,6 +37,8 @@
 # ifdef _GLIBCXX_X86_RDSEED
 #  define USE_RDSEED 1
 # endif
+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
+# define USE_DARN 1
 #endif
 
 #include <cerrno>
@@ -69,7 +71,7 @@
 #if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM
 // The OS provides a source of randomness we can use.
 # pragma GCC poison _M_mt
-#elif defined USE_RDRAND || defined USE_RDSEED
+#elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
 // Hardware instructions might be available, but use cpuid checks at runtime.
 # pragma GCC poison _M_mt
 // If the runtime cpuid checks fail we'll use a linear congruential engine.
@@ -135,6 +137,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
 #endif
 #endif
 
+#ifdef USE_DARN
+    unsigned int
+    __attribute__((target("power9")))
+    __ppc_darn(void*)
+    {
+      return __builtin_darn_32();
+    }
+#endif
+
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     unsigned int
     __winxp_rand_s(void*)
@@ -193,11 +204,16 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif
 
-    enum Which {
-      rand_s = 1, rdseed = 2, rdrand = 4, device_file = 8, prng = 16,
+    enum Which : unsigned {
+      device_file = 1, prng = 2, rand_s = 4,
+      rdseed = 64, rdrand = 128, darn = 256,
       any = 0xffff
     };
 
+    constexpr Which
+    operator|(Which l, Which r) noexcept
+    { return Which(unsigned(l) | unsigned(r)); }
+
     inline Which
     which_source(random_device::result_type (*func [[maybe_unused]])(void*),
 		 void* file [[maybe_unused]])
@@ -221,6 +237,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
 	return rdrand;
 #endif
 
+#ifdef USE_DARN
+      if (func == &__ppc_darn)
+	return darn;
+#endif
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
       if (file != nullptr)
 	return device_file;
@@ -269,6 +290,14 @@ namespace std _GLIBCXX_VISIBILITY(default)
     else if (token == "rdrand" || token == "rdrnd")
       which = rdrand;
 #endif // USE_RDRAND
+#ifdef USE_DARN
+    else if (token == "darn")
+      which = darn;
+#endif
+#if defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
+    else if (token == "hw" || token == "hardware")
+      which = rdrand | rdseed | darn;
+#endif
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     else if (token == "rand_s")
       which = rand_s;
@@ -346,6 +375,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif // USE_RDRAND
 
+#ifdef USE_DARN
+    if (which & darn)
+      {
+	if (__builtin_cpu_supports("darn"))
+	  {
+	    _M_func = &__ppc_darn;
+	    return;
+	  }
+      }
+#endif // USE_DARN
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
     if (which & device_file)
     {
@@ -497,6 +537,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
     {
     case rdrand:
     case rdseed:
+    case darn:
       return (double) max;
     case rand_s:
     case prng:
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
index aeb7403e830..d6ac3a37c64 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
@@ -51,8 +51,9 @@ test03()
 {
   // At least one of these tokens should be valid.
   const std::string tokens[] = {
-    "rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937",
-    "prng"
+    "rdseed", "rdrand", "darn",
+    "rand_s", "/dev/urandom", "/dev/random",
+    "mt19937", "prng"
   };
   int count = 0;
   for (const std::string& token : tokens)
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
index 9ef1538d2bb..6f3ebb1b38e 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
@@ -22,7 +22,7 @@ test01()
       VERIFY( entropy <= max );
     }
 
-  for (auto token : { "rdrand", "rdseed" })
+  for (auto token : { "rdrand", "rdseed", "darn", "hw" })
     if (__gnu_test::random_device_available(token))
     {
       const double entropy = std::random_device(token).entropy();

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-10-19 16:47 [PATCH] libstdc++: Add support for POWER9 DARN instruction to std::random_device Jonathan Wakely
@ 2021-10-20  9:12 ` Jonathan Wakely
  2021-10-20 13:00   ` [PATCH v2] " Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2021-10-20  9:12 UTC (permalink / raw)
  To: libstdc++, gcc-patches; +Cc: Bill Schmidt, Segher Boessenkool

On 19/10/21 17:47 +0100, Jonathan Wakely wrote:
>The ISA-3.0 instruction set includes DARN ("deliver a random number")
>which can be used similar to the existing support for RDRAND and RDSEED.
>
>libstdc++-v3/ChangeLog:
>
>	* src/c++11/random.cc (USE_DARN): Define.
>	(__ppc_darn): New function to use POWER9 DARN instruction.
>	(Which): Add 'darn' enumerator.
>	(which_source): Check for __ppc_darn.
>	(random_device::_M_init): Support "darn" and "hw" tokens.
>	(random_device::_M_getentropy): Add darn to switch.
>	* testsuite/26_numerics/random/random_device/cons/token.cc:
>	Check "darn" token.
>	* testsuite/26_numerics/random/random_device/entropy.cc:
>	Likewise.
>
>Tested powerpc64le-linux (power8 and power9) and x86_64-linux.
>
>The new "darn" (power-specific) and "hw" (x86 and power)
>strings should be documented, but I'll do that if this gets committed.
>
>Most of this patch is just "more of the same", similar to the existing
>code for RDRAND and RDSEED on x86, but the parts of the patch I'd like
>more eyes on are:
>
>
>+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
>+# define USE_DARN 1
> #endif

This means DARN can only be used when __builtin_cpu_supports is
available, which means glibc 2.23 ... is that acceptable? It means
RHEL 7 wouldn't be able to use DARN, but RHEL 8 would.

There certainly are POWER9 machines running RHEL 7 and similar
vintages (the GCC compile farm has one) so if there's another way to
check for ISA 3.0 then I could use that.

If __POWER9_VECTOR__ is defined when building libstdc++, presumably
that means the whole library can only be run on POWER9 hardware. So
would that mean we don't need to check __builtin_cpu_supports("darn")
when __POWER9_VECTOR__ is defined? Or is it possible to build with
-mcpu=power8 -mpower9-vector and run it on h/w without the DARN
instruction?

Also, I forgot to add a configure check that the assembler supports
darn, which is another prerequisite for using it here.

>@@ -135,6 +137,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
> #endif
> #endif
>
>+#ifdef USE_DARN
>+    unsigned int
>+    __attribute__((target("power9")))

Oops, that should be "cpu=power9".

With that change it works on a POWER9 machine (9009-42A) with glibc
2.34 and binutils 2.35.


>+    __ppc_darn(void*)
>+    {
>+      return __builtin_darn_32();
>+    }
>+#endif


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH v2] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-10-20  9:12 ` Jonathan Wakely
@ 2021-10-20 13:00   ` Jonathan Wakely
  2021-11-03 15:01     ` Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2021-10-20 13:00 UTC (permalink / raw)
  To: libstdc++, gcc-patches; +Cc: Bill Schmidt, Segher Boessenkool

[-- Attachment #1: Type: text/plain, Size: 2568 bytes --]

On 20/10/21 10:12 +0100, Jonathan Wakely wrote:
>On 19/10/21 17:47 +0100, Jonathan Wakely wrote:
>>The ISA-3.0 instruction set includes DARN ("deliver a random number")
>>which can be used similar to the existing support for RDRAND and RDSEED.
>>
>>libstdc++-v3/ChangeLog:
>>
>>	* src/c++11/random.cc (USE_DARN): Define.
>>	(__ppc_darn): New function to use POWER9 DARN instruction.
>>	(Which): Add 'darn' enumerator.
>>	(which_source): Check for __ppc_darn.
>>	(random_device::_M_init): Support "darn" and "hw" tokens.
>>	(random_device::_M_getentropy): Add darn to switch.
>>	* testsuite/26_numerics/random/random_device/cons/token.cc:
>>	Check "darn" token.
>>	* testsuite/26_numerics/random/random_device/entropy.cc:
>>	Likewise.
>>
>>Tested powerpc64le-linux (power8 and power9) and x86_64-linux.
>>
>>The new "darn" (power-specific) and "hw" (x86 and power)
>>strings should be documented, but I'll do that if this gets committed.
>>
>>Most of this patch is just "more of the same", similar to the existing
>>code for RDRAND and RDSEED on x86, but the parts of the patch I'd like
>>more eyes on are:
>>
>>
>>+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
>>+# define USE_DARN 1
>>#endif
>
>This means DARN can only be used when __builtin_cpu_supports is
>available, which means glibc 2.23 ... is that acceptable? It means
>RHEL 7 wouldn't be able to use DARN, but RHEL 8 would.
>
>There certainly are POWER9 machines running RHEL 7 and similar
>vintages (the GCC compile farm has one) so if there's another way to
>check for ISA 3.0 then I could use that.
>
>If __POWER9_VECTOR__ is defined when building libstdc++, presumably
>that means the whole library can only be run on POWER9 hardware. So
>would that mean we don't need to check __builtin_cpu_supports("darn")
>when __POWER9_VECTOR__ is defined? Or is it possible to build with
>-mcpu=power8 -mpower9-vector and run it on h/w without the DARN
>instruction?
>
>Also, I forgot to add a configure check that the assembler supports
>darn, which is another prerequisite for using it here.
>
>>@@ -135,6 +137,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
>>#endif
>>#endif
>>
>>+#ifdef USE_DARN
>>+    unsigned int
>>+    __attribute__((target("power9")))
>
>Oops, that should be "cpu=power9".
>
>With that change it works on a POWER9 machine (9009-42A) with glibc
>2.34 and binutils 2.35.
>

Here's the updated patch with a configure check for assembler support,
and the target attribute fixed.

This still requires Glibc 2.23 for __builtin_cpu_supports, which I'm
assuming is acceptable.



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 7007 bytes --]

commit a6f925407dd05c593b230da1627435adc53584f8
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Oct 20 09:25:24 2021

    libstdc++: Add support for POWER9 DARN instruction to std::random_device
    
    The ISA-3.0 instruction set includes DARN ("deliver a random number")
    which can be used similar to the existing support for RDRAND and RDSEED.
    
    libstdc++-v3/ChangeLog:
    
            * acinclude.m4 (GLIBCXX_CHECK_PPC_DARN): Check assembler.
            * config.h.in: Regenerate.
            * configure: Regenerate.
            * configure.ac: Use GLIBCXX_CHECK_PPC_DARN.
            * src/c++11/random.cc [_GLIBCXX_PPC_DARN] (USE_DARN): Define.
            (__ppc_darn): New function to use POWER9 DARN instruction.
            (Which): Add 'darn' enumerator.
            (which_source): Check for __ppc_darn.
            (random_device::_M_init): Support "darn" and "hw" tokens.
            (random_device::_M_getentropy): Add darn to switch.
            * testsuite/26_numerics/random/random_device/cons/token.cc:
            Check "darn" token.
            * testsuite/26_numerics/random/random_device/entropy.cc:
            Likewise.

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 90ecc4a87a2..9ff9ceb20ac 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4100,6 +4100,27 @@ AC_DEFUN([GLIBCXX_CHECK_X86_RDSEED], [
   AC_MSG_RESULT($ac_cv_x86_rdseed)
 ])
 
+dnl
+dnl Check whether darn is supported in the assembler.
+AC_DEFUN([GLIBCXX_CHECK_PPC_DARN], [
+  AC_MSG_CHECKING([for darn support in assembler])
+  AC_CACHE_VAL(ac_cv_ppc_darn, [
+  ac_cv_ppc_darn=no
+  case "$target" in
+    powerpc*-*-*)
+    AC_TRY_COMPILE(, [
+      signed int x;
+      __asm__ __volatile__ (".machine power9; darn %0,0;": "=r" (x));
+    ], [ac_cv_ppc_darn=yes], [ac_cv_ppc_darn=no])
+  esac
+  ])
+  if test $ac_cv_ppc_darn = yes; then
+    AC_DEFINE(_GLIBCXX_PPC_DARN, 1,
+		[ Defined if as can handle darn. ])
+  fi
+  AC_MSG_RESULT($ac_cv_ppc_darn)
+])
+
 dnl
 dnl Check whether get_nprocs is available in <sys/sysinfo.h>, and define _GLIBCXX_USE_GET_NPROCS.
 dnl
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 2d68b3672b9..1189c68c380 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -467,6 +467,8 @@ GCC_CHECK_ASSEMBLER_HWCAP
 GLIBCXX_CHECK_X86_RDRAND
 # Check if assembler supports rdseed opcode.
 GLIBCXX_CHECK_X86_RDSEED
+# Check if assembler supports darn opcode.
+GLIBCXX_CHECK_PPC_DARN
 
 # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE.
 GLIBCXX_CONFIGURE_TESTSUITE
diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc
index 4b64bde00ea..213ad691837 100644
--- a/libstdc++-v3/src/c++11/random.cc
+++ b/libstdc++-v3/src/c++11/random.cc
@@ -37,6 +37,9 @@
 # ifdef _GLIBCXX_X86_RDSEED
 #  define USE_RDSEED 1
 # endif
+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__ \
+  && defined _GLIBCXX_PPC_DARN
+# define USE_DARN 1
 #endif
 
 #include <cerrno>
@@ -69,7 +72,7 @@
 #if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM
 // The OS provides a source of randomness we can use.
 # pragma GCC poison _M_mt
-#elif defined USE_RDRAND || defined USE_RDSEED
+#elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
 // Hardware instructions might be available, but use cpuid checks at runtime.
 # pragma GCC poison _M_mt
 // If the runtime cpuid checks fail we'll use a linear congruential engine.
@@ -135,6 +138,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
 #endif
 #endif
 
+#ifdef USE_DARN
+    unsigned int
+    __attribute__((target("cpu=power9")))
+    __ppc_darn(void*)
+    {
+      return __builtin_darn_32();
+    }
+#endif
+
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     unsigned int
     __winxp_rand_s(void*)
@@ -193,11 +205,16 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif
 
-    enum Which {
-      rand_s = 1, rdseed = 2, rdrand = 4, device_file = 8, prng = 16,
+    enum Which : unsigned {
+      device_file = 1, prng = 2, rand_s = 4,
+      rdseed = 64, rdrand = 128, darn = 256,
       any = 0xffff
     };
 
+    constexpr Which
+    operator|(Which l, Which r) noexcept
+    { return Which(unsigned(l) | unsigned(r)); }
+
     inline Which
     which_source(random_device::result_type (*func [[maybe_unused]])(void*),
 		 void* file [[maybe_unused]])
@@ -221,6 +238,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
 	return rdrand;
 #endif
 
+#ifdef USE_DARN
+      if (func == &__ppc_darn)
+	return darn;
+#endif
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
       if (file != nullptr)
 	return device_file;
@@ -269,6 +291,14 @@ namespace std _GLIBCXX_VISIBILITY(default)
     else if (token == "rdrand" || token == "rdrnd")
       which = rdrand;
 #endif // USE_RDRAND
+#ifdef USE_DARN
+    else if (token == "darn")
+      which = darn;
+#endif
+#if defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
+    else if (token == "hw" || token == "hardware")
+      which = rdrand | rdseed | darn;
+#endif
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     else if (token == "rand_s")
       which = rand_s;
@@ -346,6 +376,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif // USE_RDRAND
 
+#ifdef USE_DARN
+    if (which & darn)
+      {
+	if (__builtin_cpu_supports("darn"))
+	  {
+	    _M_func = &__ppc_darn;
+	    return;
+	  }
+      }
+#endif // USE_DARN
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
     if (which & device_file)
     {
@@ -497,6 +538,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
     {
     case rdrand:
     case rdseed:
+    case darn:
       return (double) max;
     case rand_s:
     case prng:
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
index aeb7403e830..d6ac3a37c64 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
@@ -51,8 +51,9 @@ test03()
 {
   // At least one of these tokens should be valid.
   const std::string tokens[] = {
-    "rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937",
-    "prng"
+    "rdseed", "rdrand", "darn",
+    "rand_s", "/dev/urandom", "/dev/random",
+    "mt19937", "prng"
   };
   int count = 0;
   for (const std::string& token : tokens)
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
index 9ef1538d2bb..6f3ebb1b38e 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
@@ -22,7 +22,7 @@ test01()
       VERIFY( entropy <= max );
     }
 
-  for (auto token : { "rdrand", "rdseed" })
+  for (auto token : { "rdrand", "rdseed", "darn", "hw" })
     if (__gnu_test::random_device_available(token))
     {
       const double entropy = std::random_device(token).entropy();

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-10-20 13:00   ` [PATCH v2] " Jonathan Wakely
@ 2021-11-03 15:01     ` Jonathan Wakely
  2021-11-03 15:02       ` Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2021-11-03 15:01 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc Patches, Bill Schmidt, Segher Boessenkool

Any feedback from POWER maintainers about this? I'd like to push it soon if
there's nothing wrong with it.

On Wed, 20 Oct 2021 at 14:00, Jonathan Wakely via Libstdc++ <
libstdc++@gcc.gnu.org> wrote:

> On 20/10/21 10:12 +0100, Jonathan Wakely wrote:
> >On 19/10/21 17:47 +0100, Jonathan Wakely wrote:
> >>The ISA-3.0 instruction set includes DARN ("deliver a random number")
> >>which can be used similar to the existing support for RDRAND and RDSEED.
> >>
> >>libstdc++-v3/ChangeLog:
> >>
> >>      * src/c++11/random.cc (USE_DARN): Define.
> >>      (__ppc_darn): New function to use POWER9 DARN instruction.
> >>      (Which): Add 'darn' enumerator.
> >>      (which_source): Check for __ppc_darn.
> >>      (random_device::_M_init): Support "darn" and "hw" tokens.
> >>      (random_device::_M_getentropy): Add darn to switch.
> >>      * testsuite/26_numerics/random/random_device/cons/token.cc:
> >>      Check "darn" token.
> >>      * testsuite/26_numerics/random/random_device/entropy.cc:
> >>      Likewise.
> >>
> >>Tested powerpc64le-linux (power8 and power9) and x86_64-linux.
> >>
> >>The new "darn" (power-specific) and "hw" (x86 and power)
> >>strings should be documented, but I'll do that if this gets committed.
> >>
> >>Most of this patch is just "more of the same", similar to the existing
> >>code for RDRAND and RDSEED on x86, but the parts of the patch I'd like
> >>more eyes on are:
> >>
> >>
> >>+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
> >>+# define USE_DARN 1
> >>#endif
> >
> >This means DARN can only be used when __builtin_cpu_supports is
> >available, which means glibc 2.23 ... is that acceptable? It means
> >RHEL 7 wouldn't be able to use DARN, but RHEL 8 would.
> >
> >There certainly are POWER9 machines running RHEL 7 and similar
> >vintages (the GCC compile farm has one) so if there's another way to
> >check for ISA 3.0 then I could use that.
> >
> >If __POWER9_VECTOR__ is defined when building libstdc++, presumably
> >that means the whole library can only be run on POWER9 hardware. So
> >would that mean we don't need to check __builtin_cpu_supports("darn")
> >when __POWER9_VECTOR__ is defined? Or is it possible to build with
> >-mcpu=power8 -mpower9-vector and run it on h/w without the DARN
> >instruction?
> >
> >Also, I forgot to add a configure check that the assembler supports
> >darn, which is another prerequisite for using it here.
> >
> >>@@ -135,6 +137,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
> >>#endif
> >>#endif
> >>
> >>+#ifdef USE_DARN
> >>+    unsigned int
> >>+    __attribute__((target("power9")))
> >
> >Oops, that should be "cpu=power9".
> >
> >With that change it works on a POWER9 machine (9009-42A) with glibc
> >2.34 and binutils 2.35.
> >
>
> Here's the updated patch with a configure check for assembler support,
> and the target attribute fixed.
>
> This still requires Glibc 2.23 for __builtin_cpu_supports, which I'm
> assuming is acceptable.
>
>
>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-11-03 15:01     ` Jonathan Wakely
@ 2021-11-03 15:02       ` Jonathan Wakely
  2021-11-04 20:44         ` Bill Schmidt
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2021-11-03 15:02 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc Patches, Bill Schmidt, Segher Boessenkool

[-- Attachment #1: Type: text/plain, Size: 3150 bytes --]

On Wed, 3 Nov 2021 at 15:01, Jonathan Wakely wrote:

> Any feedback from POWER maintainers about this? I'd like to push it soon
> if there's nothing wrong with it.
>

With the updated patch attached again this time ...



> On Wed, 20 Oct 2021 at 14:00, Jonathan Wakely via Libstdc++ <
> libstdc++@gcc.gnu.org> wrote:
>
>> On 20/10/21 10:12 +0100, Jonathan Wakely wrote:
>> >On 19/10/21 17:47 +0100, Jonathan Wakely wrote:
>> >>The ISA-3.0 instruction set includes DARN ("deliver a random number")
>> >>which can be used similar to the existing support for RDRAND and RDSEED.
>> >>
>> >>libstdc++-v3/ChangeLog:
>> >>
>> >>      * src/c++11/random.cc (USE_DARN): Define.
>> >>      (__ppc_darn): New function to use POWER9 DARN instruction.
>> >>      (Which): Add 'darn' enumerator.
>> >>      (which_source): Check for __ppc_darn.
>> >>      (random_device::_M_init): Support "darn" and "hw" tokens.
>> >>      (random_device::_M_getentropy): Add darn to switch.
>> >>      * testsuite/26_numerics/random/random_device/cons/token.cc:
>> >>      Check "darn" token.
>> >>      * testsuite/26_numerics/random/random_device/entropy.cc:
>> >>      Likewise.
>> >>
>> >>Tested powerpc64le-linux (power8 and power9) and x86_64-linux.
>> >>
>> >>The new "darn" (power-specific) and "hw" (x86 and power)
>> >>strings should be documented, but I'll do that if this gets committed.
>> >>
>> >>Most of this patch is just "more of the same", similar to the existing
>> >>code for RDRAND and RDSEED on x86, but the parts of the patch I'd like
>> >>more eyes on are:
>> >>
>> >>
>> >>+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
>> >>+# define USE_DARN 1
>> >>#endif
>> >
>> >This means DARN can only be used when __builtin_cpu_supports is
>> >available, which means glibc 2.23 ... is that acceptable? It means
>> >RHEL 7 wouldn't be able to use DARN, but RHEL 8 would.
>> >
>> >There certainly are POWER9 machines running RHEL 7 and similar
>> >vintages (the GCC compile farm has one) so if there's another way to
>> >check for ISA 3.0 then I could use that.
>> >
>> >If __POWER9_VECTOR__ is defined when building libstdc++, presumably
>> >that means the whole library can only be run on POWER9 hardware. So
>> >would that mean we don't need to check __builtin_cpu_supports("darn")
>> >when __POWER9_VECTOR__ is defined? Or is it possible to build with
>> >-mcpu=power8 -mpower9-vector and run it on h/w without the DARN
>> >instruction?
>> >
>> >Also, I forgot to add a configure check that the assembler supports
>> >darn, which is another prerequisite for using it here.
>> >
>> >>@@ -135,6 +137,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
>> >>#endif
>> >>#endif
>> >>
>> >>+#ifdef USE_DARN
>> >>+    unsigned int
>> >>+    __attribute__((target("power9")))
>> >
>> >Oops, that should be "cpu=power9".
>> >
>> >With that change it works on a POWER9 machine (9009-42A) with glibc
>> >2.34 and binutils 2.35.
>> >
>>
>> Here's the updated patch with a configure check for assembler support,
>> and the target attribute fixed.
>>
>> This still requires Glibc 2.23 for __builtin_cpu_supports, which I'm
>> assuming is acceptable.
>>
>>
>>

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 7218 bytes --]

commit a6f925407dd05c593b230da1627435adc53584f8
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Oct 20 09:25:24 2021

    libstdc++: Add support for POWER9 DARN instruction to std::random_device
    
    The ISA-3.0 instruction set includes DARN ("deliver a random number")
    which can be used similar to the existing support for RDRAND and RDSEED.
    
    libstdc++-v3/ChangeLog:
    
            * acinclude.m4 (GLIBCXX_CHECK_PPC_DARN): Check assembler.
            * config.h.in: Regenerate.
            * configure: Regenerate.
            * configure.ac: Use GLIBCXX_CHECK_PPC_DARN.
            * src/c++11/random.cc [_GLIBCXX_PPC_DARN] (USE_DARN): Define.
            (__ppc_darn): New function to use POWER9 DARN instruction.
            (Which): Add 'darn' enumerator.
            (which_source): Check for __ppc_darn.
            (random_device::_M_init): Support "darn" and "hw" tokens.
            (random_device::_M_getentropy): Add darn to switch.
            * testsuite/26_numerics/random/random_device/cons/token.cc:
            Check "darn" token.
            * testsuite/26_numerics/random/random_device/entropy.cc:
            Likewise.

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 90ecc4a87a2..9ff9ceb20ac 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4100,6 +4100,27 @@ AC_DEFUN([GLIBCXX_CHECK_X86_RDSEED], [
   AC_MSG_RESULT($ac_cv_x86_rdseed)
 ])
 
+dnl
+dnl Check whether darn is supported in the assembler.
+AC_DEFUN([GLIBCXX_CHECK_PPC_DARN], [
+  AC_MSG_CHECKING([for darn support in assembler])
+  AC_CACHE_VAL(ac_cv_ppc_darn, [
+  ac_cv_ppc_darn=no
+  case "$target" in
+    powerpc*-*-*)
+    AC_TRY_COMPILE(, [
+      signed int x;
+      __asm__ __volatile__ (".machine power9; darn %0,0;": "=r" (x));
+    ], [ac_cv_ppc_darn=yes], [ac_cv_ppc_darn=no])
+  esac
+  ])
+  if test $ac_cv_ppc_darn = yes; then
+    AC_DEFINE(_GLIBCXX_PPC_DARN, 1,
+		[ Defined if as can handle darn. ])
+  fi
+  AC_MSG_RESULT($ac_cv_ppc_darn)
+])
+
 dnl
 dnl Check whether get_nprocs is available in <sys/sysinfo.h>, and define _GLIBCXX_USE_GET_NPROCS.
 dnl
diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac
index 2d68b3672b9..1189c68c380 100644
--- a/libstdc++-v3/configure.ac
+++ b/libstdc++-v3/configure.ac
@@ -467,6 +467,8 @@ GCC_CHECK_ASSEMBLER_HWCAP
 GLIBCXX_CHECK_X86_RDRAND
 # Check if assembler supports rdseed opcode.
 GLIBCXX_CHECK_X86_RDSEED
+# Check if assembler supports darn opcode.
+GLIBCXX_CHECK_PPC_DARN
 
 # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE.
 GLIBCXX_CONFIGURE_TESTSUITE
diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc
index 4b64bde00ea..213ad691837 100644
--- a/libstdc++-v3/src/c++11/random.cc
+++ b/libstdc++-v3/src/c++11/random.cc
@@ -37,6 +37,9 @@
 # ifdef _GLIBCXX_X86_RDSEED
 #  define USE_RDSEED 1
 # endif
+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__ \
+  && defined _GLIBCXX_PPC_DARN
+# define USE_DARN 1
 #endif
 
 #include <cerrno>
@@ -69,7 +72,7 @@
 #if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM
 // The OS provides a source of randomness we can use.
 # pragma GCC poison _M_mt
-#elif defined USE_RDRAND || defined USE_RDSEED
+#elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
 // Hardware instructions might be available, but use cpuid checks at runtime.
 # pragma GCC poison _M_mt
 // If the runtime cpuid checks fail we'll use a linear congruential engine.
@@ -135,6 +138,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
 #endif
 #endif
 
+#ifdef USE_DARN
+    unsigned int
+    __attribute__((target("cpu=power9")))
+    __ppc_darn(void*)
+    {
+      return __builtin_darn_32();
+    }
+#endif
+
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     unsigned int
     __winxp_rand_s(void*)
@@ -193,11 +205,16 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif
 
-    enum Which {
-      rand_s = 1, rdseed = 2, rdrand = 4, device_file = 8, prng = 16,
+    enum Which : unsigned {
+      device_file = 1, prng = 2, rand_s = 4,
+      rdseed = 64, rdrand = 128, darn = 256,
       any = 0xffff
     };
 
+    constexpr Which
+    operator|(Which l, Which r) noexcept
+    { return Which(unsigned(l) | unsigned(r)); }
+
     inline Which
     which_source(random_device::result_type (*func [[maybe_unused]])(void*),
 		 void* file [[maybe_unused]])
@@ -221,6 +238,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
 	return rdrand;
 #endif
 
+#ifdef USE_DARN
+      if (func == &__ppc_darn)
+	return darn;
+#endif
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
       if (file != nullptr)
 	return device_file;
@@ -269,6 +291,14 @@ namespace std _GLIBCXX_VISIBILITY(default)
     else if (token == "rdrand" || token == "rdrnd")
       which = rdrand;
 #endif // USE_RDRAND
+#ifdef USE_DARN
+    else if (token == "darn")
+      which = darn;
+#endif
+#if defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
+    else if (token == "hw" || token == "hardware")
+      which = rdrand | rdseed | darn;
+#endif
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     else if (token == "rand_s")
       which = rand_s;
@@ -346,6 +376,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif // USE_RDRAND
 
+#ifdef USE_DARN
+    if (which & darn)
+      {
+	if (__builtin_cpu_supports("darn"))
+	  {
+	    _M_func = &__ppc_darn;
+	    return;
+	  }
+      }
+#endif // USE_DARN
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
     if (which & device_file)
     {
@@ -497,6 +538,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
     {
     case rdrand:
     case rdseed:
+    case darn:
       return (double) max;
     case rand_s:
     case prng:
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
index aeb7403e830..d6ac3a37c64 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
@@ -51,8 +51,9 @@ test03()
 {
   // At least one of these tokens should be valid.
   const std::string tokens[] = {
-    "rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937",
-    "prng"
+    "rdseed", "rdrand", "darn",
+    "rand_s", "/dev/urandom", "/dev/random",
+    "mt19937", "prng"
   };
   int count = 0;
   for (const std::string& token : tokens)
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
index 9ef1538d2bb..6f3ebb1b38e 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
@@ -22,7 +22,7 @@ test01()
       VERIFY( entropy <= max );
     }
 
-  for (auto token : { "rdrand", "rdseed" })
+  for (auto token : { "rdrand", "rdseed", "darn", "hw" })
     if (__gnu_test::random_device_available(token))
     {
       const double entropy = std::random_device(token).entropy();

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-11-03 15:02       ` Jonathan Wakely
@ 2021-11-04 20:44         ` Bill Schmidt
  2021-11-05 12:44           ` Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Bill Schmidt @ 2021-11-04 20:44 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc Patches, Segher Boessenkool

For posterity:  This was discussed briefly on IRC, and Segher approved with some 
simplifications and a request to implement a fail/retry check.

Thanks,
Bill

On 11/3/21 10:02 AM, Jonathan Wakely wrote:
> On Wed, 3 Nov 2021 at 15:01, Jonathan Wakely wrote: Any feedback from POWER maintainers about this? I'd like to push it soon if there's nothing wrong with it. With the updated patch attached again this time ... ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ‍ ZjQcmQRYFpfptBannerStart
> This Message Is From an External Sender
> This message came from outside your organization.
> ZjQcmQRYFpfptBannerEnd
> On Wed, 3 Nov 2021 at 15:01, Jonathan Wakely wrote:
>
>     Any feedback from POWER maintainers about this? I'd like to push it soon if there's nothing wrong with it.
>
>
> With the updated patch attached again this time ...
>
>
>
>     On Wed, 20 Oct 2021 at 14:00, Jonathan Wakely via Libstdc++ <libstdc++@gcc.gnu.org <mailto:libstdc%2B%2B@gcc.gnu.org>> wrote:
>
>         On 20/10/21 10:12 +0100, Jonathan Wakely wrote:
>         >On 19/10/21 17:47 +0100, Jonathan Wakely wrote:
>         >>The ISA-3.0 instruction set includes DARN ("deliver a random number")
>         >>which can be used similar to the existing support for RDRAND and RDSEED.
>         >>
>         >>libstdc++-v3/ChangeLog:
>         >>
>         >>      * src/c++11/random.cc (USE_DARN): Define.
>         >>      (__ppc_darn): New function to use POWER9 DARN instruction.
>         >>      (Which): Add 'darn' enumerator.
>         >>      (which_source): Check for __ppc_darn.
>         >>      (random_device::_M_init): Support "darn" and "hw" tokens.
>         >>      (random_device::_M_getentropy): Add darn to switch.
>         >>      * testsuite/26_numerics/random/random_device/cons/token.cc:
>         >>      Check "darn" token.
>         >>      * testsuite/26_numerics/random/random_device/entropy.cc:
>         >>      Likewise.
>         >>
>         >>Tested powerpc64le-linux (power8 and power9) and x86_64-linux.
>         >>
>         >>The new "darn" (power-specific) and "hw" (x86 and power)
>         >>strings should be documented, but I'll do that if this gets committed.
>         >>
>         >>Most of this patch is just "more of the same", similar to the existing
>         >>code for RDRAND and RDSEED on x86, but the parts of the patch I'd like
>         >>more eyes on are:
>         >>
>         >>
>         >>+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
>         >>+# define USE_DARN 1
>         >>#endif
>         >
>         >This means DARN can only be used when __builtin_cpu_supports is
>         >available, which means glibc 2.23 ... is that acceptable? It means
>         >RHEL 7 wouldn't be able to use DARN, but RHEL 8 would.
>         >
>         >There certainly are POWER9 machines running RHEL 7 and similar
>         >vintages (the GCC compile farm has one) so if there's another way to
>         >check for ISA 3.0 then I could use that.
>         >
>         >If __POWER9_VECTOR__ is defined when building libstdc++, presumably
>         >that means the whole library can only be run on POWER9 hardware. So
>         >would that mean we don't need to check __builtin_cpu_supports("darn")
>         >when __POWER9_VECTOR__ is defined? Or is it possible to build with
>         >-mcpu=power8 -mpower9-vector and run it on h/w without the DARN
>         >instruction?
>         >
>         >Also, I forgot to add a configure check that the assembler supports
>         >darn, which is another prerequisite for using it here.
>         >
>         >>@@ -135,6 +137,15 @@ namespace std _GLIBCXX_VISIBILITY(default)
>         >>#endif
>         >>#endif
>         >>
>         >>+#ifdef USE_DARN
>         >>+    unsigned int
>         >>+    __attribute__((target("power9")))
>         >
>         >Oops, that should be "cpu=power9".
>         >
>         >With that change it works on a POWER9 machine (9009-42A) with glibc
>         >2.34 and binutils 2.35.
>         >
>
>         Here's the updated patch with a configure check for assembler support,
>         and the target attribute fixed.
>
>         This still requires Glibc 2.23 for __builtin_cpu_supports, which I'm
>         assuming is acceptable.
>
>
>
>  

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-11-04 20:44         ` Bill Schmidt
@ 2021-11-05 12:44           ` Jonathan Wakely
  2021-11-05 13:20             ` Bill Schmidt
  0 siblings, 1 reply; 9+ messages in thread
From: Jonathan Wakely @ 2021-11-05 12:44 UTC (permalink / raw)
  To: Bill Schmidt; +Cc: libstdc++, gcc Patches, Segher Boessenkool

[-- Attachment #1: Type: text/plain, Size: 410 bytes --]

On Thu, 4 Nov 2021 at 20:44, Bill Schmidt wrote:

> For posterity:  This was discussed briefly on IRC, and Segher approved
> with some
> simplifications and a request to implement a fail/retry check.
>
>
Here's what I have now. No more assembler check in configure, and it uses
the 64-bit __builtin_darn() and truncates it to 32-bit, or retries (up to
100 times) if it fails.

I'm doing some more testing now.

[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 5598 bytes --]

commit 77816264712923481db37a29d1638faa1d99aadc
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Oct 20 09:25:24 2021

    libstdc++: Add support for POWER9 DARN instruction to std::random_device
    
    The ISA-3.0 instruction set includes DARN ("deliver a random number")
    which can be used similar to the existing support for RDRAND and RDSEED.
    
    libstdc++-v3/ChangeLog:
    
            * src/c++11/random.cc [__powerpc__] (USE_DARN): Define.
            (__ppc_darn): New function to use POWER9 DARN instruction.
            (Which): Add 'darn' enumerator.
            (which_source): Check for __ppc_darn.
            (random_device::_M_init): Support "darn" and "hw" tokens.
            (random_device::_M_getentropy): Add darn to switch.
            * testsuite/26_numerics/random/random_device/cons/token.cc:
            Check "darn" token.
            * testsuite/26_numerics/random/random_device/entropy.cc:
            Likewise.

diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc
index 4b64bde00ea..b0d88374d59 100644
--- a/libstdc++-v3/src/c++11/random.cc
+++ b/libstdc++-v3/src/c++11/random.cc
@@ -37,6 +37,8 @@
 # ifdef _GLIBCXX_X86_RDSEED
 #  define USE_RDSEED 1
 # endif
+#elif defined __powerpc__ && defined __BUILTIN_CPU_SUPPORTS__
+# define USE_DARN 1
 #endif
 
 #include <cerrno>
@@ -69,7 +71,7 @@
 #if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM
 // The OS provides a source of randomness we can use.
 # pragma GCC poison _M_mt
-#elif defined USE_RDRAND || defined USE_RDSEED
+#elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
 // Hardware instructions might be available, but use cpuid checks at runtime.
 # pragma GCC poison _M_mt
 // If the runtime cpuid checks fail we'll use a linear congruential engine.
@@ -135,6 +137,24 @@ namespace std _GLIBCXX_VISIBILITY(default)
 #endif
 #endif
 
+#ifdef USE_DARN
+    unsigned int
+    __attribute__((target("cpu=power9")))
+    __ppc_darn(void*)
+    {
+      const uint64_t failed = -1;
+      unsigned int retries = 100;
+      uint64_t val = __builtin_darn();
+      while (val == failed) [[__unlikely__]]
+	{
+	  if (--retries == 0)
+	    std::__throw_runtime_error(__N("random_device: darn failed"));
+	  val = __builtin_darn();
+	}
+      return (uint32_t)val;
+    }
+#endif
+
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     unsigned int
     __winxp_rand_s(void*)
@@ -193,11 +213,16 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif
 
-    enum Which {
-      rand_s = 1, rdseed = 2, rdrand = 4, device_file = 8, prng = 16,
+    enum Which : unsigned {
+      device_file = 1, prng = 2, rand_s = 4,
+      rdseed = 64, rdrand = 128, darn = 256,
       any = 0xffff
     };
 
+    constexpr Which
+    operator|(Which l, Which r) noexcept
+    { return Which(unsigned(l) | unsigned(r)); }
+
     inline Which
     which_source(random_device::result_type (*func [[maybe_unused]])(void*),
 		 void* file [[maybe_unused]])
@@ -221,6 +246,11 @@ namespace std _GLIBCXX_VISIBILITY(default)
 	return rdrand;
 #endif
 
+#ifdef USE_DARN
+      if (func == &__ppc_darn)
+	return darn;
+#endif
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
       if (file != nullptr)
 	return device_file;
@@ -269,6 +299,14 @@ namespace std _GLIBCXX_VISIBILITY(default)
     else if (token == "rdrand" || token == "rdrnd")
       which = rdrand;
 #endif // USE_RDRAND
+#ifdef USE_DARN
+    else if (token == "darn")
+      which = darn;
+#endif
+#if defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN
+    else if (token == "hw" || token == "hardware")
+      which = rdrand | rdseed | darn;
+#endif
 #ifdef _GLIBCXX_USE_CRT_RAND_S
     else if (token == "rand_s")
       which = rand_s;
@@ -346,6 +384,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
     }
 #endif // USE_RDRAND
 
+#ifdef USE_DARN
+    if (which & darn)
+      {
+	if (__builtin_cpu_supports("darn"))
+	  {
+	    _M_func = &__ppc_darn;
+	    return;
+	  }
+      }
+#endif // USE_DARN
+
 #ifdef _GLIBCXX_USE_DEV_RANDOM
     if (which & device_file)
     {
@@ -497,6 +546,7 @@ namespace std _GLIBCXX_VISIBILITY(default)
     {
     case rdrand:
     case rdseed:
+    case darn:
       return (double) max;
     case rand_s:
     case prng:
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
index aeb7403e830..d6ac3a37c64 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc
@@ -51,8 +51,9 @@ test03()
 {
   // At least one of these tokens should be valid.
   const std::string tokens[] = {
-    "rdseed", "rdrand", "rand_s", "/dev/urandom", "/dev/random", "mt19937",
-    "prng"
+    "rdseed", "rdrand", "darn",
+    "rand_s", "/dev/urandom", "/dev/random",
+    "mt19937", "prng"
   };
   int count = 0;
   for (const std::string& token : tokens)
diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
index 9ef1538d2bb..6f3ebb1b38e 100644
--- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
+++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc
@@ -22,7 +22,7 @@ test01()
       VERIFY( entropy <= max );
     }
 
-  for (auto token : { "rdrand", "rdseed" })
+  for (auto token : { "rdrand", "rdseed", "darn", "hw" })
     if (__gnu_test::random_device_available(token))
     {
       const double entropy = std::random_device(token).entropy();

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-11-05 12:44           ` Jonathan Wakely
@ 2021-11-05 13:20             ` Bill Schmidt
  2021-11-05 18:16               ` Jonathan Wakely
  0 siblings, 1 reply; 9+ messages in thread
From: Bill Schmidt @ 2021-11-05 13:20 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc Patches, Segher Boessenkool


On 11/5/21 7:44 AM, Jonathan Wakely wrote:
> On Thu, 4 Nov 2021 at 20:44, Bill Schmidt wrote: For posterity:  This was discussed briefly on IRC, and Segher approved with some simplifications and a request to implement a fail/retry check. Here's what I have now. No more assembler check 
> On Thu, 4 Nov 2021 at 20:44, Bill Schmidt wrote:
>
>     For posterity:  This was discussed briefly on IRC, and Segher approved with some
>     simplifications and a request to implement a fail/retry check.
>
>
> Here's what I have now. No more assembler check in configure, and it uses the 64-bit __builtin_darn() and truncates it to 32-bit, or retries (up to 100 times) if it fails.
>
> I'm doing some more testing now.
>
Those changes look good from my perspective.  Thanks again for this work!  (Not a maintainer, blah blah...)

Bill


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2] libstdc++: Add support for POWER9 DARN instruction to std::random_device
  2021-11-05 13:20             ` Bill Schmidt
@ 2021-11-05 18:16               ` Jonathan Wakely
  0 siblings, 0 replies; 9+ messages in thread
From: Jonathan Wakely @ 2021-11-05 18:16 UTC (permalink / raw)
  To: Bill Schmidt; +Cc: libstdc++, gcc Patches, Segher Boessenkool

On Fri, 5 Nov 2021 at 13:20, Bill Schmidt wrote:

>
> On 11/5/21 7:44 AM, Jonathan Wakely wrote:
> > On Thu, 4 Nov 2021 at 20:44, Bill Schmidt wrote: For posterity:  This
> was discussed briefly on IRC, and Segher approved with some simplifications
> and a request to implement a fail/retry check. Here's what I have now. No
> more assembler check
> > On Thu, 4 Nov 2021 at 20:44, Bill Schmidt wrote:
> >
> >     For posterity:  This was discussed briefly on IRC, and Segher
> approved with some
> >     simplifications and a request to implement a fail/retry check.
> >
> >
> > Here's what I have now. No more assembler check in configure, and it
> uses the 64-bit __builtin_darn() and truncates it to 32-bit, or retries (up
> to 100 times) if it fails.
> >
> > I'm doing some more testing now.
> >
> Those changes look good from my perspective.  Thanks again for this work!
> (Not a maintainer, blah blah...)
>

I changed the number of retries to 10 and pushed it to trunk.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2021-11-05 18:16 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-19 16:47 [PATCH] libstdc++: Add support for POWER9 DARN instruction to std::random_device Jonathan Wakely
2021-10-20  9:12 ` Jonathan Wakely
2021-10-20 13:00   ` [PATCH v2] " Jonathan Wakely
2021-11-03 15:01     ` Jonathan Wakely
2021-11-03 15:02       ` Jonathan Wakely
2021-11-04 20:44         ` Bill Schmidt
2021-11-05 12:44           ` Jonathan Wakely
2021-11-05 13:20             ` Bill Schmidt
2021-11-05 18:16               ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).