aboutsummaryrefslogtreecommitdiff
path: root/libc/src
diff options
context:
space:
mode:
authorMikhail R. Gadelha <mikhail@igalia.com>2024-07-17 17:01:26 +0200
committerGitHub <noreply@github.com>2024-07-17 12:01:26 -0300
commit5d42d69d936bc3f29e849aac33d331b198143145 (patch)
tree4cfe2b8662b8eb4e76099aadd933bb213b98fa67 /libc/src
parenta56e009ef852926c8e77eb8e50739d2b5a389212 (diff)
downloadllvm-5d42d69d936bc3f29e849aac33d331b198143145.zip
llvm-5d42d69d936bc3f29e849aac33d331b198143145.tar.gz
llvm-5d42d69d936bc3f29e849aac33d331b198143145.tar.bz2
[libc] Change rand implementation so all tests pass in both 32- and 64-bit systems (#98692)
This patch makes rand select different algorithms depending on the arch. This is needed to avoid a test failure in 32-bit systems where the LSB of rand was not uniform enough when the 64-bit constants are used in 32-bit systems.
Diffstat (limited to 'libc/src')
-rw-r--r--libc/src/stdlib/rand.cpp41
1 files changed, 30 insertions, 11 deletions
diff --git a/libc/src/stdlib/rand.cpp b/libc/src/stdlib/rand.cpp
index 1931727e..a8a4fab 100644
--- a/libc/src/stdlib/rand.cpp
+++ b/libc/src/stdlib/rand.cpp
@@ -14,20 +14,39 @@
namespace LIBC_NAMESPACE_DECL {
-// An implementation of the xorshift64star pseudo random number generator. This
-// is a good general purpose generator for most non-cryptographics applications.
LLVM_LIBC_FUNCTION(int, rand, (void)) {
unsigned long orig = rand_next.load(cpp::MemoryOrder::RELAXED);
- for (;;) {
- unsigned long x = orig;
- x ^= x >> 12;
- x ^= x << 25;
- x ^= x >> 27;
- if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
- cpp::MemoryOrder::RELAXED))
- return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
- sleep_briefly();
+
+ // An implementation of the xorshift64star pseudo random number generator.
+ // This is a good general purpose generator for most non-cryptographics
+ // applications.
+ if constexpr (sizeof(void *) == sizeof(uint64_t)) {
+ for (;;) {
+ unsigned long x = orig;
+ x ^= x >> 12;
+ x ^= x << 25;
+ x ^= x >> 27;
+ if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
+ cpp::MemoryOrder::RELAXED))
+ return static_cast<int>((x * 0x2545F4914F6CDD1Dul) >> 32) & RAND_MAX;
+ sleep_briefly();
+ }
+ } else {
+ // This is the xorshift32 pseudo random number generator, slightly different
+ // from the 64-bit star version above, as the previous version fails to
+ // generate uniform enough LSB in 32-bit systems.
+ for (;;) {
+ unsigned long x = orig;
+ x ^= x >> 13;
+ x ^= x << 27;
+ x ^= x >> 5;
+ if (rand_next.compare_exchange_strong(orig, x, cpp::MemoryOrder::ACQUIRE,
+ cpp::MemoryOrder::RELAXED))
+ return static_cast<int>(x * 1597334677ul) & RAND_MAX;
+ sleep_briefly();
+ }
}
+ __builtin_unreachable();
}
} // namespace LIBC_NAMESPACE_DECL