qsimd.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/corelib/tools/qsimd.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
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-
73QT_BEGIN_NAMESPACE-
74-
75#if defined (Q_OS_NACL)-
76static inline uint detectProcessorFeatures()-
77{-
78 return 0;-
79}-
80#elif defined (Q_OS_WINCE)-
81static 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)-
100static 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-
146static 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:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
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-
187static 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 block
Executed by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
1044
203-
204#ifdef Q_OS_WIN-
205inline void __cpuidex(int info[4], int, __int64) { memset(info, 0, 4*sizeof(int));}-
206#endif-
207-
208static 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 block
Executed by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
1044
228-
229#ifdef Q_OS_WIN-
230// fallback overload in case this intrinsic does not exist: unsigned __int64 _xgetbv(unsigned int);-
231inline quint64 _xgetbv(__int64) { return 0; }-
232#endif-
233static 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-
246static 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)) {
cpuid01ECX & (1u << 27)Description
TRUEnever evaluated
FALSEevaluated 1044 times by 96 tests
Evaluated by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
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) {
cpuidLevel >= 7Description
TRUEevaluated 1044 times by 96 tests
Evaluated by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
FALSEnever evaluated
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 block
Executed by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
1044
313-
314 if ((xgetbvA & AVXState) != AVXState) {
(xgetbvA & AVX...e) != AVXStateDescription
TRUEevaluated 1044 times by 96 tests
Evaluated by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
FALSEnever evaluated
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 block
Executed by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
(xgetbvA & AVX...!= AVX512StateDescription
TRUEnever evaluated
FALSEnever evaluated
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))
cpuid0700ECX & (1u << 1)Description
TRUEnever evaluated
FALSEnever evaluated
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:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
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//-
340struct 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//-
382static 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//-
408static 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-
443static 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-
468static 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 */-
486static const char features_string[] = " neon\0";-
487static const int features_indices[] = { 0 };-
488#elif defined(Q_PROCESSOR_MIPS)-
489/* Data:-
490 dsp-
491 dspr2-
492*/-
493static const char features_string[] =-
494 " dsp\0"-
495 " dspr2\0"-
496 "\0";-
497-
498static 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 */-
568static 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-
600static 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-
611static const char features_string[] = "";-
612static const int features_indices[] = { };-
613#endif-
614// end generated-
615-
616static 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-
619static const quint64 minFeature = qCompilerCpuFeatures;-
620-
621#ifdef Q_OS_WIN-
622#if defined(Q_CC_GNU)-
623# define ffsll __builtin_ffsll-
624#else-
625int 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-
644Q_CORE_EXPORT QBasicAtomicInteger<quint64> qt_cpu_features[1] = { Q_BASIC_ATOMIC_INITIALIZER(0) };-
645#else-
646Q_CORE_EXPORT QBasicAtomicInteger<unsigned> qt_cpu_features[2] = { Q_BASIC_ATOMIC_INITIALIZER(0), Q_BASIC_ATOMIC_INITIALIZER(0) };-
647#endif-
648-
649void 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()) {
!disable.isEmpty()Description
TRUEnever evaluated
FALSEevaluated 1044 times by 96 tests
Evaluated by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
0-1044
680 disable.prepend(' ');-
681 for (int i = 0; i < features_count; ++i) {
i < features_countDescription
TRUEnever evaluated
FALSEnever evaluated
0
682 if (disable.contains(features_string + features_indices[i]))
disable.contai...es_indices[i])Description
TRUEnever evaluated
FALSEnever evaluated
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)) {
!runningOnValgrindDescription
TRUEevaluated 1044 times by 96 tests
Evaluated by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
FALSEnever evaluated
minFeature != 0Description
TRUEevaluated 1044 times by 96 tests
Evaluated by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
FALSEnever evaluated
(f & minFeature) != minFeatureDescription
TRUEnever evaluated
FALSEevaluated 1044 times by 96 tests
Evaluated by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
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) {
i < features_countDescription
TRUEnever evaluated
FALSEnever evaluated
0
696 if (missing & (Q_UINT64_C(1) << i))
missing & (sta...g>(1ULL) << i)Description
TRUEnever evaluated
FALSEnever evaluated
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 block
Executed by:
  • tst_Collections
  • tst_QAbstractFileEngine
  • tst_QAbstractItemModel
  • tst_QAnimationGroup
  • tst_QAuthenticator
  • tst_QByteArray
  • tst_QCache
  • tst_QCommandLineParser
  • tst_QDBusAbstractInterface
  • tst_QDBusConnection
  • tst_QDBusConnectionNoBus
  • tst_QDBusConnectionNoLibDBus1
  • tst_QDBusConnection_Delayed
  • tst_QDBusConnection_NoApplication
  • tst_QDBusConnection_SpyHook
  • tst_QDBusContext
  • tst_QDBusInterface
  • tst_QDBusMetaObject
  • tst_QDBusServiceWatcher
  • tst_QDBusThreading
  • tst_QDBusXmlParser
  • tst_QDate
  • tst_QDateTime
  • tst_QDebug
  • tst_QDir
  • ...
1044
710-
711void qDumpCPUFeatures()-
712{-
713 quint64 features = qCpuFeatures() & ~quint64(QSimdInitialized);-
714 printf("Processor features: ");-
715 for (int i = 0; i < features_count; ++i) {
i < features_countDescription
TRUEnever evaluated
FALSEnever evaluated
0
716 if (features & (Q_UINT64_C(1) << i))
features & (st...g>(1ULL) << i)Description
TRUEnever evaluated
FALSEnever evaluated
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-
723QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9