17

在编译一些代码时,我注意到在 -O0 和 -O1 之间创建的汇编程序存在很大差异。我想通过启用/禁用优化,直到我发现是什么导致了汇编程序的某些变化。

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

除了 '-f...' 和 '-m...' 还有什么可以改变的吗?

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


抱歉,这与使用 GCC + ARM 在递归期间减少堆栈使用有关,但提及它使问题有点难以理解。

4

3 回答 3

9

如果您只想查看在 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 在 O1 执行了哪些不受标志控制的额外魔法传递。

编辑:

一个不那么混乱的方法可能是比较 -fdump-passes 的输出,它将列出哪些 pass 是 ON 或 OFF 到 stderr。

所以像:

gcc -O0 test.c -fdump-passes |& grep ON > O0
gcc -O1 test.c -fdump-passes |& grep ON > O1
diff O0 O1
于 2012-11-01T09:56:16.673 回答
4

-O1除了为您对无法关闭的魔法的怀疑提供一些证据之外,这并不是说这有帮助:

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

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

  • 来自 Hagen 的“GCC 权威指南,第二版”:

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

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

于 2012-10-31T17:34:55.700 回答
2

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

--param max-crossjump-edges=1

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

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

  return perform_tree_ssa_dce (/*aggressive=*/optimize >= 2);
于 2019-09-08T14:00:08.460 回答