From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 5CB363858038 for ; Tue, 19 Oct 2021 16:47:30 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5CB363858038 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-162-VqmWIcmjPQKfAAypWVe48Q-1; Tue, 19 Oct 2021 12:47:24 -0400 X-MC-Unique: VqmWIcmjPQKfAAypWVe48Q-1 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 9262BA0CD0; Tue, 19 Oct 2021 16:47:23 +0000 (UTC) Received: from localhost (unknown [10.33.36.194]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2CAEC5DD68; Tue, 19 Oct 2021 16:47:22 +0000 (UTC) Date: Tue, 19 Oct 2021 17:47:22 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Bill Schmidt , Segher Boessenkool Subject: [PATCH] libstdc++: Add support for POWER9 DARN instruction to std::random_device Message-ID: MIME-Version: 1.0 X-Clacks-Overhead: GNU Terry Pratchett X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: multipart/mixed; boundary="Q060Ol97SBHJj+LN" Content-Disposition: inline X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=unavailable autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 19 Oct 2021 16:47:31 -0000 --Q060Ol97SBHJj+LN Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 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) { --Q060Ol97SBHJj+LN Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="patch.txt" commit 5cfef2d435b5cb3b3e959e14e4b1edde8edea473 Author: Jonathan Wakely 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 @@ -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(); --Q060Ol97SBHJj+LN--