7#define __INTEL_COMPILER_USE_INTRINSIC_PROTOTYPES
17#if defined(QT_NO_DEBUG) && !defined(NDEBUG)
23# include "../testlib/3rdparty/valgrind/valgrind_p.h"
26#define QT_FUNCTION_TARGET_BASELINE
29# if !defined(Q_CC_GNU)
32# if defined(Q_PROCESSOR_ARM_64)
33# include <qt_windows.h>
34# include <processthreadsapi.h>
36#elif defined(Q_OS_LINUX) && defined(Q_PROCESSOR_MIPS_32)
37# include "private/qcore_unix_p.h"
38#elif QT_CONFIG(getauxval) && (defined(Q_PROCESSOR_ARM) || defined(Q_PROCESSOR_LOONGARCH))
45#define HWCAP_NEON 4096
48#define HWCAP2_AES (1
<< 0
)
49#define HWCAP2_CRC32 (1
<< 4
)
52#define HWCAP_AES (1
<< 3
)
53#define HWCAP_CRC32 (1
<< 7
)
54#define HWCAP_SVE (1
<< 22
)
60#elif defined(Q_CC_GHS)
61# include <INTEGRITY_types.h>
62#elif defined(Q_OS_DARWIN) && defined(Q_PROCESSOR_ARM)
63# include <sys/sysctl.h>
69uint arraysize(T (&)[N])
76#if defined(Q_PROCESSOR_ARM)
78
79
80
81
82
83static const char features_string[] =
89static const int features_indices[] = { 0, 1, 7, 14, 19 };
90#elif defined(Q_PROCESSOR_MIPS)
92
93
94
95static const char features_string[] =
100static const int features_indices[] = {
103#elif defined(Q_PROCESSOR_LOONGARCH)
105
106
107
108static const char features_string[] =
113static const int features_indices[] = {
116#elif defined(Q_PROCESSOR_X86)
117# include "qsimd_x86.cpp"
124#if defined(Q_PROCESSOR_ARM)
125static inline quint64 detectProcessorFeatures()
127 quint64 features = 0;
129#if QT_CONFIG(getauxval)
130 unsigned long auxvHwCap = getauxval(AT_HWCAP);
131 if (auxvHwCap != 0) {
132# if defined(Q_PROCESSOR_ARM_64)
134 features |= CpuFeatureNEON;
135 if (auxvHwCap & HWCAP_CRC32)
136 features |= CpuFeatureCRC32;
137 if (auxvHwCap & HWCAP_AES)
138 features |= CpuFeatureAES;
139 if (auxvHwCap & HWCAP_SVE)
140 features |= CpuFeatureSVE;
143 if (auxvHwCap & HWCAP_NEON)
144 features |= CpuFeatureNEON;
145 auxvHwCap = getauxval(AT_HWCAP2);
146 if (auxvHwCap & HWCAP2_CRC32)
147 features |= CpuFeatureCRC32;
148 if (auxvHwCap & HWCAP2_AES)
149 features |= CpuFeatureAES;
154#elif defined(Q_OS_DARWIN) && defined(Q_PROCESSOR_ARM)
156 size_t len =
sizeof(feature);
158#if defined(__ARM_NEON)
159 features |= CpuFeatureNEON;
161 #error "Misconfiguration, NEON should always be enabled on Apple hardware"
163#if defined(__ARM_FEATURE_CRC32)
164 features |= CpuFeatureCRC32;
165#elif defined(Q_OS_MACOS)
166 #error "Misconfiguration, CRC32 should always be enabled on Apple desktop hardware"
168 if (sysctlbyname(
"hw.optional.armv8_crc32", &feature, &len,
nullptr, 0) == 0)
169 features |= feature ? CpuFeatureCRC32 : 0;
171#if defined(__ARM_FEATURE_CRYPTO)
172 features |= CpuFeatureAES;
173#elif defined(Q_OS_MACOS)
174 #error "Misconfiguration, CRYPTO/AES should always be enabled on Apple desktop hardware"
176 if (sysctlbyname(
"hw.optional.arm.FEAT_AES", &feature, &len,
nullptr, 0) == 0)
177 features |= feature ? CpuFeatureAES : 0;
179#if defined(__ARM_FEATURE_SVE)
180 features |= CpuFeatureSVE;
182 if (sysctlbyname(
"hw.optional.arm.FEAT_SVE", &feature, &len,
nullptr, 0) == 0)
183 features |= feature ? CpuFeatureSVE : 0;
186#elif defined(Q_OS_WIN) && defined(Q_PROCESSOR_ARM_64)
187 features |= CpuFeatureNEON;
188 if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE) != 0)
189 features |= CpuFeatureCRC32;
190 if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0)
191 features |= CpuFeatureAES;
194#if defined(__ARM_NEON__)
195 features |= CpuFeatureNEON;
197#if defined(__ARM_FEATURE_CRC32)
198 features |= CpuFeatureCRC32;
200#if defined(__ARM_FEATURE_CRYPTO)
201 features |= CpuFeatureAES;
203#if defined(__ARM_FEATURE_SVE)
204 features |= CpuFeatureSVE;
210#elif defined(Q_PROCESSOR_LOONGARCH)
211static inline quint64 detectProcessorFeatures()
213 quint64 features = 0;
214# if QT_CONFIG(getauxval)
215 quint64 hwcap = getauxval(AT_HWCAP);
217 if (hwcap & HWCAP_LOONGARCH_LSX)
218 features |= CpuFeatureLSX;
219 if (hwcap & HWCAP_LOONGARCH_LASX)
220 features |= CpuFeatureLASX;
222 enum LoongArchFeatures {
223 LOONGARCH_CFG2 = 0x2,
224 LOONGARCH_CFG2_LSX = (1 << 6),
225 LOONGARCH_CFG2_LASX = (1 << 7)
233 :
"r"(LOONGARCH_CFG2)
236 if (reg & LOONGARCH_CFG2_LSX)
237 features |= CpuFeatureLSX;
238 if (reg & LOONGARCH_CFG2_LASX)
239 features |= CpuFeatureLASX;
244#elif defined(Q_PROCESSOR_X86)
246#ifdef Q_PROCESSOR_X86_32
247# define PICreg "%%ebx"
249# define PICreg "%%rbx"
252# define X86_BASELINE "no-sse3"
254# define X86_BASELINE "no-sse"
257#if defined(Q_CC_GNU) || defined(Q_CC_CLANG)
259# undef QT_FUNCTION_TARGET_BASELINE
260# define QT_FUNCTION_TARGET_BASELINE __attribute__((target(X86_BASELINE)))
263QT_FUNCTION_TARGET_BASELINE
264static int maxBasicCpuidSupported()
266#if defined(Q_CC_EMSCRIPTEN)
268#elif defined(Q_CC_GNU)
271# if Q_PROCESSOR_X86 < 5
273 long cpuid_supported;
277 "xor $0x00200000, %0\n"
283 :
"=a" (cpuid_supported),
"=r" (tmp1)
285 if (!cpuid_supported)
290 asm (
"xchg " PICreg
", %1\n"
292 "xchg " PICreg
", %1\n"
293 :
"=&a" (result),
"=&r" (tmp1)
297#elif defined(Q_OS_WIN)
302#elif defined(Q_CC_GHS)
303 unsigned int info[4];
311QT_FUNCTION_TARGET_BASELINE
312static void cpuidFeatures01(uint &ecx, uint &edx)
314#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
316 asm (
"xchg " PICreg
", %2\n"
318 "xchg " PICreg
", %2\n"
319 :
"=&c" (ecx),
"=&d" (edx),
"=&r" (tmp1)
321#elif defined(Q_OS_WIN)
326#elif defined(Q_CC_GHS)
327 unsigned int info[4];
338inline void __cpuidex(
int info[4],
int, __int64) { memset(info, 0, 4*
sizeof(
int));}
341QT_FUNCTION_TARGET_BASELINE
342static void cpuidFeatures07_00(uint &ebx, uint &ecx, uint &edx)
344#if defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)
346 qregisteruint rcx = 0;
347 qregisteruint rdx = 0;
348 asm (
"xchg " PICreg
", %0\n"
350 "xchg " PICreg
", %0\n"
351 :
"=&r" (rbx),
"+&c" (rcx),
"+&d" (rdx)
356#elif defined(Q_OS_WIN)
358 __cpuidex(info, 7, 0);
362#elif defined(Q_CC_GHS)
363 unsigned int info[4];
364 __CPUIDEX(7, 0, info);
375QT_FUNCTION_TARGET_BASELINE
376#if defined(Q_OS_WIN) && !(defined(Q_CC_GNU) || defined(Q_CC_GHS))
378inline quint64 _xgetbv(__int64) {
return 0; }
380static void xgetbv(uint in, uint &eax, uint &edx)
382#if (defined(Q_CC_GNU) && !defined(Q_CC_EMSCRIPTEN)) || defined(Q_CC_GHS)
383 asm (
".byte 0x0F, 0x01, 0xD0"
384 :
"=a" (eax),
"=d" (edx)
386#elif defined(Q_OS_WIN)
387 quint64 result = _xgetbv(in);
397QT_FUNCTION_TARGET_BASELINE
398static quint64 adjustedXcr0(quint64 xcr0)
401
402
403
404
405
406
407
408
412 constexpr quint64 kHasAVX512F = Q_UINT64_C(0x0000004000000000);
413 constexpr quintptr commpage =
sizeof(
void *) > 4 ? Q_UINT64_C(0x00007fffffe00000) : 0xffff0000;
414 constexpr quintptr cpu_capabilities64 = commpage + 0x10;
415 quint64 capab = *
reinterpret_cast<quint64 *>(cpu_capabilities64);
416 if (capab & kHasAVX512F)
417 xcr0 |= XSave_Avx512State;
423QT_FUNCTION_TARGET_BASELINE
424static quint64 detectProcessorFeatures()
426 quint64 features = 0;
427 int cpuidLevel = maxBasicCpuidSupported();
428#if Q_PROCESSOR_X86 < 5
432 assert(cpuidLevel >= 1);
435 uint results[X86CpuidMaxLeaf] = {};
436 cpuidFeatures01(results[Leaf01ECX], results[Leaf01EDX]);
438 cpuidFeatures07_00(results[Leaf07_00EBX], results[Leaf07_00ECX], results[Leaf07_00EDX]);
441 for (uint i = 0; i < arraysize(x86_locators); ++i) {
442 uint word = x86_locators[i] / 32;
443 uint bit = 1U << (x86_locators[i] % 32);
444 quint64 feature = Q_UINT64_C(1) << i;
445 if (results[word] & bit)
451 if (results[Leaf01ECX] & (1u << 27)) {
453 uint xgetbvA = 0, xgetbvD = 0;
454 xgetbv(0, xgetbvA, xgetbvD);
457 if (
sizeof(XSaveBits) >
sizeof(xgetbvA))
458 xcr0 |= quint64(xgetbvD) << 32;
459 xcr0 = adjustedXcr0(xcr0);
462 for (
auto req : xsave_requirements) {
463 if ((xcr0 & req.xsave_state) != req.xsave_state)
464 features &= ~req.cpu_features;
470#elif defined(Q_PROCESSOR_MIPS_32)
472#if defined(Q_OS_LINUX)
481 static const int chunk_size = 256;
486 QSimpleBuffer() : data(
nullptr), alloc(0), size(0) { }
487 ~QSimpleBuffer() { ::free(data); }
489 void resize(
unsigned newsize)
491 if (newsize > alloc) {
492 unsigned newalloc = chunk_size * ((newsize / chunk_size) + 1);
493 if (newalloc < newsize)
495 if (newalloc != alloc) {
496 data =
static_cast<
char *>(::realloc(data, newalloc));
502 void append(
const QSimpleBuffer &other,
unsigned appendsize)
504 unsigned oldsize = size;
505 resize(oldsize + appendsize);
506 ::memcpy(data + oldsize, other.data, appendsize);
508 void popleft(
unsigned amount)
513 ::memmove(data, data + amount, size);
519 return (data[size] =
'\0', data);
529static void bufReadLine(
int fd, QSimpleBuffer &line, QSimpleBuffer &buffer)
532 char *newline =
static_cast<
char *>(::memchr(buffer.data,
'\n', buffer.size));
534 unsigned piece_size = newline - buffer.data + 1;
535 line.append(buffer, piece_size);
536 buffer.popleft(piece_size);
537 line.resize(line.size - 1);
540 if (buffer.size + QSimpleBuffer::chunk_size > buffer.alloc) {
541 int oldsize = buffer.size;
542 buffer.resize(buffer.size + QSimpleBuffer::chunk_size);
543 buffer.size = oldsize;
546 ::qt_safe_read(fd, buffer.data + buffer.size, QSimpleBuffer::chunk_size);
548 buffer.size += read_bytes;
558static bool procCpuinfoContains(
const char *prefix,
const char *string)
560 int cpuinfo_fd = ::qt_safe_open(
"/proc/cpuinfo", O_RDONLY);
561 if (cpuinfo_fd == -1)
564 unsigned string_len = ::strlen(string);
565 unsigned prefix_len = ::strlen(prefix);
566 QSimpleBuffer line, buffer;
567 bool present =
false;
570 bufReadLine(cpuinfo_fd, line, buffer);
571 char *colon =
static_cast<
char *>(::memchr(line.data,
':', line.size));
572 if (colon && line.size > prefix_len + string_len) {
573 if (!::strncmp(prefix, line.data, prefix_len)) {
575 if (line.data[prefix_len] ==
':' || ::isspace(line.data[prefix_len])) {
577 char *found = ::strstr(line.cString(), string);
578 if (found && ::isspace(found[-1]) &&
579 (::isspace(found[string_len]) || found[string_len] ==
'\0')) {
588 ::qt_safe_close(cpuinfo_fd);
593static inline quint64 detectProcessorFeatures()
598#if defined __mips_dsp
599 flags |= CpuFeatureDSP;
600# if defined __mips_dsp_rev && __mips_dsp_rev >= 2
601 flags |= CpuFeatureDSPR2;
602# elif defined(Q_OS_LINUX)
603 if (procCpuinfoContains(
"cpu model",
"MIPS 74Kc") || procCpuinfoContains(
"cpu model",
"MIPS 74Kf"))
604 flags |= CpuFeatureDSPR2;
606#elif defined(Q_OS_LINUX)
607 if (procCpuinfoContains(
"ASEs implemented",
"dsp")) {
608 flags |= CpuFeatureDSP;
609 if (procCpuinfoContains(
"cpu model",
"MIPS 74Kc") || procCpuinfoContains(
"cpu model",
"MIPS 74Kf"))
610 flags |= CpuFeatureDSPR2;
633 auto minFeatureTest = minFeature;
634#if defined(Q_PROCESSOR_X86_64) && defined(cpu_feature_shstk)
638 minFeatureTest &= ~CpuFeatureSHSTK;
643 if (
char *disable = getenv(
"QT_NO_CPU_FEATURE"); disable && *disable) {
644#if _POSIX_C_SOURCE
>= 200112L
645 char *saveptr =
nullptr;
646 auto strtok = [&saveptr](
char *str,
const char *delim) {
647 return ::strtok_r(str, delim, &saveptr);
650 while (
char *token = strtok(disable,
" ")) {
654 f &= ~(Q_UINT64_C(1) << i);
659#ifdef RUNNING_ON_VALGRIND
660 bool runningOnValgrind = RUNNING_ON_VALGRIND;
662 bool runningOnValgrind =
false;
664 if (Q_UNLIKELY(!runningOnValgrind && minFeatureTest != 0 && (f & minFeatureTest) != minFeatureTest)) {
665 quint64 missing = minFeatureTest & ~quint64(f);
666 fprintf(stderr,
"Incompatible processor. This Qt build requires the following features:\n ");
668 if (missing & (Q_UINT64_C(1) << i))
671 fprintf(stderr,
"\n");
678 std::atomic_store_explicit(QT_MANGLE_NAMESPACE(qt_cpu_features), f,
std::memory_order_relaxed);
686 printf(
"Processor features: ");
688 if (features & (Q_UINT64_C(1) << i))
690 minFeature & (Q_UINT64_C(1) << i) ?
"[required]" :
"");
693 printf(
"\n!!!!!!!!!!!!!!!!!!!!\n!!! Missing required features:");
695 if (features & (Q_UINT64_C(1) << i))
698 printf(
"\n!!! Applications will likely crash with \"Invalid Instruction\"\n!!!!!!!!!!!!!!!!!!!!");
703#if QT_SUPPORTS_INIT_PRIORITY
705struct QSimdInitializer
707 inline QSimdInitializer() { QT_MANGLE_NAMESPACE(qDetectCpuFeatures)(); }
712Q_DECL_INIT_PRIORITY(01)
static QSimdInitializer initializer;
#define QT_FUNCTION_TARGET_BASELINE
QT_FUNCTION_TARGET_BASELINE uint64_t QT_MANGLE_NAMESPACE qDetectCpuFeatures()
static constexpr auto SimdInitialized
static const int features_indices[]
static uint detectProcessorFeatures()
static const char features_string[]
static const quint64 minFeature
static const uint64_t qCompilerCpuFeatures