Clang是否具有#Pragma GCC目标之类的东西



我写了一些代码,该代码在当前CPU上可用时使用AVX Intrinsics。在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代码。

等效于GCC push_options / GCC target / GCC pop_options的叮当声是clang attribute push / clang attribute pop Pragmas,以及target属性:

#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 pragma获取目标选项的逗号列表的地方,Clang target属性会在内部进行单个字符串,以逗号限制在内部。

clang支持负目标选项(例如"no-avx"),但我更喜欢使用正面选项添加到由命令行选项选择的功能集中。

您可能应该使用 static inline而不是 inline,因此只有从该翻译单元中的呼叫者使用-mavx编译的函数的版本。

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

这也具有一个优势,即编译器不会浪费时间发出独立的定义,以确定其决定介入该翻译单元中的每个呼叫者。


如果您习惯了GCC/CLANG的方式,并为其设计代码是有道理的。并请注意,如果您要编译使用AVX的功能,则需要启用MSVC。否则,它将混合vex和非vex编码,导致大规模惩罚,而不是在 _mm256_add_ps环的末端使用vex编码为128位_mm_add_ps之类的东西。

。 。

因此,您基本上遇到了MSVC相同的问题,编译_mm_whatever将制作仅AVX的机器代码。