1#
2#  W A R N I N G
3#  -------------
4#
5# This file is not part of the Qt API.  It exists purely as an
6# implementation detail.  It may change from version to version
7# without notice, or even be removed.
8#
9# We mean it.
10#
11
12# Get the SIMD flags
13load(qt_build_config)
14
15# Set QT_CPU_FEATURES for convenience
16QT_CPU_FEATURES = $$eval(QT_CPU_FEATURES.$$QT_ARCH)
17
18#
19# Set up compilers for SIMD (SSE/AVX, NEON etc)
20#
21defineTest(addSimdCompiler) {
22    name = $$1
23    upname = $$upper($$name)
24    headers_var = $${upname}_HEADERS
25    sources_var = $${upname}_SOURCES
26    csources_var = $${upname}_C_SOURCES
27    asm_var = $${upname}_ASM
28
29    CONFIG($$1) {
30        cflags = $$eval(QMAKE_CFLAGS_$${upname})
31        ltcg: cflags += $$QMAKE_CFLAGS_DISABLE_LTCG
32        contains(QT_CPU_FEATURES, $$name) {
33            # Default compiler settings include this feature, so just add to SOURCES
34            SOURCES += $$eval($$sources_var)
35            export(SOURCES)
36        } else {
37            # We need special compiler flags
38
39            # Split C and C++ sources
40            $$csources_var = $$find($$sources_var, ".*\\.c$")
41            $$sources_var -= $$eval($$csources_var)
42            export($$csources_var)
43            export($$sources_var)
44
45            # Add C++ compiler
46            $${name}_compiler.commands = $$QMAKE_CXX -c $(CXXFLAGS) $$cflags $(INCPATH) ${QMAKE_FILE_IN}
47            msvc: $${name}_compiler.commands += -Fo${QMAKE_FILE_OUT}
48            else: $${name}_compiler.commands += -o ${QMAKE_FILE_OUT}
49
50            $${name}_compiler.dependency_type = TYPE_C
51            $${name}_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
52            $${name}_compiler.input = $$sources_var
53            $${name}_compiler.variable_out = OBJECTS
54            $${name}_compiler.name = compiling[$${name}] ${QMAKE_FILE_IN}
55            silent: $${name}_compiler.commands = @echo compiling[$${name}] ${QMAKE_FILE_IN} && $$eval($${name}_compiler.commands)
56            QMAKE_EXTRA_COMPILERS += $${name}_compiler
57
58            export($${name}_compiler.commands)
59            export($${name}_compiler.dependency_type)
60            export($${name}_compiler.output)
61            export($${name}_compiler.input)
62            export($${name}_compiler.variable_out)
63            export($${name}_compiler.name)
64
65            # Add a C compiler
66            $${name}_c_compiler.commands = $$QMAKE_CC -c $(CFLAGS) $$cflags $(INCPATH) ${QMAKE_FILE_IN}
67            msvc: $${name}_c_compiler.commands += -Fo${QMAKE_FILE_OUT}
68            else: $${name}_c_compiler.commands += -o ${QMAKE_FILE_OUT}
69
70            $${name}_c_compiler.dependency_type = TYPE_C
71            $${name}_c_compiler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
72            $${name}_c_compiler.input = $$csources_var
73            $${name}_c_compiler.variable_out = OBJECTS
74            $${name}_c_compiler.name = compiling[$${name}] ${QMAKE_FILE_IN}
75            silent: $${name}_c_compiler.commands = @echo compiling[$${name}] ${QMAKE_FILE_IN} && $$eval($${name}_c_compiler.commands)
76            QMAKE_EXTRA_COMPILERS += $${name}_c_compiler
77
78            export($${name}_c_compiler.commands)
79            export($${name}_c_compiler.dependency_type)
80            export($${name}_c_compiler.output)
81            export($${name}_c_compiler.input)
82            export($${name}_c_compiler.variable_out)
83            export($${name}_c_compiler.name)
84        }
85
86        # We always need an assembler (need to run the C compiler and without precompiled headers)
87        msvc {
88            # Don't know how to run MSVC's assembler...
89            !isEmpty($$asm_var): error("Sorry, not implemented: assembling $$upname for MSVC.")
90        } else: false {
91            # This is just for the IDE
92            SOURCES += $$eval($$asm_var)
93            export(SOURCES)
94        } else {
95            $${name}_assembler.commands = $$QMAKE_CC -c $(CFLAGS)
96            !contains(QT_CPU_FEATURES, $${name}): $${name}_assembler.commands += $$cflags
97            clang:no_clang_integrated_as: $${name}_assembler.commands += -fno-integrated-as
98            $${name}_assembler.commands += $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
99            $${name}_assembler.dependency_type = TYPE_C
100            $${name}_assembler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
101            $${name}_assembler.input = $$asm_var
102            $${name}_assembler.variable_out = OBJECTS
103            $${name}_assembler.name = assembling[$${name}] ${QMAKE_FILE_IN}
104            silent: $${name}_assembler.commands = @echo assembling[$${name}] ${QMAKE_FILE_IN} && $$eval($${name}_assembler.commands)
105            QMAKE_EXTRA_COMPILERS += $${name}_assembler
106
107            export($${name}_assembler.commands)
108            export($${name}_assembler.dependency_type)
109            export($${name}_assembler.output)
110            export($${name}_assembler.input)
111            export($${name}_assembler.variable_out)
112            export($${name}_assembler.name)
113        }
114
115        HEADERS += $$eval($$headers_var)
116        export(HEADERS)
117        export(QMAKE_EXTRA_COMPILERS)
118    }
119}
120addSimdCompiler(sse2)
121addSimdCompiler(sse3)
122addSimdCompiler(ssse3)
123addSimdCompiler(sse4_1)
124addSimdCompiler(sse4_2)
125addSimdCompiler(aesni)
126addSimdCompiler(shani)
127addSimdCompiler(vaes)
128addSimdCompiler(avx)
129addSimdCompiler(avx2)
130addSimdCompiler(avx512f)
131addSimdCompiler(avx512cd)
132addSimdCompiler(avx512er)
133addSimdCompiler(avx512pf)
134addSimdCompiler(avx512dq)
135addSimdCompiler(avx512bw)
136addSimdCompiler(avx512vl)
137addSimdCompiler(avx512vnni)
138addSimdCompiler(avx512ifma)
139addSimdCompiler(avx512vbmi)
140addSimdCompiler(avx512vbmi2)
141addSimdCompiler(avx512bitalg)
142addSimdCompiler(avx512vpopcntd)
143addSimdCompiler(f16c)
144addSimdCompiler(rdrnd)
145addSimdCompiler(rdseed)
146addSimdCompiler(neon)
147addSimdCompiler(mips_dsp)
148addSimdCompiler(mips_dspr2)
149
150# Haswell sub-architecture
151defineTest(addSimdArch) {
152    name = arch_$$1
153    dependencies = $$2
154    upname = $$upper($$name)
155
156    cpu_features_missing =
157    for(part, dependencies) {
158        !contains(QT_CPU_FEATURES, $$part): cpu_features_missing = 1
159    }
160
161    CONFIG += $$name
162    isEmpty(cpu_features_missing): QT_CPU_FEATURES += $$name
163
164    export(QT_CPU_FEATURES)
165    export(CONFIG)
166    addSimdCompiler($$name)
167}
168
169isEmpty(QMAKE_CFLAGS_ARCH_HASWELL): QMAKE_CFLAGS_ARCH_HASWELL = $$QMAKE_CFLAGS_AVX2
170avx2: addSimdArch(haswell, avx2 bmi bmi2 f16c fma lzcnt popcnt)
171
172# Follow the Intel compiler's lead and define profiles of AVX512 instructions
173defineTest(addAvx512Profile) {
174    name = $$1
175    dependencies = $$2
176    upname = $$upper($$name)
177    varname = QMAKE_CFLAGS_$$upname
178
179    cpu_features_missing =
180    cflags = $$QMAKE_CFLAGS_ARCH_HASWELL $$QMAKE_CFLAGS_AVX512F
181    for(part, dependencies) {
182        !CONFIG($$part): return()           # Profile isn't supported by the compiler
183
184        uppart = $$upper($$part)
185        cflags *= $$eval(QMAKE_CFLAGS_$${uppart})
186        !contains(QT_CPU_FEATURES, $$uppart): cpu_features_missing += $$uppart
187    }
188
189    CONFIG += $$name
190    isEmpty(cpu_features_missing): QT_CPU_FEATURES += $$name
191    $$varname = $$cflags
192
193    export(QT_CPU_FEATURES)
194    export(CONFIG)
195    export($$varname)
196    addSimdCompiler($$name)
197}
198addAvx512Profile(avx512common, avx512cd)
199addAvx512Profile(avx512core, avx512cd avx512bw avx512dq avx512vl)
200