diff options
-rw-r--r-- | config.tests/x86_simd/main.cpp | 17 | ||||
-rw-r--r-- | configure.json | 12 | ||||
-rw-r--r-- | mkspecs/common/gcc-base.conf | 1 | ||||
-rw-r--r-- | mkspecs/common/icc-base-unix.conf | 1 | ||||
-rw-r--r-- | mkspecs/common/msvc-version.conf | 1 | ||||
-rw-r--r-- | mkspecs/features/simd.prf | 1 | ||||
-rw-r--r-- | mkspecs/win32-clang-msvc/qmake.conf | 1 | ||||
-rw-r--r-- | src/corelib/tools/qsimd.cpp | 36 |
8 files changed, 69 insertions, 1 deletions
diff --git a/config.tests/x86_simd/main.cpp b/config.tests/x86_simd/main.cpp index 4fac13973a..0e7ebed8d9 100644 --- a/config.tests/x86_simd/main.cpp +++ b/config.tests/x86_simd/main.cpp @@ -132,6 +132,23 @@ attribute_target("rdrnd") int test_rdrnd() } #endif +#if T(RDSEED) +attribute_target("rdseed") int test_rdseed() +{ + unsigned short us; + unsigned int ui; + if (_rdseed16_step(&us)) + return 1; + if (_rdseed32_step(&ui)) + return 1; +# if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) + unsigned long long ull; + if (_rdseed64_step(&ull)) + return 1; +# endif +} +#endif + #if T(SHANI) attribute_target("sha") void test_shani() { diff --git a/configure.json b/configure.json index 8ebb3c841f..ce71e67993 100644 --- a/configure.json +++ b/configure.json @@ -527,6 +527,10 @@ "label": "RDRAND instruction", "type": "x86Simd" }, + "rdseed": { + "label": "RDSEED instruction", + "type": "x86Simd" + }, "shani": { "label": "SHA new instructions", "type": "x86Simd" @@ -1181,6 +1185,14 @@ { "type": "define", "name": "QT_COMPILER_SUPPORTS_RDRND", "value": 1 } ] }, + "rdseed": { + "label": "RDSEED", + "condition": "tests.rdseed", + "output": [ + "privateConfig", + { "type": "define", "name": "QT_COMPILER_SUPPORTS_RDSEED", "value": 1 } + ] + }, "shani": { "label": "SHA", "condition": "features.sse2 && tests.shani", diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index 4d82321cba..472333d2ea 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -93,6 +93,7 @@ QMAKE_CFLAGS_SSE4_1 += -msse4.1 QMAKE_CFLAGS_SSE4_2 += -msse4.2 QMAKE_CFLAGS_F16C += -mf16c QMAKE_CFLAGS_RDRND += -mrdrnd +QMAKE_CFLAGS_RDSEED += -mrdseed QMAKE_CFLAGS_AVX += -mavx QMAKE_CFLAGS_AVX2 += -mavx2 QMAKE_CFLAGS_AVX512F += -mavx512f diff --git a/mkspecs/common/icc-base-unix.conf b/mkspecs/common/icc-base-unix.conf index 54eda984b7..e0bb55577e 100644 --- a/mkspecs/common/icc-base-unix.conf +++ b/mkspecs/common/icc-base-unix.conf @@ -51,6 +51,7 @@ QMAKE_CFLAGS_AVX512VL += -march=skylake-avx512 QMAKE_CFLAGS_AESNI += -maes QMAKE_CFLAGS_F16C += $$QMAKE_CFLAGS_AVX2 QMAKE_CFLAGS_RDRND += -mrdrnd +QMAKE_CFLAGS_RDSEED += -mrdseed QMAKE_CFLAGS_SHANI += -msha QMAKE_CXX = icpc diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf index af33132077..adb45582c7 100644 --- a/mkspecs/common/msvc-version.conf +++ b/mkspecs/common/msvc-version.conf @@ -50,6 +50,7 @@ greaterThan(QMAKE_MSC_VER, 1799) { QMAKE_CFLAGS_F16C = -arch:AVX QMAKE_CFLAGS_RDRND = + QMAKE_CFLAGS_RDSEED = equals(QMAKE_MSC_VER, 1800) { QMAKE_CFLAGS_RELEASE += -Zc:strictStrings diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf index a0b40fcf11..3918c4fe73 100644 --- a/mkspecs/features/simd.prf +++ b/mkspecs/features/simd.prf @@ -137,6 +137,7 @@ addSimdCompiler(avx512ifma) addSimdCompiler(avx512vbmi) addSimdCompiler(f16c) addSimdCompiler(rdrnd) +addSimdCompiler(rdseed) addSimdCompiler(neon) addSimdCompiler(mips_dsp) addSimdCompiler(mips_dspr2) diff --git a/mkspecs/win32-clang-msvc/qmake.conf b/mkspecs/win32-clang-msvc/qmake.conf index 238e401b84..be7cdaa396 100644 --- a/mkspecs/win32-clang-msvc/qmake.conf +++ b/mkspecs/win32-clang-msvc/qmake.conf @@ -15,6 +15,7 @@ QMAKE_CFLAGS_AVX = -mavx QMAKE_CFLAGS_AVX2 = -mavx2 QMAKE_CFLAGS_F16C = -mf16c QMAKE_CFLAGS_RDRND = -mrdrnd +QMAKE_CFLAGS_RDSEED = -mrdseed QMAKE_CFLAGS_AVX512F = -mavx512f QMAKE_CFLAGS_AVX512ER = -mavx512er QMAKE_CFLAGS_AVX512CD = -mavx512cd diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index fb9b5996f6..6e3b0f9faf 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -626,8 +626,40 @@ void qDumpCPUFeatures() # ifdef Q_PROCESSOR_X86_64 # define _rdrandXX_step _rdrand64_step +# define _rdseedXX_step _rdseed64_step # else # define _rdrandXX_step _rdrand32_step +# define _rdseedXX_step _rdseed32_step +# endif + +# if QT_COMPILER_SUPPORTS_HERE(RDSEED) +static QT_FUNCTION_TARGET(RDSEED) unsigned *qt_random_rdseed(unsigned *ptr, unsigned *end) noexcept +{ + // Unlike for the RDRAND code below, the Intel whitepaper describing the + // use of the RDSEED instruction indicates we should not retry in a loop. + // If the independent bit generator used by RDSEED is out of entropy, it + // may take time to replenish. + // https://software.intel.com/en-us/articles/intel-digital-random-number-generator-drng-software-implementation-guide + while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { + if (_rdseedXX_step(reinterpret_cast<qregisteruint *>(ptr)) == 0) + goto out; + ptr += sizeof(qregisteruint)/sizeof(*ptr); + } + + if (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) { + if (_rdseed32_step(ptr) == 0) + goto out; + ++ptr; + } + +out: + return ptr; +} +# else +static unsigned *qt_random_rdseed(unsigned *ptr, unsigned *) +{ + return ptr; +} # endif QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) noexcept @@ -636,6 +668,9 @@ QT_FUNCTION_TARGET(RDRND) qsizetype qRandomCpu(void *buffer, qsizetype count) no unsigned *end = ptr + count; int retries = 10; + if (qCpuHasFeature(RDSEED)) + ptr = qt_random_rdseed(ptr, end); + while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) { if (_rdrandXX_step(reinterpret_cast<qregisteruint *>(ptr))) ptr += sizeof(qregisteruint)/sizeof(*ptr); @@ -657,5 +692,4 @@ out: } #endif - QT_END_NAMESPACE |