I am quite familiar with GCC -O3 flag, but how it differs from -Os, in which situation we should prefer one over other?
-
2Doesn't `-Os` optimize of size and `-O1`, `-O2`, `-O3` for speed? – fvdalcin Oct 30 '13 at 16:53
-
3`-Os` optimizes for executable size. You can see which specific flags are switched on [here](http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html). – BoBTFish Oct 30 '13 at 16:53
-
4["-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."](http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html). Use it for embedded platforms, where code size might be more important than bleeding edge speed (or you might not even get more speed with O3, just bigger code size) – Mihai Todor Oct 30 '13 at 16:54
-
3See also: [Is optimisation level -O3 dangerous in g++?](http://stackoverflow.com/questions/11546075/is-optimisation-level-o3-dangerous-in-g) – Marc.2377 May 23 '16 at 02:43
5 Answers
The GCC documentation describes what these options do very explicitly.
-O3 tries to optimize code very heavily for performance. It includes all of the optimizations -O2 includes, plus some more.
-Os, on the other hand, instructs GCC to "optimize for size." It enables all -O2 optimizations which do not increase the size of the executable, and then it also toggles some optimization flags to further reduce executable size.
Note that I've been deliberately a bit vague with my descriptions - read the GCC documentation for a more in-depth discussion of exactly which flags are enabled for either optimization level.
I believe the -O* optimization levels are just that - mutually exclusive, distinct levels of optimization. It doesn't really make sense to mix them, since two levels will enable or leave out flags that the other one intentionally leaves out or enables (respectively). If you want to mix and match (you probably don't actually want to do this, unless you have a really good reason to want a specific set of flags), you are best off reading the documentation and mixing and matching the flags each level enables by hand.
I think I'll also link this article from the Gentoo Linux Wiki, which talks about optimization flags as they relate to building the packages for the operating system. Obviously not all of this is applicable, but it still contains some interesting information - for one:
Compiling with -O3 is not a guaranteed way to improve performance, and in fact in many cases can slow down a system due to larger binaries and increased memory usage. -O3 is also known to break several packages. Therefore, using -O3 is not recommended.
According to that article, -O2 is, most of the time, "as good as" -O3, and is safer to use, regarding broken executable output.

- 3,870
- 3
- 19
- 31
-
1I wouldn't consider a bad practice to use O3 on most environments.Indeed the code bloat might be huge for embbeded applications and maybe some other contexts so then I agree with you that O3 might be better to be avoided. On the other hand O3 is standard-compliant so the fact that some packages break with O3 just means that the packages are non standard-compliant. I use O3 until a package I absolutely need breaks then I reduce it to O2 – Spyros Mourelatos Oct 12 '21 at 07:46
-
GCC `-O3` is more likely to be helpful than in the past, and bloat problems are probably less bad. GCC used to enable `-funroll-loops` as part of `-O3`, but doesn't anymore (only with `-fprofile-use` with PGO data available). Upcoming GCC 12 changes `-O2` to include `-ftree-vectorize` (SIMD) like clang -O2 does; previously it used to only be enabled at `-O3`. That *can* bloat loops, but it can also give major speedups for loops over arrays, especially when data is hot in L2 cache. TL:DR: **The advice to avoid `-O3` is probably outdated for most cases** – Peter Cordes Apr 05 '22 at 02:39
I suggest to read GCC documentation. -O3 is for getting a fast running code (even at the expense of some code bloat), while -Os
is optimizing for size of the generated code.
There are tons of other (obscure) GCC optimization flags (e.g. -fgcse-sm
) many of which are not enabled even at -O3
.
You might perhaps be also interested by -flto (for Link-Time Optimization) to be used, in addition of e.g. -O3
or -Os
, both at compile time and at link time. Then see also this answer.
At last, take care to use the latest version of GCC (currently 4.8 at end of 2013), because GCC is improving significantly its optimizations.
You might want to also use -mtune=native (at least for x86).
And you might even write your own optimization pass, specific to your own particular libraries and APIs, perhaps using MELT plugin.
As CmdrMoozy answered you might prefer using -O2
over -O3
(but notice that recent GCC versions have improved a lot their -O3
, so the Gentoo citation -recommending against -O3
and in favor of -O2
is becoming less relevant.).
Also, as this SlashDot-ed Stack paper (by Xi Wang, Nickolai Zeldovich, M. Frans Kaashoek, and Armando Solar-Lezama) shows, many programs are not entirely C standard compliant and are not happy (and behave incorrectly) when some valid optimizations are done. Undefined behavior is a tricky subject.
BTW, notice that using -O3
usually makes your compilation time much longer, and brings often (but not always) at most a few percent more performance than -O2
or even -O1
.... (it is even worse with -flto
). This is why I rarely use it.

- 36,492
- 15
- 194
- 265

- 223,805
- 18
- 296
- 547
It depends. Do you need to optimize speed or size?
-O3
Optimize yet more. -O3 turns on all optimizations specified by -O2 and also turns on the -finline-functions, -funswitch-loops, -fpredictive-commoning, -fgcse-after-reload, -ftree-loop-vectorize, -ftree-slp-vectorize, -fvect-cost-model, -ftree-partial-pre and -fipa-cp-clone options.-O0
Reduce compilation time and make debugging produce the expected results. This is the default.-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
Actually, -O is a shorthand for a long list of independent optimizations. If you don't know what you need, just go for -O3.

- 7,807
- 7
- 51
- 95

- 3,139
- 21
- 41
-
-
I would suggest -O2 or -Os, but still I concur that if one doesn't know which they need, anything will work. – Vorac Oct 30 '13 at 16:57
-
2If you use individual flags yes. But if you specify both -Os -O3 the second will overlap the first one... – opalenzuela Oct 30 '13 at 16:57
-O3 optimizes for speed, whereas -Os optimizes for space. That means -O3 will give you a fast executable, but it may be rather large, and -Os gives you a smaller executable, but it might be slower.
Space and time efficiency is usually a trade-off. Faster algorithms tend to take up more space, where in-place algorithms (algorithms that don't increase the space usage) tend to be less efficient.
Usually modern computers have plenty of memory space, so -O3 is usually preferable. However if you're programing for something with low-ram (like a small device) you might prefer -Os

- 73,987
- 14
- 40
- 69
This is not really possible to answer, a simple rules would be to use optimize for speed on critical code path, and optimize for size on non critical code path such as loading, ...
Some compilers can work in two passes to decide it for you, a first one create a special executable with profiling support, you run the application to collect data and a second compilation is able to decide, based on the data of what is best. It allows de-virtualization, branch prediction, ...

- 8,573
- 22
- 36
-
You're talking about Profile-guided optimization, PGO. `gcc -O3 -fprofile-generate` / test run *with input data that exercises all important hot paths, but not the rare cases* / `gcc -O3 -fprofile-use`. Combine with `-flto` and other useful options like `-march=native -fno-math-errno` as usual. – Peter Cordes Apr 05 '22 at 02:43