我最近收到一个错误报告,指出一个程序无法使用-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挂起了编译器,所以我试图追查这个问题。首先,我试图找出-O3之间的-O2之间的差异。 Gcc的手册页指出-O3启用了-O2和以下的开关(让我们称之为x
):
-finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload
-ftree-vectorize -fipa-cp-clone
我通过比较调用时使用-Q -O2 --help=optimizers
和-Q -O3 --help=optimizers
的gcc输出来验证。然后,我计划有选择地删除开关,以便找到导致问题的开关。但是,编译与-O2和上面的附加开关一起工作正常,所以我总结
-O3 != -O2 x
现在我的问题:有人知道-O2和-O3之间是否存在进一步的区别(未记录?),有没有人遇到过类似的行为?这可能是编译器错误吗?
答案 0 :(得分:21)
手册页可能已过时,但您可以找到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(文件gcc/opts.c
和可能gcc/common.opt
)的来源,如gcc-4.6.0:
/* -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
)。
选项n
中-On
的唯一额外用途是将其值保存到宏__OPTIMIZE__
中。因此,对于此宏的值等于2或3,某些标头的行为可能会有所不同。
更新:There are questions about it in GCC WIKI:
没有。首先,单个优化选项(-f *)不启用优化,选项-Os或-Ox with x> 0是必需的。其次,-Ox标志启用许多不受任何单独的-f *选项控制的优化。 There are no plans to add individual options for controlling all these optimizations.
因平台和GCC版本而异。您可以通过这样做让GCC告诉您它启用了哪些标志:
touch empty.c
gcc -O1 -S -fverbose-asm empty.c
cat empty.s
答案 1 :(得分:3)
如果您的编译器挂起,那么是 - 我认为这是一个编译器错误。编译器也有bug。
(即使用于编译编译器的编译器存在错误,也可能在新编译器中引入了一个错误 - gcc采取了一些步骤来通过它的暂存引导来避免这种错误。)
也可能是其他事情,例如完成优化只需要花费更多,更多时间来执行,或者增加的优化级别会导致使用更多内存,并且您的系统开始无用。