是否可以在同一个编译单元中混合使用VEX和非VEX编码的SIMD内在函数?我想这样做是为了简化代码发布到不同的编译器作为单个文件模块。
答案 0 :(得分:4)
您不需要这样做,并且通常使用-march=haswell
与-march=core2
或其他东西构建整个文件会更好,因此您可以设置调整选项以及目标指令集
但是单独的编译单元使得内联小函数变得更加困难,所以如果你小心实际上没有SSE-AVX transition penalties混合VEX /非VEX而没有{{1或者将VEX编码指令放入在没有AVX支持的CPU上运行的代码路径中。
IDK在内联时编译器如何尊重目标属性,但链接时优化可以内联使用不同选项编译的编译单元的代码,以及不会导致问题的AFAIK。GNU C function attributes, yes 。这适用于gcc和clang,但显然不适用于ICC,即使它不拒绝属性语法。
显然它不适用于MSVC,它无论如何都有不同的命令行选项。使用MSVC,可以编译一个使用AVX内在函数但没有vzeroupper
的文件,但不要这样做;它只会将VEX编码用于传统SSE无法编码的指令,如_mm_permutevar_ps
(vpermilps
),从而导致转换惩罚。
GNU C方式:
/arch:AVX
Compiled (on the Godbolt compiler explorer)使用gcc和clang #include <immintrin.h>
__m128 addps_sse(__m128 x, __m128 y) {
return x+y; // GNU C alternative to _mm_add_ps.
}
__attribute((target("avx"))) // <<<<<<<<<<< This line
__m128 addps_avx(__m128 x, __m128 y) {
return x+y;
}
使SSE4.2可用(并调整Nehalem),但不启用AVX。
-O3 -march=nehalem
当然,gcc和clang都发出相同的asm。 ICC对这两个版本使用addps_sse:
addps xmm0, xmm1
ret
addps_avx:
vaddps xmm0, xmm0, xmm1
ret
(非VEX)。我没有检查ICC是否允许在启用了AVX的函数内部addps
内部函数,但是gcc应该。