GCC中-O0和-O1之间的差异

GCC中-O0和-O1之间的差异,c,gcc,embedded,arm,C,Gcc,Embedded,Arm,在编译一些代码时,我注意到-O0和-O1之间创建的汇编程序有很大的不同。我想运行启用/禁用优化,直到我发现是什么导致了汇编程序中的某些更改 如果我使用-fverbose asm来找出与O0相比O1启用了哪些标志,然后手动禁用它们,那么为什么生成的汇编程序仍然如此不同?即使我使用O0运行gcc并手动添加fverbose asm所说的所有使用O1启用的标志,我也不会得到与使用O1相同的汇编程序 除了“-f..”和“-m..”之外,还有什么可以更改的吗 或者只是“O1”与“O0”相比有一些无法关闭的魔

在编译一些代码时,我注意到-O0和-O1之间创建的汇编程序有很大的不同。我想运行启用/禁用优化,直到我发现是什么导致了汇编程序中的某些更改

如果我使用-fverbose asm来找出与O0相比O1启用了哪些标志,然后手动禁用它们,那么为什么生成的汇编程序仍然如此不同?即使我使用O0运行gcc并手动添加fverbose asm所说的所有使用O1启用的标志,我也不会得到与使用O1相同的汇编程序

除了“-f..”和“-m..”之外,还有什么可以更改的吗

或者只是“O1”与“O0”相比有一些无法关闭的魔力



很抱歉,这个问题很神秘-这与提到它有关,但这让问题有点难以理解。

这并没有帮助,只是为你对
-O1
魔法的怀疑提供了一些无法关闭的证据:

  • 发件人:

    注意,-O1启用的所有优化都没有命令行切换标志来禁用它们

  • 摘自哈根的“GCC最终指南,第二版”:

    注意:并非所有的GCC优化都可以使用标志来控制。GCC自动执行一些优化,除了修改源代码之外,当您使用-O请求优化时,不能禁用这些优化


不幸的是,我还没有找到任何关于这些硬编码优化可能是什么的明确声明。希望了解GCC内部结构的人能够给出一个答案,并提供一些相关信息。

如果您只想知道哪些过程在O1启用,哪些过程在O0未启用,您可以运行以下操作:

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 -O0 test.c -fdump-passes |& grep ON > O0
gcc -O1 test.c -fdump-passes |& grep ON > O1
diff O0 O1
一个类似的过程,使用您发现的标志集,将让您看到GCC在O1执行哪些不受标志控制的额外魔法传递

编辑:

一种不那么麻烦的方法可能是比较-fdump过程的输出,它将列出哪些过程打开或关闭到stderr

比如:

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 -O0 test.c -fdump-passes |& grep ON > O0
gcc -O1 test.c -fdump-passes |& grep ON > O1
diff O0 O1

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

--param max-crossjump-edges=1
这会影响代码生成。检查源文件
params.def
中的所有可用参数

但是,在不修补源代码的情况下,无法通过添加选项从-O0切换到-O1,或从-O1切换到-O2,或从-Os或切换到-Os或其他。p.p.,因为有几个硬编码的位置在未咨询命令行选项的情况下检查级别,例如:

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

所以问题是,您不知道增加堆栈使用的“违规优化”的名称(或杀手组合),也不知道您需要的
-Os
优化的名称?其中“不知道名称”包括根本没有名称的可能性,它们是由
O1
Os
启用的杂项额外优化,无法单独控制。是的-基本上我知道GCC表示已启用的所有标志(通过-fverbose asm)。然而,手动禁用它们并不能解决问题,所以这一定是我无法控制的“魔力”。然而,我刚刚发现(见链接问题),O0的问题仍然存在,只是方式不同而已。不过,知道这个问题是否有答案还是很好的,因为无法控制优化是很可怕的。您是否尝试过使用GCC的
属性(())
或以其他方式重写函数(例如,使变量静态或手动分配其空间)?作为最后的解决方案,问题函数可以在汇编中重写。您确定这是一个优化吗?即使在-O0的情况下,您也查看了汇编程序的输出吗?我很确定gcc总是生成这样的代码,因为这是生成代码的最简单方法。我现在还没有一个arm gcc来验证,但这可能会在编译器的独立于机器的部分中处理。嗨,我刚刚更新了这个问题,试图让它更清楚(和其他问题不同),很抱歉混淆了。