【问题标题】:What's the difference between -O3 and (-O2 + flags that man gcc says -O3 adds to -O2)?-O3 和 (-O2 + man gcc 说 -O3 添加到 -O2 的标志) 之间有什么区别?
【发布时间】:2011-06-23 13:02:25
【问题描述】:

我最近收到了一个关于使用 -O3 开关编译失败的程序的错误报告(请参阅https://github.com/cschwan/sage-on-gentoo/issues/66)。特别是,问题是编译在某个点挂起。通过使用 -O2 编译解决了这个问题(我很清楚使用 -O3 编译的程序可能会被破坏,但我不知道 -O3 可能会挂起编译器)。如果你想重现问题运行

wget http://perso.ens-lyon.fr/xavier.pujol/fplll/libfplll-3.0.12.tar.gz
tar -xf libfplll-3.0.12.tar.gz
cd libfplll-3.0.12
./configure CXXFLAGS="-O3"
make

我想知道为什么 -O3 会挂起编译器,所以我试图找出问题所在。首先,我试图找出-O2和-O3之间的区别。 Gcc 的手册页指出 -O3 启用了 -O2 和以下的开关(我们称它们为x):

-finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload
-ftree-vectorize -fipa-cp-clone

我通过将调用时的 gcc 输出与-Q -O2 --help=optimizers-Q -O3 --help=optimizers 进行比较来验证这一点。然后我计划有选择地移除开关,以便找到导致问题的开关。但是,编译可以正常使用 -O2 和上面的附加开关,所以我得出结论

-O3 != -O2 x

现在我的问题:有人知道 -O2 和 -O3 之间是否有进一步的区别(未记录?),有没有人经历过类似的行为?这可能是编译器错误吗?

【问题讨论】:

  • 我认为,您应该添加到问题 -O3 运行此类选项“-ftree-dump-all-all -frtl-dump-all-all”并找到最后一个挂起的阶段它。此外,检查 gcc 的堆栈,在 gdb --args 下启动它并用 Ctrl-C 停止。
  • 对于没有 C++/make 经验的谷歌用户,他们试图像我一样制作 libfplll,但没有指定任何标志,它在 enum/libfplll_la-enumerate_base.lo 上“挂”了大约 30 分钟,然后继续。

标签: gcc


【解决方案1】:

手册页可能已经过时,但您可以找到 O2 和 O3 的实际列表。

要获取实际使用的-f 优化选项的完整列表(几乎,请检查“更新”),我建议您使用-fverbose-asm -save-temps(或-fverbose-asm -S) - 有一个完整的在 asm 文件 (*.s) 的顶部列出。

对于 gcc-4.6.0,我得到 x(O2 和 O3 之间的差异)为:

 -fgcse-after-reload
 -finline-functions
 -fipa-cp-clone
 -fpredictive-commoning
 -ftree-loop-distribute-patterns
 -ftree-vectorize
 -funswitch-loops

您问题的另一个信息来源是作为 gcc-4.6.0 的 GCC 的来源(文件 gcc/opts.c 和可能的 gcc/common.opt):

/* -O3 optimizations.  */
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fpredictive_commoning, NULL, 1 },
/* Inlining of functions reducing size is a good idea with -Os
   regardless of them being declared inline.  */
{ OPT_LEVELS_3_PLUS_AND_SIZE, OPT_finline_functions, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_funswitch_loops, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fgcse_after_reload, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_ftree_vectorize, NULL, 1 },
{ OPT_LEVELS_3_PLUS, OPT_fipa_cp_clone, NULL, 1 },

我也检查过,gcc 是否检查其他文件中的-On(cscope 符号搜索x_optimize)。

选项-Onn 的唯一额外用途是将其值保存到宏__OPTIMIZE__ 中。因此,对于这个宏的值等于 2 或 3,某些标头的行为可能会有所不同。

更新:There are questions about it in GCC WIKI

  • -O1(-O2、-O3 或 -Os)是否等同于单独的 -foptimization 选项?

没有。首先,单个优化选项 (-f*) 不启用优化,需要 x > 0 的选项 -Os 或 -Ox。其次,-Ox 标志启用了许多不受任何单个 -f* 选项控制的优化。 There are no plans to add individual options for controlling all these optimizations.

  • -O1(-O2、-O3 或 -Os)启用了哪些特定标志?

因平台和 GCC 版本而异。你可以让 GCC 告诉你它启用了哪些标志:

touch empty.c
gcc -O1 -S -fverbose-asm empty.c
cat empty.s

【讨论】:

  • 您的回答给了我正确的提示 - 在 gcc/opts.c 中,我发现了使用 -O3 设置的其他参数:max-aliased-vopsavg-aliased-vops。后者是我问题的根源。当设置为3(-O3 的默认值)时,编译器显示相同的行为。谢谢!
  • 为了完整起见:max-partial-antic-length 也受 -O3 影响。这也正确记录在 gcc 的手册页中,尽管在 -O3 的描述中没有提及。
  • cschwan,我很高兴听到你发现了问题,但我认为 vops 和 *antic 是在 gcc 或 smth 的 gentoo 版本中添加的,因为有“vanilla” gcc-4.6 中没有这样的选项
  • 不,这些选项存在于 vanilla gcc 4.4.6 中,请参阅 GCC 4.4.6 Optimization Options。在 4.5 中,max-aliased-vopsavg-alias-vops 显然已被删除(至少它们不再记录在 GCC 4.5.3 Optiomization Options 中),4.6 中删除了 max-partial-antic-length
【解决方案2】:

如果您的编译器挂起,那么是的 - 我认为这是一个编译器错误。编译器也有错误。

(即使用于编译您的编译器的编译器有错误,也可能会在新编译器中引入错误 - 不过 gcc 会采取一些措施来通过其分段引导来避免这种情况。)

也可以是其他东西,例如完成的优化只需要更多的时间来执行,或者提高的优化级别会导致使用更多的内存,并且您的系统开始报废。

【讨论】:

    猜你喜欢
    • 2015-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    • 1970-01-01
    • 2013-11-10
    • 2015-12-25
    • 1970-01-01
    相关资源
    最近更新 更多