In the early days of gcc (2.8 etc.) and in the times of egcs, and redhat 2.96 -O3 was quite buggy sometimes. But this is over a decade ago, and -O3 is not much different than other levels of optimizations (in buggyness).
It does however tend to reveal cases where people rely on undefined behavior, due to relying more strictly on the rules, and especially corner cases, of the language(s).
As a personal note, I am running production software in the financial sector for many years now with -O3 and have not yet encountered a bug that would not have been there if I would have used -O2.
By popular demand, here an addition:
-O3 and especially additional flags like -funroll-loops (not enabled by -O3) can sometimes lead to more machine code being generated. Under certain circumstances (e.g. on a cpu with exceptionally small L1 instruction cache) this can cause a slowdown due to all the code of e.g. some inner loop now not fitting anymore into L1I. Generally gcc tries quite hard to not to generate so much code, but since it usually optimizes the generic case, this can happen. Options especially prone to this (like loop unrolling) are normally not included in -O3 and are marked accordingly in the manpage. As such it is generally a good idea to use -O3 for generating fast code, and only fall back to -O2 or -Os (which tries to optimize for code size) when appropriate (e.g. when a profiler indicates L1I misses).
If you want to take optimization into the extreme, you can tweak in gcc via --param the costs associated with certain optimizations. Additionally note that gcc now has the ability to put attributes at functions that control optimization settings just for these functions, so when you find you have a problem with -O3 in one function (or want to try out special flags for just that function), you don't need to compile the whole file or even whole project with O2.
otoh it seems that care must be taken when using -Ofast, which states:
-Ofast enables all -O3 optimizations.
It also enables optimizations that are not valid for all standard
compliant programs.
which makes me conclude that -O3 is intended to be fully standards compliant.
-O3
is considered particularly buggy? I think perhaps it can make undefined behavior "worse" as it may do weird and wonderful things based on certain assumptions, but that would be your own fault. So generally, I'd say it's fine. – Inion-O2
turns on-fstrict-aliasing
, and if your code survives that then it'll probably survive other optimizations, since that's one that people get wrong over and over. That said,-fpredictive-commoning
is only in-O3
, and enabling that might enable bugs in your code caused by incorrect assumptions about concurrency. The less wrong your code is, the less dangerous optimization is ;-) – Reliable-Ofast
, it turns off IEEE-compliant handling of NaNs for example – Inappetence