AVX2 禁用 SSE 指令集的 gcc 目标

J.N*_*.N. 5 c gcc avx2

我们有一个要使用 AVX2 编译的翻译单元(仅此一个):\n它告诉 GCC\xc2\xa0upfront,文件中的第一行:

\n\n
#pragma GCC target "arch=core-avx2,tune=core-avx2"\n
Run Code Online (Sandbox Code Playgroud)\n\n

这曾经适用于 GCC 4.8 和 4.9,但从 6 开始(也尝试过 7 和 8),我们收到此警告(我们将其视为错误):

\n\n
error: SSE instruction set disabled, using 387 arithmetics\n
Run Code Online (Sandbox Code Playgroud)\n\n

在第一个返回浮点数的函数上。我尝试像这样启用 SSE 4.2 (以及 avx 和 avx2)

\n\n
#pragma GCC target "sse4.2,arch=core-avx2,tune=core-avx2"\n
Run Code Online (Sandbox Code Playgroud)\n\n

但这还不够,错误仍然存​​在。

\n\n

编辑:

\n\n

相关编译器标志,我们针对大多数内容以 AVX 为目标:

\n\n
-mfpmath=sse,387 -march=corei7-avx -mtune=corei7-avx\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑2:最小样本:

\n\n
#pragma GCC target "arch=core-avx2,tune=core-avx2"\n\n#include <immintrin.h>\n#include <math.h>\n\nstatic inline float\nlg1pf( float x ) {\n    return log1pf(x)*1.44269504088896338700465f;\n}\n\nint main()\n{\n  log1pf(2.0f);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这样编译:

\n\n
gcc -o test test.c -O2 -Wall -Werror -pedantic -std=c99 -mfpmath=sse,387 -march=corei7-avx -mtune=corei7-avx\n\nIn file included from /home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/immintrin.h:45:0,\n                 from test.c:3:\n/home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/avx512fintrin.h: In function \xe2\x80\x98_mm_add_round_sd\xe2\x80\x99:\n/home/xxx/gcc-7.1.0/lib/gcc/x86_64-pc-linux-gnu/7.1.0/include/avx512fintrin.h:1412:1: error: SSE register return with SSE disabled\n {\n ^\n
Run Code Online (Sandbox Code Playgroud)\n\n

GCC 详细信息(尽管我没有用于编译它的标志)\n gcc --version\n gcc (GCC) 7.1.0\n 版权所有 (C) 2017 Free Software Foundation, Inc.\n 这是免费软件;请参阅复制条件的来源。没有保修;甚至不是为了适销性或特定用途的适用性。

\n\n

潜在的解决方案

\n\n
#pragma GCC target "avx2"\n
Run Code Online (Sandbox Code Playgroud)\n\n

无需对代码进行其他更改即可为我工作。\n将该属性应用于各个函数也不起作用:

\n\n

相关问题:

\n\n
__attribute__((__target__("arch=broadwell")))  // does not compile\n__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }\n\n__attribute__((__target__("avx2,arch=broadwell"))) // does not compile\n__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }\n\n__attribute__((__target__("avx2"))) // compiles\n__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }\n
Run Code Online (Sandbox Code Playgroud)\n

Pet*_*des 5

这看起来像一个错误。 #pragma GCC targetbefore#include <immintrin.h>以某种方式破坏了标头,不知道为什么。即使在命令行上启用了 AVX2 -march=haswell,#pragma 似乎也会破坏此后定义的任何内在函数的内联。

#pragma 您可以在标头之后使用,但随后使用命令行上未启用的内联函数会失败。

即使是更现代的目标名称(如)#pragma GCC target "arch=haswell"也会导致错误,因此并不是说旧的模糊目标名称(如)corei7-avx一般会被破坏。他们仍然在命令行上工作。如果您想为整个文件启用某些功能,标准方法是使用编译器选项而不是编译指示。

不过,GCC 确实声称通过编译指示或 来支持每个函数的目标选项__attribute__https://gcc.gnu.org/onlinedocs/gcc/Function-Specific-Option-Pragmas.html


据我所知(Godbolt编译器资源管理器与gcc8.1)。Clang 不受影响,因为它忽略了#pragma GCC target. (所以这意味着它#pragma不太可移植;您可能希望您的代码可以与任何 GNU C 编译器一起使用,而不仅仅是 gcc 本身。)

 // breaks gcc when before immintrin.h
 // #pragma GCC target "arch=haswell"

#include <immintrin.h>
#include <math.h>

//#pragma GCC target "arch=core-avx2,tune=core-avx2"
#pragma GCC target "arch=haswell"

//static inline 
float
lg1pf( float x ) {
    return log1pf(x)*1.44269504088896338700465f;
}

// can accept / return wide vectors
__m128 nop(__m128 a) { return a; }
__m256 require_avx(__m256 a) { return a; }
// but error on using intrinsics if #include happened without target options
//__m256 use_avx(__m256 a) { return _mm256_add_ps(a,a); }

// this works, though, because AVX is enabled at this point
// presumably so would  __builtin_ia32_whatever
// Without `arch=haswell`, this breaks, so we know the pragma "worked"
__m256 use_native_vec(__m256 a) { return a+a; }
Run Code Online (Sandbox Code Playgroud)