The default optimization level for compiling C programs using GCC is -O0. which turns off all optimizations according to GCC documentation. for example:
gcc -O0 test.c
However, to check if -O0 is really turning off all optimizations. I executed this command:
gcc -Q -O0 --help=optimizers
And here, I was a bit surprised. I got around 50 options enabled. Then, I checked the default arguments passed to gcc using this:
gcc -v
I got this:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-
2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --
enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --
program-suffix=-4.8 --enable-shared --enable-linker-build-id --
libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-
gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-
sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-
time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --
with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-
cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-
java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-
jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-
directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-
gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --
with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04)
So my conclusion is that the -O0
flag I provided to the program was not overridden by something else.
In fact, I am seeking to implement from scratch a tool that generates random sequences of optimization options and compare generated sequences to default levels 0-3. Just like "acovea". So that, I would like to compare my generated sequences to a zero-optimization level (which should be -O0
)
Can you explain me why 50 options are enabled by default in -O0
?
One idea I have in mind is to compile with -O0
and turn off default optimizations in -O0
using -fno-OPTIMIZATION_NAME
50 times. What do you think?
Use -O0 to disable them and use -S to output assembly. -O3 is the highest level of optimization. Starting with gcc 4.8 the optimization level -Og is available. It enables optimizations that do not interfere with debugging and is the recommended default for the standard edit-compile-debug cycle.
GCC has a range of optimization levels, plus individual options to enable or disable particular optimizations. The overall compiler optimization level is controlled by the command line option -On, where n is the required optimization level, as follows: -O0 . (default).
The compiler optimizes to reduce the size of the binary instead of execution speed. If you do not specify an optimization option, gcc attempts to reduce the compilation time and to make debugging always yield the result expected from reading the source code.
Optimization level -O3 -O3 instructs the compiler to optimize for the performance of generated code and disregard the size of the generated code, which might result in an increased code size. It also degrades the debug experience compared to -O2 .
Stricto sensu, the GCC compiler middle-end is made of a sequence (actually a nested tree, dynamically changing during compilation) of optimization passes, so if GCC did no optimization, it won't be able to emit any code.
Think of it another way: the input language to GCC is quite rich (even for plain C, where you have while
, for
, ....) but the intermediate Gimple language is much more poor (in particular Gimple/SSA) so you need to apply some transformations to go from source AST to Gimple. These transformations are optimization passes, almost by definition.
See also the pictures from that answer and this one (an SVG image) and read the references mentioned here.
You should understand -O0
as disabling any additional optimizations (e.g. provided by -O1
etc...) not needed to produce some executable.
Well
gcc -O0 `gcc -Q -O0 --help=optimizers 2>&1 | perl -ane 'if ($F[1] =~/enabled/) {$F[0] =~ s/^\s*-f/-fno-/g;push @o,$F[0];}} END {print join(" ", @o)'` your args here
will turn all the options off (yuck).
More seriously, if you are covering all optimisation states, make a list of the optimisation flags (which you need to do anyway), and explicitly turn on or off each one with -fmyflag
or -fno-myflag
. This in essence answers your second question.
You may, however, consider it not worth your while playing with turning off optimisations that are on for all -O
levels.
As to why it's like that, that's somewhere between 'too broad' (i.e. you would have to ask whoever wrote it) and 'because that's what https://github.com/gcc-mirror/gcc/blob/master/gcc/toplev.c does'.
Note the documentation does not say that -O0
disables optimisation. It says (from the man page):
-O0
Reduce compilation time and make debugging produce the expected results. This is the default.
By implication there may be optimisations with do not increase compilation time and do not affect debugging, and these will be left on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With