summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config.tests/x86_simd/main.cpp17
-rw-r--r--configure.json12
-rw-r--r--mkspecs/common/gcc-base.conf1
-rw-r--r--mkspecs/common/icc-base-unix.conf1
-rw-r--r--mkspecs/common/msvc-version.conf1
-rw-r--r--mkspecs/features/simd.prf1
-rw-r--r--mkspecs/win32-clang-msvc/qmake.conf1
-rw-r--r--src/corelib/tools/qsimd.cpp36
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