From 15b42af11123f9d1eb4bbd79870185585103ea8d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 17 Jul 2015 12:50:56 -0700 Subject: Change the CPU feature status word to be 64-bit instead of 32-bit I'm going to need the extra bits for x86. Change-Id: Ib306f8f647014b399b87ffff13f1d3d23e138518 Reviewed-by: Oswald Buddenhagen Reviewed-by: Allan Sandfeld Jensen --- src/corelib/tools/qsimd.cpp | 51 +++++++++++++++++++++++++++------------------ src/corelib/tools/qsimd_p.h | 20 +++++++++++++----- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index e7917ffdac..91700c053d 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -240,7 +240,7 @@ static void xgetbv(uint in, uint &eax, uint &edx) #endif } -static inline uint detectProcessorFeatures() +static quint64 detectProcessorFeatures() { // Flags from the CR0 / XCR0 state register enum XCR0Flags { @@ -258,7 +258,7 @@ static inline uint detectProcessorFeatures() AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 }; - uint features = 0; + quint64 features = 0; int cpuidLevel = maxBasicCpuidSupported(); #if Q_PROCESSOR_X86 < 5 if (cpuidLevel < 1) @@ -505,27 +505,35 @@ static const int features_indices[] = { static const int features_count = (sizeof features_indices - 1) / (sizeof features_indices[0]); // record what CPU features were enabled by default in this Qt build -static const uint minFeature = qCompilerCpuFeatures; +static const quint64 minFeature = qCompilerCpuFeatures; #ifdef Q_OS_WIN #if defined(Q_CC_GNU) -# define ffs __builtin_ffs +# define ffsll __builtin_ffsll #else -int ffs(int i) +int ffsll(quint64 i) { -#ifndef Q_OS_WINCE +#if defined(Q_OS_WIN64) + unsigned long result; + return _BitScanForward64(&result, i) ? result : 0; +#elif !defined(Q_OS_WINCE) unsigned long result; - return _BitScanForward(&result, i) ? result : 0; + return _BitScanForward(&result, i) ? result : + _BitScanForward(&result, i >> 32) ? result + 32 : 0; #else return 0; #endif } #endif -#elif defined(Q_OS_ANDROID) -# define ffs __builtin_ffs +#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) +# define ffsll __builtin_ffsll #endif -QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0); +#ifdef Q_ATOMIC_INT64_IS_SUPPORTED +Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) }; +#else +Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) }; +#endif void qDetectCpuFeatures() { @@ -547,11 +555,11 @@ void qDetectCpuFeatures() // contains all the features that the code required. Qt 4 ran for years // like that, so it shouldn't be a problem. - qt_cpu_features.store(minFeature | QSimdInitialized); + qt_cpu_features.store(minFeature | quint32(QSimdInitialized)); return; # endif #endif - uint f = detectProcessorFeatures(); + quint64 f = detectProcessorFeatures(); QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); if (!disable.isEmpty()) { disable.prepend(' '); @@ -567,29 +575,32 @@ void qDetectCpuFeatures() bool runningOnValgrind = false; #endif if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) { - uint missing = minFeature & ~f; + quint64 missing = minFeature & ~f; fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n "); for (int i = 0; i < features_count; ++i) { - if (missing & (1 << i)) + if (missing & (Q_UINT64_C(1) << i)) fprintf(stderr, "%s", features_string + features_indices[i]); } fprintf(stderr, "\n"); fflush(stderr); - qFatal("Aborted. Incompatible processor: missing feature 0x%x -%s.", missing, - features_string + features_indices[ffs(missing) - 1]); + qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing, + features_string + features_indices[ffsll(missing) - 1]); } - qt_cpu_features.store(f | QSimdInitialized); + qt_cpu_features[0].store(f | quint32(QSimdInitialized)); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + qt_cpu_features[1].store(f >> 32); +#endif } void qDumpCPUFeatures() { - uint features = qCpuFeatures(); + quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized); printf("Processor features: "); for (int i = 0; i < features_count; ++i) { - if (features & (1 << i)) + if (features & (Q_UINT64_C(1) << i)) printf("%s%s", features_string + features_indices[i], - minFeature & (1 << i) ? "[required]" : ""); + minFeature & (Q_UINT64_C(1) << i) ? "[required]" : ""); } puts(""); } diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 8523fb09c1..6ca3836ca9 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -298,18 +298,28 @@ static const uint qCompilerCpuFeatures = 0 #endif ; -extern Q_CORE_EXPORT QBasicAtomicInt qt_cpu_features; +#ifdef Q_ATOMIC_INT64_IS_SUPPORTED +extern Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[1]; +#else +extern Q_CORE_EXPORT QBasicAtomicInteger qt_cpu_features[2]; +#endif Q_CORE_EXPORT void qDetectCpuFeatures(); -static inline uint qCpuFeatures() +static inline quint64 qCpuFeatures() { - int features = qt_cpu_features.load(); + quint64 features = qt_cpu_features[0].load(); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + features |= quint64(qt_cpu_features[1].load()) << 32; +#endif if (Q_UNLIKELY(features == 0)) { qDetectCpuFeatures(); - features = qt_cpu_features.load(); + features = qt_cpu_features[0].load(); +#ifndef Q_ATOMIC_INT64_IS_SUPPORTED + features |= quint64(qt_cpu_features[1].load()) << 32; +#endif Q_ASSUME(features != 0); } - return uint(features); + return features; } #define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature))) -- cgit v1.2.3