Clang是否有#pragma GCC目标?

时间:2017-09-11 23:37:44

标签: clang intrinsics avx pragma

我编写了一些使用AVX内在函数的代码,当它们在当前CPU上可用时。在GCC和Clang中,与Visual C ++不同,为了使用内在函数,必须在命令行中启用它们。

GCC和Clang的问题在于,当您启用这些选项时,您可以让编译器自由统治,以便在源文件中的任何位置使用这些指令。当你有包含内联函数或模板函数的头文件时,这是非常糟糕的,因为编译器将使用AVX指令生成这些函数。

链接时,将丢弃重复的功能。但是,由于某些源文件是使用-mavx编译的,而有些则不是,因此内联/模板函数的各种编译将有所不同。如果你运气不好,链接器将随机选择具有AVX指令的版本,导致程序在没有AVX的系统上运行时崩溃。

GCC用#pragma GCC target解决了这个问题。您可以关闭头文件的特殊说明,生成的代码不会使用AVX:

#pragma GCC push_options
#pragma GCC target("no-avx")

#include "MyHeader.h"

#pragma GCC pop_options

Clang有这样的事吗?它似乎忽略了这些选项并且无论如何都会生成AVX代码。

2 个答案:

答案 0 :(得分:6)

您可能应该使用static inline而不是inline,因此使用-mavx编译的函数版本将仅由该翻译单元的调用者使用。

链接器仍将合并实际的重复项,而不是仅按名称选择一个非内联定义。

这样做的另一个好处是,编译器不会浪费时间为它决定内联到该翻译单元中每个调用者的函数发出独立定义。

如果你已经习惯了它并为它设计代码,那么gcc / clang的方法是有意义的。请注意,如果您正在编译使用AVX的功能,则MSVC需要启用AVX。否则它将混合VEX和非VEX编码,导致严重的惩罚,而不是在_mm_add_ps循环结束时在水平加法中使用VEX编码,例如128位_mm256_add_ps

因此,基本上MSVC存在同样的问题,编译_mm_whatever将只生成AVX机器代码。

答案 1 :(得分:2)

GCC push_options / GCC target / GCC pop_options等效的Clang是clang attribute push / clang attribute pop pragmastarget attribute

#pragma clang attribute push (__attribute__((target("pclmul,sse4.1,ssse3"))), apply_to=function)
// ...
#pragma clang attribute pop

这等效于:

#pragma GCC push_options
#pragma GCC target("pclmul", "sse4.1", "ssse3")
// ...
#pragma GCC pop_options

请注意,在GCC target编译指示采用逗号分隔的目标选项列表的情况下,clang target属性采用单个字符串,内部以逗号分隔。

Clang支持否定目标选项(例如"no-avx"),但是我更喜欢使用肯定选项来添加命令行选项选择的功能集。