Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Clang have something like #pragma GCC target?

I have some code written that uses AVX intrinsics when they are available on the current CPU. In GCC and Clang, unlike Visual C++, in order to use intrinsics, you must enable them on the command line.

The problem with GCC and Clang is that when you enable these options, you're giving the compiler free reign to use those instructions everywhere in your source file. This is very bad when you have header files containing inline functions or template functions, because the compiler will generate these functions with AVX instructions.

When linking, duplicate functions will be discarded. However, because some source files were compiled with -mavx and some were not, the various compilations of the inline/template functions will be different. If you're unlucky, the linker will randomly choose the version that has AVX instructions, causing the program to crash when run on a system without AVX.

GCC solves this with #pragma GCC target. You can turn off the special instructions for the header files, and the code generated will not use AVX:

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

#include "MyHeader.h"

#pragma GCC pop_options

Does Clang have anything like this? It seems to ignore these options and generates AVX code anyway.

like image 886
Myria Avatar asked Sep 11 '17 23:09

Myria


People also ask

Is Clang better than G ++?

Clang is much faster and uses far less memory than GCC. Clang aims to provide extremely clear and concise diagnostics (error and warning messages), and includes support for expressive diagnostics. GCC's warnings are sometimes acceptable, but are often confusing and it does not support expressive diagnostics.

Does Clang support C++?

Clang has support for some of the features of the ISO C++ 2020 standard. You can use Clang in C++20 mode with the -std=c++20 option (use -std=c++2a in Clang 9 and earlier).

Is Clang a good compiler?

But the framework underlying Clang called LLVM is extensible enough to support newer languages like Julia and Swift. From the perspective of C++, both are excellent compilers supporting the C++17 standard. From Incredibuild perspective, both are great tools. That's why we support both Clang and GCC.

Is Clang the same as LLVM?

LLVM is a backend compiler meant to build compilers on top of it. It deals with optimizations and production of code adapted to the target architecture. CLang is a front end which parses C, C++ and Objective C code and translates it into a representation suitable for LLVM.


2 Answers

The Clang equivalent to GCC push_options / GCC target / GCC pop_options are the clang attribute push / clang attribute pop pragmas along with the target attribute:

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

This is the equivalent of:

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

Note that where the GCC target pragma takes a comma-delimited list of target options, the clang target attribute takes a single string, comma-delimited internally.

Clang supports negative target options (such as "no-avx"), but I prefer to use positive options to add to the feature set selected by command line options.

like image 78
ecatmur Avatar answered Sep 20 '22 10:09

ecatmur


You should probably be using static inline instead of inline, so a version of a function compiled with -mavx will only be used by callers from that translation unit.

The linker will still merge actual duplicates, instead of just picking one non-inline definition by name.

This also has the advantage that the compiler doesn't waste time emitting a stand-alone definition for functions that it decides to inline into every caller in that translation unit.


The gcc/clang way makes sense if you're used to it and design your code for it. And note that MSVC need AVX enabled if you're compiling functions that use AVX. Otherwise it will mix VEX and non-VEX encodings, leading to big penalties, instead of using the VEX encoding for something like a 128-bit _mm_add_ps in a horizontal add at the end of a _mm256_add_ps loop.

So you basically have the same problem with MSVC, that compiling _mm_whatever will make AVX-only machine code.

like image 22
Peter Cordes Avatar answered Sep 17 '22 10:09

Peter Cordes