Disable CPUID checking with GCC 4.2 or older
authorThiago Macieira <thiago.macieira@intel.com>
Tue, 14 Aug 2012 12:07:31 +0000 (14:07 +0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 15 Aug 2012 13:20:39 +0000 (15:20 +0200)
This is not the first time that GCC 4.2 on Mac has produced bad code
surrounding the CPUID instruction (see also commit 81d1f79a7f4b0f67d71).
So declare it broken beyond repair and don't run the instruction at all.

Instead, initialise the set of features found to be exactly that which
we detected at compile-time. For that reason, we can also disable the
runtime checking of the processor (minFeatures == detected features).

At the time of this commit, only the draw helpers and one QImage
helper make use of the runtime detection. Since the detection now
switches to compile-time, QtGui will start carrying dead code for GCC
4.2 and earlier: it will never run the SSE2/SSSE3 code on 32-bit
builds. (GCC 4.2 does not support AVX, so that code won't be built)

Note: all Clang versions report that they are GCC 4.2, so we need to
exclude it from the test; ICC reports the same version as the system's
GCC.

Change-Id: I43f168a9480a2479c6444eea175782b2eadc2ab2
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
src/corelib/tools/qsimd.cpp

index df41e6b..244ed2e 100644 (file)
@@ -379,6 +379,28 @@ QBasicAtomicInt qt_cpu_features = Q_BASIC_ATOMIC_INITIALIZER(0);
 
 void qDetectCpuFeatures()
 {
+#if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL)
+# if (__GNUC__ * 100 + __GNUC_MINOR__) < 403
+    // GCC 4.2 (at least the one that comes with Apple's XCode, on Mac) is
+    // known to be broken beyond repair in dealing with the inline assembly
+    // above. It will generate bad code that could corrupt important registers
+    // like the PIC register. The behaviour of code after this function would
+    // be totally unpredictable.
+    //
+    // For that reason, simply forego the CPUID check at all and return the set
+    // of features that we found at compile time, through the #defines from the
+    // compiler. This should at least allow code to execute, even if none of
+    // the specialised code found in QtGui and elsewhere will ever be enabled
+    // (it's the user's fault for using a broken compiler).
+    //
+    // This also disables the runtime checking that the processor actually
+    // 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);
+    return;
+# endif
+#endif
     uint f = detectProcessorFeatures();
     QByteArray disable = qgetenv("QT_NO_CPU_FEATURE");
     if (!disable.isEmpty()) {