Issue
I am quite familiar with GCC -O3 flag, but how it differs from -Os, in which situation we should prefer one over other?
Solution
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.
Answered By - CmdrMoozy Answer Checked By - Mary Flores (WPSolving Volunteer)