我最近收到一个关于程序无法使用-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
Run Code Online (Sandbox Code Playgroud)
我想知道为什么-O3挂起编译器,所以我试图追查这个问题.首先,我试图找出-O3之间的-O2之间的差异.Gcc的手册页指出-O3启用-O2和以下的开关(让我们调用它们x):
-finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload
-ftree-vectorize -fipa-cp-clone
Run Code Online (Sandbox Code Playgroud)
我验证通过时调用gcc的比较器的输出-Q -O2 --help=optimizers和-Q -O3 --help=optimizers.然后,我计划有选择地删除开关,以便找到导致问题的开关.但是,编译与-O2以及上面的附加开关一起工作正常,所以我总结道
-O3 != -O2 x
Run Code Online (Sandbox Code Playgroud)
现在我的问题是:有人知道-O2和-O3之间是否存在进一步的区别(未记录?),有没有人经历过类似的行为?这可能是编译器错误吗?
osg*_*sgx 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
Run Code Online (Sandbox Code Playgroud)
您的问题的另一个信息来源是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 },
Run Code Online (Sandbox Code Playgroud)
我也检查过,gcc检查-On其他文件(cscope符号搜索x_optimize).
nfrom选项的唯一额外用法-On是将其值保存到宏中__OPTIMIZE__.因此,对于此宏的值等于2或3,某些标头的行为可能不同.
首先,单个优化选项(-f*)不启用优化,需要选项-Os或-Ox,其中x> 0.其次,-Ox标志启用许多不受任何单独的-f*选项控制的优化.没有计划添加用于控制所有这些优化的单个选项.
因平台和GCC版本而异.您可以通过执行以下操作让GCC告诉您它启用了哪些标志:
touch empty.c
gcc -O1 -S -fverbose-asm empty.c
cat empty.s
Run Code Online (Sandbox Code Playgroud)