禁用GCC中的所有优化选项

sta*_*icx 14 c optimization gcc performance-testing compiler-optimization

使用GCC编译C程序的默认优化级别是-O0.根据GCC文档关闭所有优化.例如:

    gcc -O0 test.c 
Run Code Online (Sandbox Code Playgroud)

但是,要检查-O0是否真的关闭了所有优化.我执行了这个命令:

    gcc -Q -O0 --help=optimizers 
Run Code Online (Sandbox Code Playgroud)

在这里,我有点惊讶.我启用了大约50个选项.然后,我使用以下方法检查了传递给gcc的默认参数:

    gcc -v 
Run Code Online (Sandbox Code Playgroud)

我懂了:

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) 
Run Code Online (Sandbox Code Playgroud)

所以我的结论是,-O0我提供给程序的旗帜没有被其他东西所覆盖.

实际上,我正在寻求从头开始实现一个生成随机优化选项序列的工具,并将生成的序列与默认级别0-3进行比较.就像"acovea".所以,我想将我生成的序列与零优化级别(应该是-O0)进行比较

你能解释一下为什么默认启用50个选项-O0吗?

我想到的一个想法是使用50次编译-O0和关闭默认优化.你怎么看?-O0-fno-OPTIMIZATION_NAME

Bas*_*tch 15

Stricto sensu,GCC编译器中端由优化传递的序列(实际上是嵌套树,在编译期间动态改变)组成,因此如果GCC没有进行优化,它将无法发出任何代码.

想想另一种方式:输入语言GCC是相当丰富的(即使是纯C,在那里你有while,for,...),但中间GIMPLE语言是更差(特别是GIMPLE/SSA),所以你需要到应用一些转换从源AST到Gimple.这些转换优化过程,几乎可以肯定.

另请参阅该答案中的图片和答案(SVG图像)并阅读此处提到的参考资料.

您应该理解-O0为禁用生成某些可执行文件所不需要的任何其他优化(例如,由-O1... 提供).


abl*_*igh 8

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
Run Code Online (Sandbox Code Playgroud)

将关闭所有选项(哎呀).

更严重的是,如果你是涵盖了所有优化状态,使优化参数(你需要做反正)的列表,并明确打开或关闭每一个与-fmyflag-fno-myflag.这实质上回答了你的第二个问题.

但是,您可能会认为在关闭所有-O级别的优化时不值得.

至于为什么会这样,那就是"太宽泛"(即你不得不问问谁写的)和'因为那是什么https://github.com/gcc-mirror/gcc/blob/master/gcc/ toplev.c做'.

请注意,文档没有说-O0禁用优化.它说(来自手册页):

-O0减少编译时间并使调试产生预期的结果.这是默认值.

通过暗示可能存在优化,不增加编译时间并且不影响调试,并且这些将保持开启.


sta*_*icx 5

为了回答我的问题,我做了一些结论和假设:

所以我要说的是,使用 O0 编译并不意味着不会应用任何优化。正如 @abligh 上面所说,将打开减少编译时间并更好地进行调试的选项。

也就是说,O0是在编译层面进行优化。为了简化调试过程,生成的二进制文件未进行优化。

我举个例子:这个选项在O0级别启用

-faggressive-loop-优化

在海湾合作委员会文档中:

此选项告诉循环优化器使用语言约束来导出循环迭代次数的界限。这假设循环代码不会通过例如导致有符号整数溢出或越界数组访问来调用未定义的行为。循环迭代次数的界限用于指导循环展开和剥离以及循环退出测试优化。默认情况下启用此选项。

因此对于 GCC 4.8.x,默认打开了近 50 个选项。