首页 文章

禁用GCC中的所有优化选项

提问于
浏览
14

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

gcc -O0 test.c

但是,检查-O0是否真的是 turning off all optimizations . 我执行了这个命令:

gcc -Q -O0 --help=optimizers

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

gcc -v

我懂了:

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)

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

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

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

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

3 回答

  • 7

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

    想想另一种方式:GCC的输入语言非常丰富(即使对于普通的C,你有 whilefor ,....)但是中间的Gimple语言要差得多(特别是Gimple / SSA),所以你需要应用一些转换从源AST到Gimple . 这些转换几乎是定义的优化过程 .

    另请参阅answerthis中的图片(SVG图像)并阅读提及的参考文献here .

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

  • 3

    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
    

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

    更严重的是,如果要覆盖所有优化状态,请列出优化标记(无论如何需要执行),并使用 -fmyflag-fno-myflag 明确打开或关闭每个优化标志 . 这实质上回答了你的第二个问题 .

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

    至于为什么它's like that, that'介于'too broad'之间(即你不得不问谁写了它)和'because that'是什么https://github.com/gcc-mirror/gcc/blob/master/gcc/toplev.c' .

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

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

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

  • 14

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

    所以我要说用O0编译并不意味着不会应用优化 . 减少编译时间并使调试更好的选项将打开,如@abligh所述 .

    换句话说,O0在编译级别上进行了优化 . 生成的二进制文件未经过优化,以简化调试过程 .

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

    -faggressive-loop-optimizations

    在GCC文档中:

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

    因此对于GCC 4.8.x,默认情况下启用了近50个选项 .

相关问题