mirror of
https://github.com/memtest86plus/memtest86plus.git
synced 2026-08-04 10:23:17 -05:00
Invert the PRSG xorshift stages by repeated squaring (~25% faster)
This commit is contained in:
committed by
Sam Demeulemeester
parent
72d08688ba
commit
80717a1c5b
+10
-16
@@ -52,30 +52,24 @@ static const testword_t lane_salt[VEC_LANES] = {
|
||||
// Private Functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Inverts one y = x ^ (x << shift) step of the xorshift generator.
|
||||
// Inverts one y = x ^ (x << shift) step of the xorshift generator by repeated
|
||||
// squaring, doubling the shift until it exceeds the word width.
|
||||
static inline testword_t prsg_undo_lshift(testword_t y, int shift)
|
||||
{
|
||||
testword_t x = y;
|
||||
testword_t t = y;
|
||||
|
||||
for (int k = shift; k < TESTWORD_WIDTH; k += shift) {
|
||||
t <<= shift;
|
||||
x ^= t;
|
||||
for (int k = shift; k < TESTWORD_WIDTH; k *= 2) {
|
||||
y ^= y << k;
|
||||
}
|
||||
return x;
|
||||
return y;
|
||||
}
|
||||
|
||||
// Inverts one y = x ^ (x >> shift) step of the xorshift generator.
|
||||
// Inverts one y = x ^ (x >> shift) step of the xorshift generator by repeated
|
||||
// squaring, doubling the shift until it exceeds the word width.
|
||||
static inline testword_t prsg_undo_rshift(testword_t y, int shift)
|
||||
{
|
||||
testword_t x = y;
|
||||
testword_t t = y;
|
||||
|
||||
for (int k = shift; k < TESTWORD_WIDTH; k += shift) {
|
||||
t >>= shift;
|
||||
x ^= t;
|
||||
for (int k = shift; k < TESTWORD_WIDTH; k *= 2) {
|
||||
y ^= y >> k;
|
||||
}
|
||||
return x;
|
||||
return y;
|
||||
}
|
||||
|
||||
// Returns the previous word in the pseudo-random sequence generated by prsg().
|
||||
|
||||
+21
-11
@@ -10,8 +10,9 @@
|
||||
// vzeroupper itself before returning to legacy SSE code.
|
||||
//
|
||||
// Forward xorshift: x ^= x << 13; x ^= x >> 7; x ^= x << 17;
|
||||
// The backward step inverts each stage in reverse order, using the identity
|
||||
// that y = x ^ (x << s) is undone by x = y ^ (y << s) ^ (y << 2s) ^ ...
|
||||
// The backward step inverts each stage in reverse order by repeated squaring:
|
||||
// y = x ^ (x << s) is undone by x = y; x ^= x << s; x ^= x << 2s; x ^= x << 4s;
|
||||
// ... doubling the shift until it exceeds the word width.
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
@@ -20,6 +21,13 @@
|
||||
|
||||
#include "vec_prsg.h"
|
||||
|
||||
// The kernels end with vzeroupper, which zeroes the upper half of ALL ymm
|
||||
// registers, not just those in the clobber lists. This is only safe because
|
||||
// the compiler cannot hold values there when AVX code generation is disabled.
|
||||
#ifdef __AVX__
|
||||
#error "vec_prsg_avx2.c must be compiled without -mavx*"
|
||||
#endif
|
||||
|
||||
#define AVX2_STEP_FWD(s, t) \
|
||||
"vpsllq $13, " s ", " t " \n\t" \
|
||||
"vpxor " t ", " s ", " s " \n\t" \
|
||||
@@ -28,18 +36,20 @@
|
||||
"vpsllq $17, " s ", " t " \n\t" \
|
||||
"vpxor " t ", " s ", " s " \n\t"
|
||||
|
||||
#define AVX2_UNDO_SHIFT(s, t, op, shift, terms) \
|
||||
#define AVX2_UNDO_STEP(s, t, op, shift) \
|
||||
op " $" #shift ", " s ", " t " \n\t" \
|
||||
"vpxor " t ", " s ", " s " \n\t" \
|
||||
".rept " #terms " \n\t" \
|
||||
op " $" #shift ", " t ", " t " \n\t" \
|
||||
"vpxor " t ", " s ", " s " \n\t" \
|
||||
".endr \n\t"
|
||||
"vpxor " t ", " s ", " s " \n\t"
|
||||
|
||||
#define AVX2_STEP_BACK(s, t) \
|
||||
AVX2_UNDO_SHIFT(s, t, "vpsllq", 17, 2) \
|
||||
AVX2_UNDO_SHIFT(s, t, "vpsrlq", 7, 8) \
|
||||
AVX2_UNDO_SHIFT(s, t, "vpsllq", 13, 3)
|
||||
AVX2_UNDO_STEP(s, t, "vpsllq", 17) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsllq", 34) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsrlq", 7) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsrlq", 14) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsrlq", 28) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsrlq", 56) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsllq", 13) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsllq", 26) \
|
||||
AVX2_UNDO_STEP(s, t, "vpsllq", 52)
|
||||
|
||||
void vec_fill_avx2(vec_state_t *st, testword_t *p, size_t nblocks, bool splat)
|
||||
{
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
// SIMD support and no intrinsics headers are required.
|
||||
//
|
||||
// Forward xorshift: x ^= x << 13; x ^= x >> 7; x ^= x << 17;
|
||||
// The backward step inverts each stage in reverse order, using the identity
|
||||
// that y = x ^ (x << s) is undone by x = y ^ (y << s) ^ (y << 2s) ^ ...
|
||||
// The backward step inverts each stage in reverse order by repeated squaring:
|
||||
// y = x ^ (x << s) is undone by x = y; x ^= x << s; x ^= x << 2s; x ^= x << 4s;
|
||||
// ... doubling the shift until it exceeds the word width.
|
||||
|
||||
#if defined(__x86_64__)
|
||||
|
||||
@@ -30,17 +31,21 @@
|
||||
"psllq $17, " t " \n\t" \
|
||||
"pxor " t ", " s " \n\t"
|
||||
|
||||
#define SSE2_UNDO_SHIFT(s, t, op, shift, terms) \
|
||||
#define SSE2_UNDO_STEP(s, t, op, shift) \
|
||||
"movdqa " s ", " t " \n\t" \
|
||||
".rept " #terms " \n\t" \
|
||||
op " $" #shift ", " t " \n\t" \
|
||||
"pxor " t ", " s " \n\t" \
|
||||
".endr \n\t"
|
||||
"pxor " t ", " s " \n\t"
|
||||
|
||||
#define SSE2_STEP_BACK(s, t) \
|
||||
SSE2_UNDO_SHIFT(s, t, "psllq", 17, 3) \
|
||||
SSE2_UNDO_SHIFT(s, t, "psrlq", 7, 9) \
|
||||
SSE2_UNDO_SHIFT(s, t, "psllq", 13, 4)
|
||||
SSE2_UNDO_STEP(s, t, "psllq", 17) \
|
||||
SSE2_UNDO_STEP(s, t, "psllq", 34) \
|
||||
SSE2_UNDO_STEP(s, t, "psrlq", 7) \
|
||||
SSE2_UNDO_STEP(s, t, "psrlq", 14) \
|
||||
SSE2_UNDO_STEP(s, t, "psrlq", 28) \
|
||||
SSE2_UNDO_STEP(s, t, "psrlq", 56) \
|
||||
SSE2_UNDO_STEP(s, t, "psllq", 13) \
|
||||
SSE2_UNDO_STEP(s, t, "psllq", 26) \
|
||||
SSE2_UNDO_STEP(s, t, "psllq", 52)
|
||||
|
||||
void vec_fill_sse2(vec_state_t *st, testword_t *p, size_t nblocks, bool splat)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user