将 SSE2 和 AVX 内在函数与不同的编译器混合
Mixing SSE2 and AVX intrinsics with different compilers
是否可以在同一编译单元中混合使用 VEX 和非 VEX 编码的 SIMD 内在函数?我想这样做是为了简化将代码作为单个文件模块发布到不同编译器的过程。
你不需要这样做,通常只用 -march=haswell
与 -march=core2
或其他东西构建整个文件会更好,这样你就可以设置调整选项和目标指令集。
但是单独的编译单元使得让小函数内联变得更加困难,所以如果你注意不要真正导致 混合 VEX/non-VEX,那么这里可能有一个 use-case没有 vzeroupper
,或将 VEX-coded 指令放入 运行 在不支持 AVX 的 CPU 上的代码路径中。
IDK 内联时编译器如何尊重目标属性,但是 link-time 优化也可以从使用不同选项编译的编译单元中内联代码,并且 AFAIK 不会导致问题。
和GNU C function attributes, yes。这适用于 gcc 和 clang,但显然不适用于 ICC,即使它不拒绝属性语法。
显然它不适用于 MSVC,它有不同的命令行选项。使用 MSVC,您 可以 编译一个使用 AVX 内在函数而不 /arch:AVX
的文件,但不要那样做;它将仅对传统 SSE 根本无法编码的指令使用 VEX 编码,例如 _mm_permutevar_ps
(vpermilps
),导致转换惩罚。
GNU C 方式:
#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;
}
Compiled (on the Godbolt compiler explorer) 与 gcc 和 clang -O3 -march=nehalem
使 SSE4.2 可用(并为 Nehalem 调整),但不启用 AVX。
addps_sse:
addps xmm0, xmm1
ret
addps_avx:
vaddps xmm0, xmm0, xmm1
ret
当然,gcc 和 clang 都发出相同的 asm。 ICC 对两个版本都使用 addps
(non-VEX)。我没有检查 ICC 是否允许 _mm256
启用 AVX 的函数内部函数,但 gcc 应该。
是否可以在同一编译单元中混合使用 VEX 和非 VEX 编码的 SIMD 内在函数?我想这样做是为了简化将代码作为单个文件模块发布到不同编译器的过程。
你不需要这样做,通常只用 -march=haswell
与 -march=core2
或其他东西构建整个文件会更好,这样你就可以设置调整选项和目标指令集。
但是单独的编译单元使得让小函数内联变得更加困难,所以如果你注意不要真正导致 vzeroupper
,或将 VEX-coded 指令放入 运行 在不支持 AVX 的 CPU 上的代码路径中。
IDK 内联时编译器如何尊重目标属性,但是 link-time 优化也可以从使用不同选项编译的编译单元中内联代码,并且 AFAIK 不会导致问题。
和GNU C function attributes, yes。这适用于 gcc 和 clang,但显然不适用于 ICC,即使它不拒绝属性语法。
显然它不适用于 MSVC,它有不同的命令行选项。使用 MSVC,您 可以 编译一个使用 AVX 内在函数而不 /arch:AVX
的文件,但不要那样做;它将仅对传统 SSE 根本无法编码的指令使用 VEX 编码,例如 _mm_permutevar_ps
(vpermilps
),导致转换惩罚。
GNU C 方式:
#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;
}
Compiled (on the Godbolt compiler explorer) 与 gcc 和 clang -O3 -march=nehalem
使 SSE4.2 可用(并为 Nehalem 调整),但不启用 AVX。
addps_sse:
addps xmm0, xmm1
ret
addps_avx:
vaddps xmm0, xmm0, xmm1
ret
当然,gcc 和 clang 都发出相同的 asm。 ICC 对两个版本都使用 addps
(non-VEX)。我没有检查 ICC 是否允许 _mm256
启用 AVX 的函数内部函数,但 gcc 应该。