What is the difference between #pragma GCC optimize()
and #pragma GCC target()
and which one to choose when, what are the other options as well?
At a high level, optimize()
is used to control whether certain optimisation techniques are used when compiling code: the big-picture idea is that the compiler can spend more time to produce either faster-executing code or - occasionally - more compact code that needs less memory to run. Optimised code can sometimes be harder to profile or debug, so you may want most of your program un- or less-optimised, but some specific functions that are performance critical to be highly optimised. The pragma gives you that freedom to vary optimisation on a function-by-function basis.
Individual optimisations are listed and explained at https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options
A general overview of the optimise attribute notation and purpose from here:
optimize (level, …)
optimize (string, …)
The optimize attribute is used to specify that a function is to be compiled with different optimization options than specified on the command line. Valid arguments are constant non-negative integers and strings. Each numeric argument specifies an optimization level. Each string argument consists of one or more comma-separated substrings. Each substring that begins with the letter O refers to an optimization option such as
-O0
or-Os
. Other substrings are taken as suffixes to the -f prefix jointly forming the name of an optimization option. See Optimize Options.
‘#pragma GCC optimize’
can be used to set optimization options for more than one function. See Function Specific Option Pragmas, for details about the pragma.Providing multiple strings as arguments separated by commas to specify multiple options is equivalent to separating the option suffixes with a comma (‘,’) within a single string. Spaces are not permitted within the strings.
Not every optimization option that starts with the
-f
prefix specified by the attribute necessarily has an effect on the function. The optimize attribute should be used for debugging purposes only. It is not suitable in production code.
target()
indicates that the compiler can use machine code instructions for specific CPUs. Normally, if you know people running your code might use a different generations of a specific CPU, and each is backwards compatible, then you'd compile for the earliest of those generations so everyone can run your program. With target()
you can compile different functions making use of the more advanced features (machine code instructions, or just optimised for the specific cache sizes or pipelining features etc) of later generations of CPU, then your code can selectively call the faster version on CPUs that can support it.
Further details from here
target (string, …)
Multiple target back ends implement the target attribute to specify that a function is to be compiled with different target options than specified on the command line. One or more strings can be provided as arguments. Each string consists of one or more comma-separated suffixes to the -m prefix jointly forming the name of a machine-dependent option. See Machine-Dependent Options.
The target attribute can be used for instance to have a function compiled with a different ISA (instruction set architecture) than the default. ‘#pragma GCC target’ can be used to specify target-specific options for more than one function. See Function Specific Option Pragmas, for details about the pragma.
For instance, on an x86, you could declare one function with the target("sse4.1,arch=core2") attribute and another with target("sse4a,arch=amdfam10"). This is equivalent to compiling the first function with -msse4.1 and -march=core2 options, and the second function with -msse4a and -march=amdfam10 options. It is up to you to make sure that a function is only invoked on a machine that supports the particular ISA it is compiled for (for example by using cpuid on x86 to determine what feature bits and architecture family are used).
int core2_func (void) __attribute__ ((__target__ ("arch=core2")));
int sse3_func (void) __attribute__ ((__target__ ("sse3")));
Providing multiple strings as arguments separated by commas to specify multiple options is equivalent to separating the option suffixes with a comma (‘,’) within a single string. Spaces are not permitted within the strings.
The options supported are specific to each target; refer to x86 Function Attributes, PowerPC Function Attributes, ARM Function Attributes, AArch64 Function Attributes, Nios II Function Attributes, and S/390 Function Attributes for details.