Make qsimd.cpp also complain if required features are missing
authorThiago Macieira <thiago.macieira@intel.com>
Sat, 31 Dec 2011 02:16:13 +0000 (00:16 -0200)
committerQt by Nokia <qt-info@nokia.com>
Wed, 28 Mar 2012 20:32:40 +0000 (22:32 +0200)
Record in a variable the features that the compiler used for code
generation when Qt was compiled. Then complain if those are
missing. This is required in qdrawhelper_plain.cpp to make it disable
the plain build, keeping only the AVX, Neon or SSE2 builds. This code
works for GCC, ICC on Unix and Clang.

MSVC support is pending. It will involve defining the same macros
from qsimd_p.h when the compiler support is detected.

Other compilers are unknown. The only relevant one would be Sun Studio
for x86, but I have no access to it to find out what macros it
predefines.

Change-Id: I25f2d90b3c7ac7bd0442f4b349b6ee3bd751a95b
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/corelib/tools/qsimd.cpp

index 5f54ae7..7b05089 100644 (file)
@@ -342,7 +342,49 @@ static const int features_indices[] = {
 };
 // end generated
 
-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]);
+
+static const uint minFeature = None
+#if defined __RTM__
+                               | RTM
+#endif
+// don't define for HLE, since the HLE prefix can be run on older CPUs
+#if defined __AVX2__
+                               | AVX2
+#endif
+#if defined __AVX__
+                               | AVX
+#endif
+#if defined __SSE4_2__
+                               | SSE4_2
+#endif
+#if defined __SSE4_1__
+                               | SSE4_1
+#endif
+#if defined __SSSE3__
+                               | SSSE3
+#endif
+#if defined __SSE3__
+                               | SSE3
+#endif
+#if defined __SSE2__
+                               | SSE2
+#endif
+#if defined __ARM_NEON__
+                               | NEON
+#endif
+#if defined __IWMMXT__
+                               | IWMMXT
+#endif
+                               ;
+
+#ifdef Q_OS_WIN
+int ffs(int i)
+{
+    unsigned long result;
+    return _BitScanForward(&result, i) ? result : 0;
+}
+#endif
 
 uint qDetectCPUFeatures()
 {
@@ -360,6 +402,19 @@ uint qDetectCPUFeatures()
         }
     }
 
+    if (minFeature != 0 && (f & minFeature) != minFeature) {
+        uint 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))
+                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]);
+    }
+
     features.store(f);
     return f;
 }
@@ -370,7 +425,8 @@ void qDumpCPUFeatures()
     printf("Processor features: ");
     for (int i = 0; i < features_count; ++i) {
         if (features & (1 << i))
-            printf("%s", features_string + features_indices[i]);
+            printf("%s%s", features_string + features_indices[i],
+                   minFeature & (1 << i) ? "[required]" : "");
     }
     puts("");
 }