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 <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
This commit is contained in:
Thiago Macieira 2015-07-17 12:50:56 -07:00 committed by Allan Sandfeld Jensen
parent b2ca127ec4
commit 15b42af111
2 changed files with 46 additions and 25 deletions

View File

@ -240,7 +240,7 @@ static void xgetbv(uint in, uint &eax, uint &edx)
#endif #endif
} }
static inline uint detectProcessorFeatures() static quint64 detectProcessorFeatures()
{ {
// Flags from the CR0 / XCR0 state register // Flags from the CR0 / XCR0 state register
enum XCR0Flags { enum XCR0Flags {
@ -258,7 +258,7 @@ static inline uint detectProcessorFeatures()
AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31
}; };
uint features = 0; quint64 features = 0;
int cpuidLevel = maxBasicCpuidSupported(); int cpuidLevel = maxBasicCpuidSupported();
#if Q_PROCESSOR_X86 < 5 #if Q_PROCESSOR_X86 < 5
if (cpuidLevel < 1) 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]); 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 // 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 #ifdef Q_OS_WIN
#if defined(Q_CC_GNU) #if defined(Q_CC_GNU)
# define ffs __builtin_ffs # define ffsll __builtin_ffsll
#else #else
int ffs(int i) int ffsll(quint64 i)
{ {
#ifndef Q_OS_WINCE #if defined(Q_OS_WIN64)
unsigned long result; unsigned long result;
return _BitScanForward(&result, i) ? result : 0; return _BitScanForward64(&result, i) ? result : 0;
#elif !defined(Q_OS_WINCE)
unsigned long result;
return _BitScanForward(&result, i) ? result :
_BitScanForward(&result, i >> 32) ? result + 32 : 0;
#else #else
return 0; return 0;
#endif #endif
} }
#endif #endif
#elif defined(Q_OS_ANDROID) #elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX)
# define ffs __builtin_ffs # define ffsll __builtin_ffsll
#endif #endif
QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0); #ifdef Q_ATOMIC_INT64_IS_SUPPORTED
Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) };
#else
Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) };
#endif
void qDetectCpuFeatures() void qDetectCpuFeatures()
{ {
@ -547,11 +555,11 @@ void qDetectCpuFeatures()
// contains all the features that the code required. Qt 4 ran for years // contains all the features that the code required. Qt 4 ran for years
// like that, so it shouldn't be a problem. // like that, so it shouldn't be a problem.
qt_cpu_features.store(minFeature | QSimdInitialized); qt_cpu_features.store(minFeature | quint32(QSimdInitialized));
return; return;
# endif # endif
#endif #endif
uint f = detectProcessorFeatures(); quint64 f = detectProcessorFeatures();
QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); QByteArray disable = qgetenv("QT_NO_CPU_FEATURE");
if (!disable.isEmpty()) { if (!disable.isEmpty()) {
disable.prepend(' '); disable.prepend(' ');
@ -567,29 +575,32 @@ void qDetectCpuFeatures()
bool runningOnValgrind = false; bool runningOnValgrind = false;
#endif #endif
if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) { 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 "); fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n ");
for (int i = 0; i < features_count; ++i) { 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, "%s", features_string + features_indices[i]);
} }
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fflush(stderr); fflush(stderr);
qFatal("Aborted. Incompatible processor: missing feature 0x%x -%s.", missing, qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing,
features_string + features_indices[ffs(missing) - 1]); 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() void qDumpCPUFeatures()
{ {
uint features = qCpuFeatures(); quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized);
printf("Processor features: "); printf("Processor features: ");
for (int i = 0; i < features_count; ++i) { 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], printf("%s%s", features_string + features_indices[i],
minFeature & (1 << i) ? "[required]" : ""); minFeature & (Q_UINT64_C(1) << i) ? "[required]" : "");
} }
puts(""); puts("");
} }

View File

@ -298,18 +298,28 @@ static const uint qCompilerCpuFeatures = 0
#endif #endif
; ;
extern Q_CORE_EXPORT QBasicAtomicInt qt_cpu_features; #ifdef Q_ATOMIC_INT64_IS_SUPPORTED
extern Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1];
#else
extern Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2];
#endif
Q_CORE_EXPORT void qDetectCpuFeatures(); 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)) { if (Q_UNLIKELY(features == 0)) {
qDetectCpuFeatures(); 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); Q_ASSUME(features != 0);
} }
return uint(features); return features;
} }
#define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature))) #define qCpuHasFeature(feature) ((qCompilerCpuFeatures & (feature)) || (qCpuFeatures() & (feature)))