为了账号安全,请及时绑定邮箱和手机立即绑定

停用GCC中的所有优化选项

/ 猿问

停用GCC中的所有优化选项

侃侃无极 2019-10-21 15:43:50

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


    gcc -O0 test.c 

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


    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)进行比较


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


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



查看完整描述

3 回答

?
慕斯卡3215842


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级别的优化都不值得。


至于为什么会这样,介于“太宽泛”(即您必须问写它的人)和“因为那就是https://github.com/gcc-mirror/gcc/blob/master/gcc/ toplev.c确实如此。


请注意,文档中并未说明-O0禁用优化。它说(从手册页):


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


暗示可能存在一些优化,它们不会增加编译时间,也不会影响调试,这些将保留下来。


查看完整回答
反对 回复 2019-10-21
?
海绵宝宝撒

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


因此,我想说用O0进行编译并不意味着不会应用任何优化。如上面@abligh所述,可以减少编译时间并改善调试效果的选项将打开。


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


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


渐进式循环优化


在GCC文档中:


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


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


查看完整回答
反对 回复 2019-10-21
?
精慕HU

Stricto sensu,GCC编译器的中端由优化遍历的序列(实际上是嵌套树,在编译过程中会动态更改)组成,因此,如果GCC没有进行优化,则将无法发出任何代码。


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


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


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


查看完整回答
反对 回复 2019-10-21

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信