| Absolute File Name: | /home/qt/qt5_coco/qt5/qtbase/src/corelib/tools/qsimd.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||||||||||||||
| 2 | ** | - | ||||||||||||||||||
| 3 | ** Copyright (C) 2015 The Qt Company Ltd. | - | ||||||||||||||||||
| 4 | ** Copyright (C) 2012 Intel Corporation. | - | ||||||||||||||||||
| 5 | ** Contact: http://www.qt.io/licensing/ | - | ||||||||||||||||||
| 6 | ** | - | ||||||||||||||||||
| 7 | ** This file is part of the QtCore module of the Qt Toolkit. | - | ||||||||||||||||||
| 8 | ** | - | ||||||||||||||||||
| 9 | ** $QT_BEGIN_LICENSE:LGPL21$ | - | ||||||||||||||||||
| 10 | ** Commercial License Usage | - | ||||||||||||||||||
| 11 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||||||||
| 12 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||||||||
| 13 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||||||||
| 14 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||||||||
| 15 | ** and conditions see http://www.qt.io/terms-conditions. For further | - | ||||||||||||||||||
| 16 | ** information use the contact form at http://www.qt.io/contact-us. | - | ||||||||||||||||||
| 17 | ** | - | ||||||||||||||||||
| 18 | ** GNU Lesser General Public License Usage | - | ||||||||||||||||||
| 19 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||||||||
| 20 | ** General Public License version 2.1 or version 3 as published by the Free | - | ||||||||||||||||||
| 21 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | - | ||||||||||||||||||
| 22 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the | - | ||||||||||||||||||
| 23 | ** following information to ensure the GNU Lesser General Public License | - | ||||||||||||||||||
| 24 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and | - | ||||||||||||||||||
| 25 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | - | ||||||||||||||||||
| 26 | ** | - | ||||||||||||||||||
| 27 | ** As a special exception, The Qt Company gives you certain additional | - | ||||||||||||||||||
| 28 | ** rights. These rights are described in The Qt Company LGPL Exception | - | ||||||||||||||||||
| 29 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | - | ||||||||||||||||||
| 30 | ** | - | ||||||||||||||||||
| 31 | ** $QT_END_LICENSE$ | - | ||||||||||||||||||
| 32 | ** | - | ||||||||||||||||||
| 33 | ****************************************************************************/ | - | ||||||||||||||||||
| 34 | - | |||||||||||||||||||
| 35 | #include "qsimd_p.h" | - | ||||||||||||||||||
| 36 | #include <QByteArray> | - | ||||||||||||||||||
| 37 | #include <stdio.h> | - | ||||||||||||||||||
| 38 | - | |||||||||||||||||||
| 39 | #ifdef Q_OS_LINUX | - | ||||||||||||||||||
| 40 | # include "../testlib/3rdparty/valgrind_p.h" | - | ||||||||||||||||||
| 41 | #endif | - | ||||||||||||||||||
| 42 | - | |||||||||||||||||||
| 43 | #if defined(Q_OS_WIN) | - | ||||||||||||||||||
| 44 | # if defined(Q_OS_WINCE) | - | ||||||||||||||||||
| 45 | # include <qt_windows.h> | - | ||||||||||||||||||
| 46 | # if _WIN32_WCE < 0x800 | - | ||||||||||||||||||
| 47 | # include <cmnintrin.h> | - | ||||||||||||||||||
| 48 | # endif | - | ||||||||||||||||||
| 49 | # endif | - | ||||||||||||||||||
| 50 | # if !defined(Q_CC_GNU) | - | ||||||||||||||||||
| 51 | # ifndef Q_OS_WINCE | - | ||||||||||||||||||
| 52 | # include <intrin.h> | - | ||||||||||||||||||
| 53 | # endif | - | ||||||||||||||||||
| 54 | # endif | - | ||||||||||||||||||
| 55 | #elif defined(Q_OS_LINUX) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_MIPS_32)) | - | ||||||||||||||||||
| 56 | #include "private/qcore_unix_p.h" | - | ||||||||||||||||||
| 57 | - | |||||||||||||||||||
| 58 | // the kernel header definitions for HWCAP_* | - | ||||||||||||||||||
| 59 | // (the ones we need/may need anyway) | - | ||||||||||||||||||
| 60 | - | |||||||||||||||||||
| 61 | // copied from <asm/hwcap.h> (ARM) | - | ||||||||||||||||||
| 62 | #define HWCAP_CRUNCH 1024 | - | ||||||||||||||||||
| 63 | #define HWCAP_THUMBEE 2048 | - | ||||||||||||||||||
| 64 | #define HWCAP_NEON 4096 | - | ||||||||||||||||||
| 65 | #define HWCAP_VFPv3 8192 | - | ||||||||||||||||||
| 66 | #define HWCAP_VFPv3D16 16384 | - | ||||||||||||||||||
| 67 | - | |||||||||||||||||||
| 68 | // copied from <linux/auxvec.h> | - | ||||||||||||||||||
| 69 | #define AT_HWCAP 16 /* arch dependent hints at CPU capabilities */ | - | ||||||||||||||||||
| 70 | - | |||||||||||||||||||
| 71 | #endif | - | ||||||||||||||||||
| 72 | - | |||||||||||||||||||
| 73 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||
| 74 | - | |||||||||||||||||||
| 75 | #if defined (Q_OS_NACL) | - | ||||||||||||||||||
| 76 | static inline uint detectProcessorFeatures() | - | ||||||||||||||||||
| 77 | { | - | ||||||||||||||||||
| 78 | return 0; | - | ||||||||||||||||||
| 79 | } | - | ||||||||||||||||||
| 80 | #elif defined (Q_OS_WINCE) | - | ||||||||||||||||||
| 81 | static inline quint64 detectProcessorFeatures() | - | ||||||||||||||||||
| 82 | { | - | ||||||||||||||||||
| 83 | quint64 features = 0; | - | ||||||||||||||||||
| 84 | - | |||||||||||||||||||
| 85 | #if defined (ARM) | - | ||||||||||||||||||
| 86 | # ifdef PF_ARM_NEON | - | ||||||||||||||||||
| 87 | if (IsProcessorFeaturePresent(PF_ARM_NEON)) | - | ||||||||||||||||||
| 88 | features |= Q_UINT64_C(1) << CpuFeatureNEON; | - | ||||||||||||||||||
| 89 | # endif | - | ||||||||||||||||||
| 90 | #elif defined(_X86_) | - | ||||||||||||||||||
| 91 | if (IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) | - | ||||||||||||||||||
| 92 | features |= Q_UINT64_C(1) << CpuFeatureSSE2; | - | ||||||||||||||||||
| 93 | if (IsProcessorFeaturePresent(PF_SSE3_INSTRUCTIONS_AVAILABLE)) | - | ||||||||||||||||||
| 94 | features |= Q_UINT64_C(1) << CpuFeatureSSE3; | - | ||||||||||||||||||
| 95 | #endif | - | ||||||||||||||||||
| 96 | return features; | - | ||||||||||||||||||
| 97 | } | - | ||||||||||||||||||
| 98 | - | |||||||||||||||||||
| 99 | #elif defined(Q_PROCESSOR_ARM) | - | ||||||||||||||||||
| 100 | static inline quint64 detectProcessorFeatures() | - | ||||||||||||||||||
| 101 | { | - | ||||||||||||||||||
| 102 | quint64 features = 0; | - | ||||||||||||||||||
| 103 | - | |||||||||||||||||||
| 104 | #if defined(Q_OS_LINUX) | - | ||||||||||||||||||
| 105 | int auxv = qt_safe_open("/proc/self/auxv", O_RDONLY); | - | ||||||||||||||||||
| 106 | if (auxv != -1) { | - | ||||||||||||||||||
| 107 | unsigned long vector[64]; | - | ||||||||||||||||||
| 108 | int nread; | - | ||||||||||||||||||
| 109 | while (features == 0) { | - | ||||||||||||||||||
| 110 | nread = qt_safe_read(auxv, (char *)vector, sizeof vector); | - | ||||||||||||||||||
| 111 | if (nread <= 0) { | - | ||||||||||||||||||
| 112 | // EOF or error | - | ||||||||||||||||||
| 113 | break; | - | ||||||||||||||||||
| 114 | } | - | ||||||||||||||||||
| 115 | - | |||||||||||||||||||
| 116 | int max = nread / (sizeof vector[0]); | - | ||||||||||||||||||
| 117 | for (int i = 0; i < max; i += 2) | - | ||||||||||||||||||
| 118 | if (vector[i] == AT_HWCAP) { | - | ||||||||||||||||||
| 119 | if (vector[i+1] & HWCAP_NEON) | - | ||||||||||||||||||
| 120 | features |= Q_UINT64_C(1) << CpuFeatureNEON; | - | ||||||||||||||||||
| 121 | break; | - | ||||||||||||||||||
| 122 | } | - | ||||||||||||||||||
| 123 | } | - | ||||||||||||||||||
| 124 | - | |||||||||||||||||||
| 125 | qt_safe_close(auxv); | - | ||||||||||||||||||
| 126 | return features; | - | ||||||||||||||||||
| 127 | } | - | ||||||||||||||||||
| 128 | // fall back if /proc/self/auxv wasn't found | - | ||||||||||||||||||
| 129 | #endif | - | ||||||||||||||||||
| 130 | - | |||||||||||||||||||
| 131 | #if defined(__ARM_NEON__) | - | ||||||||||||||||||
| 132 | features = Q_UINT64_C(1) << CpuFeatureNEON; | - | ||||||||||||||||||
| 133 | #endif | - | ||||||||||||||||||
| 134 | - | |||||||||||||||||||
| 135 | return features; | - | ||||||||||||||||||
| 136 | } | - | ||||||||||||||||||
| 137 | - | |||||||||||||||||||
| 138 | #elif defined(Q_PROCESSOR_X86) | - | ||||||||||||||||||
| 139 | - | |||||||||||||||||||
| 140 | #ifdef Q_PROCESSOR_X86_32 | - | ||||||||||||||||||
| 141 | # define PICreg "%%ebx" | - | ||||||||||||||||||
| 142 | #else | - | ||||||||||||||||||
| 143 | # define PICreg "%%rbx" | - | ||||||||||||||||||
| 144 | #endif | - | ||||||||||||||||||
| 145 | - | |||||||||||||||||||
| 146 | static int maxBasicCpuidSupported() | - | ||||||||||||||||||
| 147 | { | - | ||||||||||||||||||
| 148 | #if defined(Q_CC_GNU) | - | ||||||||||||||||||
| 149 | qregisterint tmp1; | - | ||||||||||||||||||
| 150 | - | |||||||||||||||||||
| 151 | # if Q_PROCESSOR_X86 < 5 | - | ||||||||||||||||||
| 152 | // check if the CPUID instruction is supported | - | ||||||||||||||||||
| 153 | long cpuid_supported; | - | ||||||||||||||||||
| 154 | asm ("pushf\n" | - | ||||||||||||||||||
| 155 | "pop %0\n" | - | ||||||||||||||||||
| 156 | "mov %0, %1\n" | - | ||||||||||||||||||
| 157 | "xor $0x00200000, %0\n" | - | ||||||||||||||||||
| 158 | "push %0\n" | - | ||||||||||||||||||
| 159 | "popf\n" | - | ||||||||||||||||||
| 160 | "pushf\n" | - | ||||||||||||||||||
| 161 | "pop %0\n" | - | ||||||||||||||||||
| 162 | "xor %1, %0\n" // %eax is now 0 if CPUID is not supported | - | ||||||||||||||||||
| 163 | : "=a" (cpuid_supported), "=r" (tmp1) | - | ||||||||||||||||||
| 164 | ); | - | ||||||||||||||||||
| 165 | if (!cpuid_supported) | - | ||||||||||||||||||
| 166 | return 0; | - | ||||||||||||||||||
| 167 | # endif | - | ||||||||||||||||||
| 168 | - | |||||||||||||||||||
| 169 | int result; | - | ||||||||||||||||||
| 170 | asm ("xchg " PICreg", %1\n" | - | ||||||||||||||||||
| 171 | "cpuid\n" | - | ||||||||||||||||||
| 172 | "xchg " PICreg", %1\n" | - | ||||||||||||||||||
| 173 | : "=&a" (result), "=&r" (tmp1) | - | ||||||||||||||||||
| 174 | : "0" (0) | - | ||||||||||||||||||
| 175 | : "ecx", "edx"); | - | ||||||||||||||||||
| 176 | return result; executed 1044 times by 96 tests: return result;Executed by:
| 1044 | ||||||||||||||||||
| 177 | #elif defined(Q_OS_WIN) | - | ||||||||||||||||||
| 178 | // Use the __cpuid function; if the CPUID instruction isn't supported, it will return 0 | - | ||||||||||||||||||
| 179 | int info[4]; | - | ||||||||||||||||||
| 180 | __cpuid(info, 0); | - | ||||||||||||||||||
| 181 | return info[0]; | - | ||||||||||||||||||
| 182 | #else | - | ||||||||||||||||||
| 183 | return 0; | - | ||||||||||||||||||
| 184 | #endif | - | ||||||||||||||||||
| 185 | } | - | ||||||||||||||||||
| 186 | - | |||||||||||||||||||
| 187 | static void cpuidFeatures01(uint &ecx, uint &edx) | - | ||||||||||||||||||
| 188 | { | - | ||||||||||||||||||
| 189 | #if defined(Q_CC_GNU) | - | ||||||||||||||||||
| 190 | qregisterint tmp1; | - | ||||||||||||||||||
| 191 | asm ("xchg " PICreg", %2\n" | - | ||||||||||||||||||
| 192 | "cpuid\n" | - | ||||||||||||||||||
| 193 | "xchg " PICreg", %2\n" | - | ||||||||||||||||||
| 194 | : "=&c" (ecx), "=&d" (edx), "=&r" (tmp1) | - | ||||||||||||||||||
| 195 | : "a" (1)); | - | ||||||||||||||||||
| 196 | #elif defined(Q_OS_WIN) | - | ||||||||||||||||||
| 197 | int info[4]; | - | ||||||||||||||||||
| 198 | __cpuid(info, 1); | - | ||||||||||||||||||
| 199 | ecx = info[2]; | - | ||||||||||||||||||
| 200 | edx = info[3]; | - | ||||||||||||||||||
| 201 | #endif | - | ||||||||||||||||||
| 202 | } executed 1044 times by 96 tests: end of blockExecuted by:
| 1044 | ||||||||||||||||||
| 203 | - | |||||||||||||||||||
| 204 | #ifdef Q_OS_WIN | - | ||||||||||||||||||
| 205 | inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));} | - | ||||||||||||||||||
| 206 | #endif | - | ||||||||||||||||||
| 207 | - | |||||||||||||||||||
| 208 | static void cpuidFeatures07_00(uint &ebx, uint &ecx) | - | ||||||||||||||||||
| 209 | { | - | ||||||||||||||||||
| 210 | #if defined(Q_CC_GNU) | - | ||||||||||||||||||
| 211 | qregisteruint rbx; // in case it's 64-bit | - | ||||||||||||||||||
| 212 | qregisteruint rcx = 0; | - | ||||||||||||||||||
| 213 | asm ("xchg " PICreg", %0\n" | - | ||||||||||||||||||
| 214 | "cpuid\n" | - | ||||||||||||||||||
| 215 | "xchg " PICreg", %0\n" | - | ||||||||||||||||||
| 216 | : "=&r" (rbx), "+&c" (rcx) | - | ||||||||||||||||||
| 217 | : "a" (7) | - | ||||||||||||||||||
| 218 | : "%edx"); | - | ||||||||||||||||||
| 219 | ebx = rbx; | - | ||||||||||||||||||
| 220 | ecx = rcx; | - | ||||||||||||||||||
| 221 | #elif defined(Q_OS_WIN) | - | ||||||||||||||||||
| 222 | int info[4]; | - | ||||||||||||||||||
| 223 | __cpuidex(info, 7, 0); | - | ||||||||||||||||||
| 224 | ebx = info[1]; | - | ||||||||||||||||||
| 225 | ecx = info[2]; | - | ||||||||||||||||||
| 226 | #endif | - | ||||||||||||||||||
| 227 | } executed 1044 times by 96 tests: end of blockExecuted by:
| 1044 | ||||||||||||||||||
| 228 | - | |||||||||||||||||||
| 229 | #ifdef Q_OS_WIN | - | ||||||||||||||||||
| 230 | // fallback overload in case this intrinsic does not exist: unsigned __int64 _xgetbv(unsigned int); | - | ||||||||||||||||||
| 231 | inline quint64 _xgetbv(__int64) { return 0; } | - | ||||||||||||||||||
| 232 | #endif | - | ||||||||||||||||||
| 233 | static void xgetbv(uint in, uint &eax, uint &edx) | - | ||||||||||||||||||
| 234 | { | - | ||||||||||||||||||
| 235 | #if defined(Q_CC_GNU) | - | ||||||||||||||||||
| 236 | asm (".byte 0x0F, 0x01, 0xD0" // xgetbv instruction | - | ||||||||||||||||||
| 237 | : "=a" (eax), "=d" (edx) | - | ||||||||||||||||||
| 238 | : "c" (in)); | - | ||||||||||||||||||
| 239 | #elif defined(Q_OS_WIN) | - | ||||||||||||||||||
| 240 | quint64 result = _xgetbv(in); | - | ||||||||||||||||||
| 241 | eax = result; | - | ||||||||||||||||||
| 242 | edx = result >> 32; | - | ||||||||||||||||||
| 243 | #endif | - | ||||||||||||||||||
| 244 | } never executed: end of block | 0 | ||||||||||||||||||
| 245 | - | |||||||||||||||||||
| 246 | static quint64 detectProcessorFeatures() | - | ||||||||||||||||||
| 247 | { | - | ||||||||||||||||||
| 248 | // Flags from the CR0 / XCR0 state register | - | ||||||||||||||||||
| 249 | enum XCR0Flags { | - | ||||||||||||||||||
| 250 | X87 = 1 << 0, | - | ||||||||||||||||||
| 251 | XMM0_15 = 1 << 1, | - | ||||||||||||||||||
| 252 | YMM0_15Hi128 = 1 << 2, | - | ||||||||||||||||||
| 253 | BNDRegs = 1 << 3, | - | ||||||||||||||||||
| 254 | BNDCSR = 1 << 4, | - | ||||||||||||||||||
| 255 | OpMask = 1 << 5, | - | ||||||||||||||||||
| 256 | ZMM0_15Hi256 = 1 << 6, | - | ||||||||||||||||||
| 257 | ZMM16_31 = 1 << 7, | - | ||||||||||||||||||
| 258 | - | |||||||||||||||||||
| 259 | SSEState = XMM0_15, | - | ||||||||||||||||||
| 260 | AVXState = XMM0_15 | YMM0_15Hi128, | - | ||||||||||||||||||
| 261 | AVX512State = AVXState | OpMask | ZMM0_15Hi256 | ZMM16_31 | - | ||||||||||||||||||
| 262 | }; | - | ||||||||||||||||||
| 263 | static const quint64 AllAVX512 = (Q_UINT64_C(1) << CpuFeatureAVX512F) | (Q_UINT64_C(1) << CpuFeatureAVX512CD) | | - | ||||||||||||||||||
| 264 | (Q_UINT64_C(1) << CpuFeatureAVX512ER) | (Q_UINT64_C(1) << CpuFeatureAVX512PF) | | - | ||||||||||||||||||
| 265 | (Q_UINT64_C(1) << CpuFeatureAVX512BW) | (Q_UINT64_C(1) << CpuFeatureAVX512DQ) | | - | ||||||||||||||||||
| 266 | (Q_UINT64_C(1) << CpuFeatureAVX512VL) | | - | ||||||||||||||||||
| 267 | (Q_UINT64_C(1) << CpuFeatureAVX512IFMA) | (Q_UINT64_C(1) << CpuFeatureAVX512VBMI); | - | ||||||||||||||||||
| 268 | static const quint64 AllAVX2 = (Q_UINT64_C(1) << CpuFeatureAVX2) | AllAVX512; | - | ||||||||||||||||||
| 269 | static const quint64 AllAVX = (Q_UINT64_C(1) << CpuFeatureAVX) | AllAVX2; | - | ||||||||||||||||||
| 270 | - | |||||||||||||||||||
| 271 | quint64 features = 0; | - | ||||||||||||||||||
| 272 | int cpuidLevel = maxBasicCpuidSupported(); | - | ||||||||||||||||||
| 273 | #if Q_PROCESSOR_X86 < 5 | - | ||||||||||||||||||
| 274 | if (cpuidLevel < 1) | - | ||||||||||||||||||
| 275 | return 0; | - | ||||||||||||||||||
| 276 | #else | - | ||||||||||||||||||
| 277 | Q_ASSERT(cpuidLevel >= 1); | - | ||||||||||||||||||
| 278 | #endif | - | ||||||||||||||||||
| 279 | - | |||||||||||||||||||
| 280 | uint cpuid01ECX = 0, cpuid01EDX = 0; | - | ||||||||||||||||||
| 281 | cpuidFeatures01(cpuid01ECX, cpuid01EDX); | - | ||||||||||||||||||
| 282 | - | |||||||||||||||||||
| 283 | // the low 32-bits of features is cpuid01ECX | - | ||||||||||||||||||
| 284 | // note: we need to check OS support for saving the AVX register state | - | ||||||||||||||||||
| 285 | features = cpuid01ECX; | - | ||||||||||||||||||
| 286 | - | |||||||||||||||||||
| 287 | #if defined(Q_PROCESSOR_X86_32) | - | ||||||||||||||||||
| 288 | // x86 might not have SSE2 support | - | ||||||||||||||||||
| 289 | if (cpuid01EDX & (1u << 26)) | - | ||||||||||||||||||
| 290 | features |= Q_UINT64_C(1) << CpuFeatureSSE2; | - | ||||||||||||||||||
| 291 | else | - | ||||||||||||||||||
| 292 | features &= ~(Q_UINT64_C(1) << CpuFeatureSSE2); | - | ||||||||||||||||||
| 293 | // we should verify that the OS enabled saving of the SSE state... | - | ||||||||||||||||||
| 294 | #else | - | ||||||||||||||||||
| 295 | // x86-64 or x32 | - | ||||||||||||||||||
| 296 | features |= Q_UINT64_C(1) << CpuFeatureSSE2; | - | ||||||||||||||||||
| 297 | #endif | - | ||||||||||||||||||
| 298 | - | |||||||||||||||||||
| 299 | uint xgetbvA = 0, xgetbvD = 0; | - | ||||||||||||||||||
| 300 | if (cpuid01ECX & (1u << 27)) {
| 0-1044 | ||||||||||||||||||
| 301 | // XGETBV enabled | - | ||||||||||||||||||
| 302 | xgetbv(0, xgetbvA, xgetbvD); | - | ||||||||||||||||||
| 303 | } never executed: end of block | 0 | ||||||||||||||||||
| 304 | - | |||||||||||||||||||
| 305 | uint cpuid0700EBX = 0; | - | ||||||||||||||||||
| 306 | uint cpuid0700ECX = 0; | - | ||||||||||||||||||
| 307 | if (cpuidLevel >= 7) {
| 0-1044 | ||||||||||||||||||
| 308 | cpuidFeatures07_00(cpuid0700EBX, cpuid0700ECX); | - | ||||||||||||||||||
| 309 | - | |||||||||||||||||||
| 310 | // the high 32-bits of features is cpuid0700EBX | - | ||||||||||||||||||
| 311 | features |= quint64(cpuid0700EBX) << 32; | - | ||||||||||||||||||
| 312 | } executed 1044 times by 96 tests: end of blockExecuted by:
| 1044 | ||||||||||||||||||
| 313 | - | |||||||||||||||||||
| 314 | if ((xgetbvA & AVXState) != AVXState) {
| 0-1044 | ||||||||||||||||||
| 315 | // support for YMM registers is disabled, disable all AVX | - | ||||||||||||||||||
| 316 | features &= ~AllAVX; | - | ||||||||||||||||||
| 317 | } else if ((xgetbvA & AVX512State) != AVX512State) { executed 1044 times by 96 tests: end of blockExecuted by:
| 0-1044 | ||||||||||||||||||
| 318 | // support for ZMM registers or mask registers is disabled, disable all AVX512 | - | ||||||||||||||||||
| 319 | features &= ~AllAVX512; | - | ||||||||||||||||||
| 320 | } else { never executed: end of block | 0 | ||||||||||||||||||
| 321 | // this feature is out of order | - | ||||||||||||||||||
| 322 | if (cpuid0700ECX & (1u << 1))
| 0 | ||||||||||||||||||
| 323 | features |= Q_UINT64_C(1) << CpuFeatureAVX512VBMI; never executed: features |= static_cast<unsigned long long>(1ULL) << CpuFeatureAVX512VBMI; | 0 | ||||||||||||||||||
| 324 | else | - | ||||||||||||||||||
| 325 | features &= ~(Q_UINT64_C(1) << CpuFeatureAVX512VBMI); never executed: features &= ~(static_cast<unsigned long long>(1ULL) << CpuFeatureAVX512VBMI); | 0 | ||||||||||||||||||
| 326 | } | - | ||||||||||||||||||
| 327 | - | |||||||||||||||||||
| 328 | return features; executed 1044 times by 96 tests: return features;Executed by:
| 1044 | ||||||||||||||||||
| 329 | } | - | ||||||||||||||||||
| 330 | - | |||||||||||||||||||
| 331 | #elif defined(Q_PROCESSOR_MIPS_32) | - | ||||||||||||||||||
| 332 | - | |||||||||||||||||||
| 333 | #if defined(Q_OS_LINUX) | - | ||||||||||||||||||
| 334 | // | - | ||||||||||||||||||
| 335 | // Do not use QByteArray: it could use SIMD instructions itself at | - | ||||||||||||||||||
| 336 | // some point, thus creating a recursive dependency. Instead, use a | - | ||||||||||||||||||
| 337 | // QSimpleBuffer, which has the bare minimum needed to use memory | - | ||||||||||||||||||
| 338 | // dynamically and read lines from /proc/cpuinfo of arbitrary sizes. | - | ||||||||||||||||||
| 339 | // | - | ||||||||||||||||||
| 340 | struct QSimpleBuffer { | - | ||||||||||||||||||
| 341 | static const int chunk_size = 256; | - | ||||||||||||||||||
| 342 | char *data; | - | ||||||||||||||||||
| 343 | unsigned alloc; | - | ||||||||||||||||||
| 344 | unsigned size; | - | ||||||||||||||||||
| 345 | - | |||||||||||||||||||
| 346 | QSimpleBuffer(): data(0), alloc(0), size(0) {} | - | ||||||||||||||||||
| 347 | ~QSimpleBuffer() { ::free(data); } | - | ||||||||||||||||||
| 348 | - | |||||||||||||||||||
| 349 | void resize(unsigned newsize) { | - | ||||||||||||||||||
| 350 | if (newsize > alloc) { | - | ||||||||||||||||||
| 351 | unsigned newalloc = chunk_size * ((newsize / chunk_size) + 1); | - | ||||||||||||||||||
| 352 | if (newalloc < newsize) newalloc = newsize; | - | ||||||||||||||||||
| 353 | if (newalloc != alloc) { | - | ||||||||||||||||||
| 354 | data = static_cast<char*>(::realloc(data, newalloc)); | - | ||||||||||||||||||
| 355 | alloc = newalloc; | - | ||||||||||||||||||
| 356 | } | - | ||||||||||||||||||
| 357 | } | - | ||||||||||||||||||
| 358 | size = newsize; | - | ||||||||||||||||||
| 359 | } | - | ||||||||||||||||||
| 360 | void append(const QSimpleBuffer &other, unsigned appendsize) { | - | ||||||||||||||||||
| 361 | unsigned oldsize = size; | - | ||||||||||||||||||
| 362 | resize(oldsize + appendsize); | - | ||||||||||||||||||
| 363 | ::memcpy(data + oldsize, other.data, appendsize); | - | ||||||||||||||||||
| 364 | } | - | ||||||||||||||||||
| 365 | void popleft(unsigned amount) { | - | ||||||||||||||||||
| 366 | if (amount >= size) return resize(0); | - | ||||||||||||||||||
| 367 | size -= amount; | - | ||||||||||||||||||
| 368 | ::memmove(data, data + amount, size); | - | ||||||||||||||||||
| 369 | } | - | ||||||||||||||||||
| 370 | char* cString() { | - | ||||||||||||||||||
| 371 | if (!alloc) resize(1); | - | ||||||||||||||||||
| 372 | return (data[size] = '\0', data); | - | ||||||||||||||||||
| 373 | } | - | ||||||||||||||||||
| 374 | }; | - | ||||||||||||||||||
| 375 | - | |||||||||||||||||||
| 376 | // | - | ||||||||||||||||||
| 377 | // Uses a scratch "buffer" (which must be used for all reads done in the | - | ||||||||||||||||||
| 378 | // same file descriptor) to read chunks of data from a file, to read | - | ||||||||||||||||||
| 379 | // one line at a time. Lines include the trailing newline character ('\n'). | - | ||||||||||||||||||
| 380 | // On EOF, line.size is zero. | - | ||||||||||||||||||
| 381 | // | - | ||||||||||||||||||
| 382 | static void bufReadLine(int fd, QSimpleBuffer &line, QSimpleBuffer &buffer) | - | ||||||||||||||||||
| 383 | { | - | ||||||||||||||||||
| 384 | for (;;) { | - | ||||||||||||||||||
| 385 | char *newline = static_cast<char*>(::memchr(buffer.data, '\n', buffer.size)); | - | ||||||||||||||||||
| 386 | if (newline) { | - | ||||||||||||||||||
| 387 | unsigned piece_size = newline - buffer.data + 1; | - | ||||||||||||||||||
| 388 | line.append(buffer, piece_size); | - | ||||||||||||||||||
| 389 | buffer.popleft(piece_size); | - | ||||||||||||||||||
| 390 | line.resize(line.size - 1); | - | ||||||||||||||||||
| 391 | return; | - | ||||||||||||||||||
| 392 | } | - | ||||||||||||||||||
| 393 | if (buffer.size + QSimpleBuffer::chunk_size > buffer.alloc) { | - | ||||||||||||||||||
| 394 | int oldsize = buffer.size; | - | ||||||||||||||||||
| 395 | buffer.resize(buffer.size + QSimpleBuffer::chunk_size); | - | ||||||||||||||||||
| 396 | buffer.size = oldsize; | - | ||||||||||||||||||
| 397 | } | - | ||||||||||||||||||
| 398 | ssize_t read_bytes = ::qt_safe_read(fd, buffer.data + buffer.size, QSimpleBuffer::chunk_size); | - | ||||||||||||||||||
| 399 | if (read_bytes > 0) buffer.size += read_bytes; | - | ||||||||||||||||||
| 400 | else return; | - | ||||||||||||||||||
| 401 | } | - | ||||||||||||||||||
| 402 | } | - | ||||||||||||||||||
| 403 | - | |||||||||||||||||||
| 404 | // | - | ||||||||||||||||||
| 405 | // Checks if any line with a given prefix from /proc/cpuinfo contains | - | ||||||||||||||||||
| 406 | // a certain string, surrounded by spaces. | - | ||||||||||||||||||
| 407 | // | - | ||||||||||||||||||
| 408 | static bool procCpuinfoContains(const char *prefix, const char *string) | - | ||||||||||||||||||
| 409 | { | - | ||||||||||||||||||
| 410 | int cpuinfo_fd = ::qt_safe_open("/proc/cpuinfo", O_RDONLY); | - | ||||||||||||||||||
| 411 | if (cpuinfo_fd == -1) | - | ||||||||||||||||||
| 412 | return false; | - | ||||||||||||||||||
| 413 | - | |||||||||||||||||||
| 414 | unsigned string_len = ::strlen(string); | - | ||||||||||||||||||
| 415 | unsigned prefix_len = ::strlen(prefix); | - | ||||||||||||||||||
| 416 | QSimpleBuffer line, buffer; | - | ||||||||||||||||||
| 417 | bool present = false; | - | ||||||||||||||||||
| 418 | do { | - | ||||||||||||||||||
| 419 | line.resize(0); | - | ||||||||||||||||||
| 420 | bufReadLine(cpuinfo_fd, line, buffer); | - | ||||||||||||||||||
| 421 | char *colon = static_cast<char*>(::memchr(line.data, ':', line.size)); | - | ||||||||||||||||||
| 422 | if (colon && line.size > prefix_len + string_len) { | - | ||||||||||||||||||
| 423 | if (!::strncmp(prefix, line.data, prefix_len)) { | - | ||||||||||||||||||
| 424 | // prefix matches, next character must be ':' or space | - | ||||||||||||||||||
| 425 | if (line.data[prefix_len] == ':' || ::isspace(line.data[prefix_len])) { | - | ||||||||||||||||||
| 426 | // Does it contain the string? | - | ||||||||||||||||||
| 427 | char *found = ::strstr(line.cString(), string); | - | ||||||||||||||||||
| 428 | if (found && ::isspace(found[-1]) && | - | ||||||||||||||||||
| 429 | (::isspace(found[string_len]) || found[string_len] == '\0')) { | - | ||||||||||||||||||
| 430 | present = true; | - | ||||||||||||||||||
| 431 | break; | - | ||||||||||||||||||
| 432 | } | - | ||||||||||||||||||
| 433 | } | - | ||||||||||||||||||
| 434 | } | - | ||||||||||||||||||
| 435 | } | - | ||||||||||||||||||
| 436 | } while (line.size); | - | ||||||||||||||||||
| 437 | - | |||||||||||||||||||
| 438 | ::qt_safe_close(cpuinfo_fd); | - | ||||||||||||||||||
| 439 | return present; | - | ||||||||||||||||||
| 440 | } | - | ||||||||||||||||||
| 441 | #endif | - | ||||||||||||||||||
| 442 | - | |||||||||||||||||||
| 443 | static inline quint64 detectProcessorFeatures() | - | ||||||||||||||||||
| 444 | { | - | ||||||||||||||||||
| 445 | // NOTE: MIPS 74K cores are the only ones supporting DSPr2. | - | ||||||||||||||||||
| 446 | quint64 flags = 0; | - | ||||||||||||||||||
| 447 | - | |||||||||||||||||||
| 448 | #if defined __mips_dsp | - | ||||||||||||||||||
| 449 | flags |= Q_UINT64_C(1) << CpuFeatureDSP; | - | ||||||||||||||||||
| 450 | # if defined __mips_dsp_rev && __mips_dsp_rev >= 2 | - | ||||||||||||||||||
| 451 | flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; | - | ||||||||||||||||||
| 452 | # elif defined(Q_OS_LINUX) | - | ||||||||||||||||||
| 453 | if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) | - | ||||||||||||||||||
| 454 | flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; | - | ||||||||||||||||||
| 455 | # endif | - | ||||||||||||||||||
| 456 | #elif defined(Q_OS_LINUX) | - | ||||||||||||||||||
| 457 | if (procCpuinfoContains("ASEs implemented", "dsp")) { | - | ||||||||||||||||||
| 458 | flags |= Q_UINT64_C(1) << CpuFeatureDSP; | - | ||||||||||||||||||
| 459 | if (procCpuinfoContains("cpu model", "MIPS 74Kc") || procCpuinfoContains("cpu model", "MIPS 74Kf")) | - | ||||||||||||||||||
| 460 | flags |= Q_UINT64_C(1) << CpuFeatureDSPR2; | - | ||||||||||||||||||
| 461 | } | - | ||||||||||||||||||
| 462 | #endif | - | ||||||||||||||||||
| 463 | - | |||||||||||||||||||
| 464 | return flags; | - | ||||||||||||||||||
| 465 | } | - | ||||||||||||||||||
| 466 | - | |||||||||||||||||||
| 467 | #else | - | ||||||||||||||||||
| 468 | static inline uint detectProcessorFeatures() | - | ||||||||||||||||||
| 469 | { | - | ||||||||||||||||||
| 470 | return 0; | - | ||||||||||||||||||
| 471 | } | - | ||||||||||||||||||
| 472 | #endif | - | ||||||||||||||||||
| 473 | - | |||||||||||||||||||
| 474 | /* | - | ||||||||||||||||||
| 475 | * Use kdesdk/scripts/generate_string_table.pl to update the table below. Note | - | ||||||||||||||||||
| 476 | * that the x86 version has a lot of blanks that must be kept and that the | - | ||||||||||||||||||
| 477 | * offset table's type is changed to make the table smaller. We also remove the | - | ||||||||||||||||||
| 478 | * terminating -1 that the script adds. | - | ||||||||||||||||||
| 479 | */ | - | ||||||||||||||||||
| 480 | - | |||||||||||||||||||
| 481 | // begin generated | - | ||||||||||||||||||
| 482 | #if defined(Q_PROCESSOR_ARM) | - | ||||||||||||||||||
| 483 | /* Data: | - | ||||||||||||||||||
| 484 | neon | - | ||||||||||||||||||
| 485 | */ | - | ||||||||||||||||||
| 486 | static const char features_string[] = " neon\0"; | - | ||||||||||||||||||
| 487 | static const int features_indices[] = { 0 }; | - | ||||||||||||||||||
| 488 | #elif defined(Q_PROCESSOR_MIPS) | - | ||||||||||||||||||
| 489 | /* Data: | - | ||||||||||||||||||
| 490 | dsp | - | ||||||||||||||||||
| 491 | dspr2 | - | ||||||||||||||||||
| 492 | */ | - | ||||||||||||||||||
| 493 | static const char features_string[] = | - | ||||||||||||||||||
| 494 | " dsp\0" | - | ||||||||||||||||||
| 495 | " dspr2\0" | - | ||||||||||||||||||
| 496 | "\0"; | - | ||||||||||||||||||
| 497 | - | |||||||||||||||||||
| 498 | static const int features_indices[] = { | - | ||||||||||||||||||
| 499 | 0, 5 | - | ||||||||||||||||||
| 500 | }; | - | ||||||||||||||||||
| 501 | #elif defined(Q_PROCESSOR_X86) | - | ||||||||||||||||||
| 502 | /* Data: | - | ||||||||||||||||||
| 503 | sse3 | - | ||||||||||||||||||
| 504 | sse2 | - | ||||||||||||||||||
| 505 | avx512vbmi | - | ||||||||||||||||||
| 506 | - | |||||||||||||||||||
| 507 | - | |||||||||||||||||||
| 508 | - | |||||||||||||||||||
| 509 | - | |||||||||||||||||||
| 510 | - | |||||||||||||||||||
| 511 | - | |||||||||||||||||||
| 512 | ssse3 | - | ||||||||||||||||||
| 513 | - | |||||||||||||||||||
| 514 | - | |||||||||||||||||||
| 515 | fma | - | ||||||||||||||||||
| 516 | cmpxchg16b | - | ||||||||||||||||||
| 517 | - | |||||||||||||||||||
| 518 | - | |||||||||||||||||||
| 519 | - | |||||||||||||||||||
| 520 | - | |||||||||||||||||||
| 521 | - | |||||||||||||||||||
| 522 | sse4.1 | - | ||||||||||||||||||
| 523 | sse4.2 | - | ||||||||||||||||||
| 524 | - | |||||||||||||||||||
| 525 | movbe | - | ||||||||||||||||||
| 526 | popcnt | - | ||||||||||||||||||
| 527 | - | |||||||||||||||||||
| 528 | aes | - | ||||||||||||||||||
| 529 | - | |||||||||||||||||||
| 530 | - | |||||||||||||||||||
| 531 | avx | - | ||||||||||||||||||
| 532 | f16c | - | ||||||||||||||||||
| 533 | rdrand | - | ||||||||||||||||||
| 534 | - | |||||||||||||||||||
| 535 | - | |||||||||||||||||||
| 536 | - | |||||||||||||||||||
| 537 | - | |||||||||||||||||||
| 538 | bmi | - | ||||||||||||||||||
| 539 | hle | - | ||||||||||||||||||
| 540 | avx2 | - | ||||||||||||||||||
| 541 | - | |||||||||||||||||||
| 542 | - | |||||||||||||||||||
| 543 | bmi2 | - | ||||||||||||||||||
| 544 | - | |||||||||||||||||||
| 545 | - | |||||||||||||||||||
| 546 | rtm | - | ||||||||||||||||||
| 547 | - | |||||||||||||||||||
| 548 | - | |||||||||||||||||||
| 549 | - | |||||||||||||||||||
| 550 | - | |||||||||||||||||||
| 551 | avx512f | - | ||||||||||||||||||
| 552 | avx512dq | - | ||||||||||||||||||
| 553 | rdseed | - | ||||||||||||||||||
| 554 | - | |||||||||||||||||||
| 555 | - | |||||||||||||||||||
| 556 | avx512ifma | - | ||||||||||||||||||
| 557 | - | |||||||||||||||||||
| 558 | - | |||||||||||||||||||
| 559 | - | |||||||||||||||||||
| 560 | - | |||||||||||||||||||
| 561 | avx512pf | - | ||||||||||||||||||
| 562 | avx512er | - | ||||||||||||||||||
| 563 | avx512cd | - | ||||||||||||||||||
| 564 | sha | - | ||||||||||||||||||
| 565 | avx512bw | - | ||||||||||||||||||
| 566 | avx512vl | - | ||||||||||||||||||
| 567 | */ | - | ||||||||||||||||||
| 568 | static const char features_string[] = | - | ||||||||||||||||||
| 569 | " sse3\0" | - | ||||||||||||||||||
| 570 | " sse2\0" | - | ||||||||||||||||||
| 571 | " avx512vbmi\0" | - | ||||||||||||||||||
| 572 | " ssse3\0" | - | ||||||||||||||||||
| 573 | " fma\0" | - | ||||||||||||||||||
| 574 | " cmpxchg16b\0" | - | ||||||||||||||||||
| 575 | " sse4.1\0" | - | ||||||||||||||||||
| 576 | " sse4.2\0" | - | ||||||||||||||||||
| 577 | " movbe\0" | - | ||||||||||||||||||
| 578 | " popcnt\0" | - | ||||||||||||||||||
| 579 | " aes\0" | - | ||||||||||||||||||
| 580 | " avx\0" | - | ||||||||||||||||||
| 581 | " f16c\0" | - | ||||||||||||||||||
| 582 | " rdrand\0" | - | ||||||||||||||||||
| 583 | " bmi\0" | - | ||||||||||||||||||
| 584 | " hle\0" | - | ||||||||||||||||||
| 585 | " avx2\0" | - | ||||||||||||||||||
| 586 | " bmi2\0" | - | ||||||||||||||||||
| 587 | " rtm\0" | - | ||||||||||||||||||
| 588 | " avx512f\0" | - | ||||||||||||||||||
| 589 | " avx512dq\0" | - | ||||||||||||||||||
| 590 | " rdseed\0" | - | ||||||||||||||||||
| 591 | " avx512ifma\0" | - | ||||||||||||||||||
| 592 | " avx512pf\0" | - | ||||||||||||||||||
| 593 | " avx512er\0" | - | ||||||||||||||||||
| 594 | " avx512cd\0" | - | ||||||||||||||||||
| 595 | " sha\0" | - | ||||||||||||||||||
| 596 | " avx512bw\0" | - | ||||||||||||||||||
| 597 | " avx512vl\0" | - | ||||||||||||||||||
| 598 | "\0"; | - | ||||||||||||||||||
| 599 | - | |||||||||||||||||||
| 600 | static const quint8 features_indices[] = { | - | ||||||||||||||||||
| 601 | 0, 6, 12, 5, 5, 5, 5, 5, | - | ||||||||||||||||||
| 602 | 5, 24, 5, 5, 31, 36, 5, 5, | - | ||||||||||||||||||
| 603 | 5, 5, 5, 48, 56, 5, 64, 71, | - | ||||||||||||||||||
| 604 | 5, 79, 5, 5, 84, 89, 95, 5, | - | ||||||||||||||||||
| 605 | 5, 5, 5, 103, 108, 113, 5, 5, | - | ||||||||||||||||||
| 606 | 119, 5, 5, 125, 5, 5, 5, 5, | - | ||||||||||||||||||
| 607 | 130, 139, 149, 5, 5, 157, 5, 5, | - | ||||||||||||||||||
| 608 | 5, 5, 169, 179, 189, 199, 204, 214 | - | ||||||||||||||||||
| 609 | }; | - | ||||||||||||||||||
| 610 | #else | - | ||||||||||||||||||
| 611 | static const char features_string[] = ""; | - | ||||||||||||||||||
| 612 | static const int features_indices[] = { }; | - | ||||||||||||||||||
| 613 | #endif | - | ||||||||||||||||||
| 614 | // end generated | - | ||||||||||||||||||
| 615 | - | |||||||||||||||||||
| 616 | static const int features_count = (sizeof features_indices) / (sizeof features_indices[0]); | - | ||||||||||||||||||
| 617 | - | |||||||||||||||||||
| 618 | // record what CPU features were enabled by default in this Qt build | - | ||||||||||||||||||
| 619 | static const quint64 minFeature = qCompilerCpuFeatures; | - | ||||||||||||||||||
| 620 | - | |||||||||||||||||||
| 621 | #ifdef Q_OS_WIN | - | ||||||||||||||||||
| 622 | #if defined(Q_CC_GNU) | - | ||||||||||||||||||
| 623 | # define ffsll __builtin_ffsll | - | ||||||||||||||||||
| 624 | #else | - | ||||||||||||||||||
| 625 | int ffsll(quint64 i) | - | ||||||||||||||||||
| 626 | { | - | ||||||||||||||||||
| 627 | #if defined(Q_OS_WIN64) | - | ||||||||||||||||||
| 628 | unsigned long result; | - | ||||||||||||||||||
| 629 | return _BitScanForward64(&result, i) ? result : 0; | - | ||||||||||||||||||
| 630 | #elif !defined(Q_OS_WINCE) | - | ||||||||||||||||||
| 631 | unsigned long result; | - | ||||||||||||||||||
| 632 | return _BitScanForward(&result, i) ? result : | - | ||||||||||||||||||
| 633 | _BitScanForward(&result, i >> 32) ? result + 32 : 0; | - | ||||||||||||||||||
| 634 | #else | - | ||||||||||||||||||
| 635 | return 0; | - | ||||||||||||||||||
| 636 | #endif | - | ||||||||||||||||||
| 637 | } | - | ||||||||||||||||||
| 638 | #endif | - | ||||||||||||||||||
| 639 | #elif defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) | - | ||||||||||||||||||
| 640 | # define ffsll __builtin_ffsll | - | ||||||||||||||||||
| 641 | #endif | - | ||||||||||||||||||
| 642 | - | |||||||||||||||||||
| 643 | #ifdef Q_ATOMIC_INT64_IS_SUPPORTED | - | ||||||||||||||||||
| 644 | Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) }; | - | ||||||||||||||||||
| 645 | #else | - | ||||||||||||||||||
| 646 | Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) }; | - | ||||||||||||||||||
| 647 | #endif | - | ||||||||||||||||||
| 648 | - | |||||||||||||||||||
| 649 | void qDetectCpuFeatures() | - | ||||||||||||||||||
| 650 | { | - | ||||||||||||||||||
| 651 | #if defined(Q_CC_GNU) && !defined(Q_CC_CLANG) && !defined(Q_CC_INTEL) | - | ||||||||||||||||||
| 652 | # if Q_CC_GNU < 403 | - | ||||||||||||||||||
| 653 | // GCC 4.2 (at least the one that comes with Apple's XCode, on Mac) is | - | ||||||||||||||||||
| 654 | // known to be broken beyond repair in dealing with the inline assembly | - | ||||||||||||||||||
| 655 | // above. It will generate bad code that could corrupt important registers | - | ||||||||||||||||||
| 656 | // like the PIC register. The behaviour of code after this function would | - | ||||||||||||||||||
| 657 | // be totally unpredictable. | - | ||||||||||||||||||
| 658 | // | - | ||||||||||||||||||
| 659 | // For that reason, simply forego the CPUID check at all and return the set | - | ||||||||||||||||||
| 660 | // of features that we found at compile time, through the #defines from the | - | ||||||||||||||||||
| 661 | // compiler. This should at least allow code to execute, even if none of | - | ||||||||||||||||||
| 662 | // the specialized code found in Qt GUI and elsewhere will ever be enabled | - | ||||||||||||||||||
| 663 | // (it's the user's fault for using a broken compiler). | - | ||||||||||||||||||
| 664 | // | - | ||||||||||||||||||
| 665 | // This also disables the runtime checking that the processor actually | - | ||||||||||||||||||
| 666 | // contains all the features that the code required. Qt 4 ran for years | - | ||||||||||||||||||
| 667 | // like that, so it shouldn't be a problem. | - | ||||||||||||||||||
| 668 | - | |||||||||||||||||||
| 669 | qt_cpu_features[0].store(minFeature | quint32(QSimdInitialized)); | - | ||||||||||||||||||
| 670 | #ifndef Q_ATOMIC_INT64_IS_SUPPORTED | - | ||||||||||||||||||
| 671 | qt_cpu_features[1].store(minFeature >> 32); | - | ||||||||||||||||||
| 672 | #endif | - | ||||||||||||||||||
| 673 | - | |||||||||||||||||||
| 674 | return; | - | ||||||||||||||||||
| 675 | # endif | - | ||||||||||||||||||
| 676 | #endif | - | ||||||||||||||||||
| 677 | quint64 f = detectProcessorFeatures(); | - | ||||||||||||||||||
| 678 | QByteArray disable = qgetenv("QT_NO_CPU_FEATURE"); | - | ||||||||||||||||||
| 679 | if (!disable.isEmpty()) {
| 0-1044 | ||||||||||||||||||
| 680 | disable.prepend(' '); | - | ||||||||||||||||||
| 681 | for (int i = 0; i < features_count; ++i) {
| 0 | ||||||||||||||||||
| 682 | if (disable.contains(features_string + features_indices[i]))
| 0 | ||||||||||||||||||
| 683 | f &= ~(Q_UINT64_C(1) << i); never executed: f &= ~(static_cast<unsigned long long>(1ULL) << i); | 0 | ||||||||||||||||||
| 684 | } never executed: end of block | 0 | ||||||||||||||||||
| 685 | } never executed: end of block | 0 | ||||||||||||||||||
| 686 | - | |||||||||||||||||||
| 687 | #ifdef RUNNING_ON_VALGRIND | - | ||||||||||||||||||
| 688 | bool runningOnValgrind = RUNNING_ON_VALGRIND; | - | ||||||||||||||||||
| 689 | #else | - | ||||||||||||||||||
| 690 | bool runningOnValgrind = false; | - | ||||||||||||||||||
| 691 | #endif | - | ||||||||||||||||||
| 692 | if (!runningOnValgrind && (minFeature != 0 && (f & minFeature) != minFeature)) {
| 0-1044 | ||||||||||||||||||
| 693 | quint64 missing = minFeature & ~f; | - | ||||||||||||||||||
| 694 | fprintf(stderr, "Incompatible processor. This Qt build requires the following features:\n "); | - | ||||||||||||||||||
| 695 | for (int i = 0; i < features_count; ++i) {
| 0 | ||||||||||||||||||
| 696 | if (missing & (Q_UINT64_C(1) << i))
| 0 | ||||||||||||||||||
| 697 | fprintf(stderr, "%s", features_string + features_indices[i]); never executed: fprintf(stderr, "%s", features_string + features_indices[i]); | 0 | ||||||||||||||||||
| 698 | } never executed: end of block | 0 | ||||||||||||||||||
| 699 | fprintf(stderr, "\n"); | - | ||||||||||||||||||
| 700 | fflush(stderr); | - | ||||||||||||||||||
| 701 | qFatal("Aborted. Incompatible processor: missing feature 0x%llx -%s.", missing, | - | ||||||||||||||||||
| 702 | features_string + features_indices[ffsll(missing) - 1]); | - | ||||||||||||||||||
| 703 | } never executed: end of block | 0 | ||||||||||||||||||
| 704 | - | |||||||||||||||||||
| 705 | qt_cpu_features[0].store(f | quint32(QSimdInitialized)); | - | ||||||||||||||||||
| 706 | #ifndef Q_ATOMIC_INT64_IS_SUPPORTED | - | ||||||||||||||||||
| 707 | qt_cpu_features[1].store(f >> 32); | - | ||||||||||||||||||
| 708 | #endif | - | ||||||||||||||||||
| 709 | } executed 1044 times by 96 tests: end of blockExecuted by:
| 1044 | ||||||||||||||||||
| 710 | - | |||||||||||||||||||
| 711 | void qDumpCPUFeatures() | - | ||||||||||||||||||
| 712 | { | - | ||||||||||||||||||
| 713 | quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized); | - | ||||||||||||||||||
| 714 | printf("Processor features: "); | - | ||||||||||||||||||
| 715 | for (int i = 0; i < features_count; ++i) {
| 0 | ||||||||||||||||||
| 716 | if (features & (Q_UINT64_C(1) << i))
| 0 | ||||||||||||||||||
| 717 | printf("%s%s", features_string + features_indices[i], never executed: printf("%s%s", features_string + features_indices[i], minFeature & (static_cast<unsigned long long>(1ULL) << i) ? "[required]" : ""); | 0 | ||||||||||||||||||
| 718 | minFeature & (Q_UINT64_C(1) << i) ? "[required]" : ""); never executed: printf("%s%s", features_string + features_indices[i], minFeature & (static_cast<unsigned long long>(1ULL) << i) ? "[required]" : ""); | 0 | ||||||||||||||||||
| 719 | } never executed: end of block | 0 | ||||||||||||||||||
| 720 | puts(""); | - | ||||||||||||||||||
| 721 | } never executed: end of block | 0 | ||||||||||||||||||
| 722 | - | |||||||||||||||||||
| 723 | QT_END_NAMESPACE | - | ||||||||||||||||||
| Source code | Switch to Preprocessed file |