关于C#:GCC中-O0和-O1之间的差异

Differences between -O0 and -O1 in GCC

在编译一些代码时,我注意到-O0和-O1之间创建的汇编程序存在很大差异。我想遍历启用/禁用优化,直到找出导致汇编程序发生某些更改的原因。

如果我使用-fverbose-asm来准确找出O1与O0相比启用了哪些标志,然后手动将其禁用,那么为什么生成的汇编器仍然如此巨大?即使我用O0运行gcc并手动添加fverbose-asm所说的所有已被O1启用的标志,我也不会得到仅使用O1就能得到的同一汇编器。

除了\\'-f ... \\'和\\'-m ... \\'之外,是否还有其他可以更改的内容?

或者仅仅是\\'O1 \\'与无法关闭的''O0 \\'相比具有一些魔力。

很抱歉,这与在使用GCC ARM进行递归过程中减少堆栈使用量有关,但是提及它使这个问题有点难以理解。


如果您只想查看O1启用了哪些通行证,而O0则未启用通行证,则可以运行以下命令:

1
2
3
4
5
6
gcc -O0 test.c -fdump-tree-all -da
ls > O0
rm -f test.c.*
gcc -O1 test.c -fdump-tree-all -da
ls > O1
diff O0 O1

使用您发现的一组标志的类似过程,将使您看到GCC在O1进行哪些不受标志控制的额外魔术传递。

编辑:

一种比较简单的方法可能是比较-fdump-passs的输出,该输出将列出与stderr对应的ON或OFF的通行证。

类似这样:

1
2
3
gcc -O0 test.c -fdump-passes |& grep ON > O0
gcc -O1 test.c -fdump-passes |& grep ON > O1
diff O0 O1

除了为您怀疑无法关闭的-O1魔术提供一些证据外,这无济于事:

  • 来自http://gcc.gnu.org/ml/gcc-help/2007-11/msg00214.html:

    CAVEAT, not all optimizations enabled by -O1 have a command-line toggle flag to disable them.

  • 摘自Hagen的" GCC权威指南,第二版":

    Note: Not all of GCCa€?s optimizations can be controlled using a flag. GCC performs some optimizations automatically and, short of modifying the source code, you cannot disable these optimizations when you request optimization using -O

不幸的是,我没有找到关于这些硬编码优化可能是什么的明确声明。希望对GCC的内部知识了解的人可以发布答案,并提供一些有关此信息。


除了许多选项外,您还可以更改参数,例如

1
--param max-crossjump-edges=1

这会影响代码生成。检查源文件params.def中所有可用的参数。

但是无法从-O0切换到-O1,或者从-O1切换到-O2,或者从-Os切换到-Os等等。 ,通过添加选项而不修补源代码,因为在不参考命令行选项的情况下检查级别的硬编码位置有多个,例如:

1
  return perform_tree_ssa_dce (/*aggressive=*/optimize >= 2);