What Does '#Pragma Gcc Optimize ("O3")' Mean

C code optimization using #pragma GCC optimize

An ICE (internal compiler error) leading to a segmentation fault is always a bug in the compiler, which is why it asks you to report the bug. You should not be able to crash the compiler with any source code, valid or invalid. (There are all sorts of things that may happen, most often involving a refusal to compile invalid code, but crash isn't one of them.)

Since GCC 4.6.1 is current, why not consider an upgrade to a more recent version of GCC (not that 4.4.3 is all that old).

Before submitting a bug report, you should try to minimize your reproduction. Everything from line 494 onwards is probably immaterial; with luck, you can reduce the material between lines 1 and 493 from almost 500 down to 20 or so. You should certainly aim to reduce it as much as possible while preserving the error. Before you start chopping the code, preserve the version that crashes the compiler. As you successfully remove the code while preserving the crash, check each successive version into your VCS. (You are using a VCS, aren't you? That's a rhetorical question; if you're not, now's a good time to start. You need one to avoid making changes that can't be undone.) Try to eliminate non-standard headers (ones you've written) before eliminating standard headers. Try to get rid of as many headers as possible. Note the request for preprocessed source - the code reduction I'm talking of reduces the size of the preprocessed source.

pragma gcc optimize in function

Fairly useful way is to split up a code to functions, e.g.:

int main() {
for (int i = 0; i < 5; ++i) printf("%d", i);

for (int j = 0; j < 5; ++j) printf("%d", 5 - i);
}

then becomes


int main() {
fn1();
fn2();
}

inline void fn1() {
for (int i = 0; i < 5; ++i) printf("%d", i);
}

// here you can place pragma

inline void fn2() {
for (int j = 0; j < 5; ++j) printf("%d", 5 - i);
}

Most probably, functions would be inlined and compiler can understand its pragams as according to doc:

#pragma GCC optimize (string, …)

This pragma allows you to set global optimization options for functions defined later in the source file.

Moreover, I would consider to put these functions to files, so you are able to have a finer-grained flags specific to a compilation unit and do not depend on compiler-specific pragmas (which I believe does not work on clang/inter-compiler/msvc/etc).

std::min vs ternary gcc auto vectorization with #pragma GCC optimize (O3)

Summary: don't use #pragma GCC optimize. Use -O3 on the command line instead, and you'll get the behavior you expect.

GCC's documentation on #pragma GCC optimize says:

Each function that is defined after this point is treated as if it had been declared with one optimize(string) attribute for each string argument.

And the optimize attribute is documented as:

The optimize attribute is used to specify that a function is to be compiled with different optimization options than specified on the command line. [...] The optimize attribute should be used for debugging purposes only. It is not suitable in production code. [Emphasis added, thanks Peter Cordes for spotting the last part.]

So, don't use it.

In particular, it looks like specifying #pragma GCC optimize ("O3") at the top of your file is not actually equivalent to using -O3 on the command line. It turns out that the former doesn't result in std::min being inlined, and so the compiler actually does assume that it might modify global memory, such as your a,b arrays. This naturally inhibits vectorization.

A careful reading of the documentation for __attribute__((optimize)) makes it look like each of the functions main() and std::min() will be compiled as if with -O3. But that's not the same as compiling the two of them together with -O3, as only in the latter case would interprocedural optimizations like inlining be available.

Here is a very simple example on godbolt. With #pragma GCC optimize ("O3") the functions foo() and please_inline_me() are each optimized, but please_inline_me() does not get inlined. But with -O3 on the command line, it does.

A guess would be that the optimize attribute, and by extension #pragma GCC optimize, causes the compiler to treat the function as if its definition were in a separate source file which was being compiled with the specified option. And indeed, if std::min() and main() were defined in separate source files, you could compile each one with -O3 but you wouldn't get inlining.

Arguably the GCC manual should document this more explicitly, though I guess if it's only meant for debugging, it might be fair to assume it's intended for experts who would be familiar with the distinction.

If you really do compile your example with -O3 on the command line, you get identical (vectorized) assembly for both versions, or at least I did. (After fixing the backwards comparison: your ternary code is computing max instead of min.)

How to change optimization level of one function?

It's described in https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#Common-Function-Attributes

You can change the level by declaring the function like this:

void some_func() __attribute__ ((optimize(1))) {
....
}

To force optimization level 1 for it.

IBM XL C/C++ equivalent to #pragma GCC optimize

An IBM XL C/C++ for AIX V13.1 option that you could use to compile that one source file at -O2 is #pragma options optimize=2. Info about it can be found online here or in the PDF here. If you want to override -O3 that has already been specified on the command line, and control it at a function level, you may use #pragma option_override(<your function name>, "opt(level, 2)"). Info about it can be found online here or in the PDF here. You can also achieve the same thing by modifying your Makefile so that one source file gets compiled at -O2 instead of -O3.

Also, are you sure the error message you reported starting with tea.cpp:27:26 came from IBM XL C/C++ for AIX V13.1? It doesn't look like it's in the format of that product's diagnostic messages.

We will continue to monitor for your comments on Stack Overflow (tagging with xlc helps us find it), but you may find you can get a faster response time if you post your questions on our forum at http://ibm.biz/xl-power-compilers-forum, which the IBM compiler development team monitors more actively.

How many GCC optimization levels are there?

To be pedantic, there are 8 different valid -O options you can give to gcc, though there are some that mean the same thing.

The original version of this answer stated there were 7 options. GCC has since added -Og to bring the total to 8.

From the man page:

  • -O (Same as -O1)
  • -O0 (do no optimization, the default if no optimization level is specified)
  • -O1 (optimize minimally)
  • -O2 (optimize more)
  • -O3 (optimize even more)
  • -Ofast (optimize very aggressively to the point of breaking standard compliance)
  • -Og (Optimize debugging experience. -Og enables optimizations that do not interfere with debugging. It should be the
    optimization level of choice for the standard edit-compile-debug cycle, offering a reasonable level of optimization
    while maintaining fast compilation and a good debugging experience.)
  • -Os (Optimize for size. -Os enables all -O2 optimizations that do not typically increase code size. It also performs further optimizations
    designed to reduce code size.
    -Os disables the following optimization flags: -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version)

There may also be platform specific optimizations, as @pauldoo notes, OS X has -Oz.

__FILE__ macro shows full path

Try

#include <string.h>

#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)

For Windows use '\\' instead of '/'.



Related Topics



Leave a reply



Submit