我遇到了GCC 4.6.3的问题,我找不到任何逻辑解决scheme/解释。 我正在开发一个将带有操作系统的embedded式固件应用程序移植到基于Linux的应用程序的项目。 该应用程序有一大堆unit testing,可以通过参数激活,以检查代码/function的完整性。
当我在debugging编译时,一切正常工作,所有的unit testing通过。 不过,我有发布版本(使用-O3优化)的问题。 我设法隔离有问题的文件。 这个文件来自一个不由我们编码的外部软件包,我们根本不想改变它。
我使用GCC的文档来获得-O3中包含的所有优化。 这是我得到的:
-fauto-inc-dec -fcprop-registers -fdce -fdefer-pop -fdse -fguess-branch-probability -fif-conversion2 -fif-conversion -finline-small-functions -fipa-pure-const -fipa-reference -fmerge-constants -fsplit-wide-types -ftree-builtin-call-dce -ftree-ccp -ftree-ch -ftree-copyrename -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-fre -ftree-sra -ftree-ter -funit-at-a-time -fomit-frame-pointer -fthread-jumps -falign-functions -falign-jumps -falign-loops -falign-labels -fcaller-saves -fcrossjumping -fcse-follow-jumps -fcse-skip-blocks -fdelete-null-pointer-checks -fexpensive-optimizations -fgcse -fgcse-lm -findirect-inlining -foptimize-sibling-calls -fpeephole2 -fregmove -freorder-blocks -freorder-functions -frerun-cse-after-loop -fsched-interblock -fsched-spec -fschedule-insns -fschedule-insns2 -fstrict-aliasing -fstrict-overflow -ftree-switch-conversion -ftree-pre -ftree-vrp -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -ftree-vectorize -fipa-cp-clone
我发现这是-fschedule-insns
导致了这个问题。 删除这个优化得到的代码再次正常工作。
这里是我无法解释的,GCC的文档说,如果你想知道GCC应用到底是什么,你可以在控制台gcc -Q -O3 --help=optimizers | grep "enabled"
gcc -Q -O3 --help=optimizers | grep "enabled"
。 我做了,这里是输出:
-falign-functions [enabled] -falign-jumps [enabled] -falign-labels [enabled] -falign-loops [enabled] -fasynchronous-unwind-tables [enabled] -fbranch-count-reg [enabled] -fcaller-saves [enabled] -fcombine-stack-adjustments [enabled] -fcommon [enabled] -fcompare-elim [enabled] -fcprop-registers [enabled] -fcrossjumping [enabled] -fcse-follow-jumps [enabled] -fdce [enabled] -fdefer-pop [enabled] -fdelete-null-pointer-checks [enabled] -fdevirtualize [enabled] -fdse [enabled] -fearly-inlining [enabled] -fexpensive-optimizations [enabled] -fforward-propagate [enabled] -fgcse [enabled] -fgcse-after-reload [enabled] -fgcse-lm [enabled] -fguess-branch-probability [enabled] -fif-conversion [enabled] -fif-conversion2 [enabled] -finline-functions [enabled] -finline-functions-called-once [enabled] -finline-small-functions [enabled] -fipa-cp [enabled] -fipa-cp-clone [enabled] -fipa-profile [enabled] -fipa-pure-const [enabled] -fipa-reference [enabled] -fipa-sra [enabled] -fivopts [enabled] -fjump-tables [enabled] -fmath-errno [enabled] -fmerge-constants [enabled] -fmove-loop-invariants [enabled] -foptimize-register-move [enabled] -foptimize-sibling-calls [enabled] -fpeephole [enabled] -fpeephole2 [enabled] -fpredictive-commoning [enabled] -fprefetch-loop-arrays [enabled] -fregmove [enabled] -frename-registers [enabled] -freorder-blocks [enabled] -freorder-functions [enabled] -frerun-cse-after-loop [enabled] -frtti [enabled] -fsched-critical-path-heuristic [enabled] -fsched-dep-count-heuristic [enabled] -fsched-group-heuristic [enabled] -fsched-interblock [enabled] -fsched-last-insn-heuristic [enabled] -fsched-rank-heuristic [enabled] -fsched-spec [enabled] -fsched-spec-insn-heuristic [enabled] -fsched-stalled-insns-dep [enabled] -fschedule-insns2 [enabled] -fshort-enums [enabled] -fsigned-zeros [enabled] -fsplit-ivs-in-unroller [enabled] -fsplit-wide-types [enabled] -fstrict-aliasing [enabled] -fthread-jumps [enabled] -fno-threadsafe-statics [enabled] -ftoplevel-reorder [enabled] -ftrapping-math [enabled] -ftree-bit-ccp [enabled] -ftree-builtin-call-dce [enabled] -ftree-ccp [enabled] -ftree-ch [enabled] -ftree-copy-prop [enabled] -ftree-copyrename [enabled] -ftree-cselim [enabled] -ftree-dce [enabled] -ftree-dominator-opts [enabled] -ftree-dse [enabled] -ftree-forwprop [enabled] -ftree-fre [enabled] -ftree-loop-distribute-patterns [enabled] -ftree-loop-if-convert [enabled] -ftree-loop-im [enabled] -ftree-loop-ivcanon [enabled] -ftree-loop-optimize [enabled] -ftree-phiprop [enabled] -ftree-pre [enabled] -ftree-pta [enabled] -ftree-reassoc [enabled] -ftree-scev-cprop [enabled] -ftree-sink [enabled] -ftree-slp-vectorize [enabled] -ftree-sra [enabled] -ftree-switch-conversion [enabled] -ftree-ter [enabled] -ftree-vect-loop-version [enabled] -ftree-vectorize [enabled] -ftree-vrp [enabled] -funit-at-a-time [enabled] -funswitch-loops [enabled] -fvar-tracking [enabled] -fvar-tracking-assignments [enabled] -fvect-cost-model [enabled] -fweb [enabled]
-fschedule-insns
不在列表中,如果我删除了grep
,它将被标记为禁用。 如果我把GCC的命令输出中列出的所有优化都用所提供的列表编译成问题文件,代码仍然通过。 这里有什么问题?
这是一个总结。 如果我直接使用-O3,它会失败。 如果我使用GCC文档中列出的-O3的所有优化,则失败。 如果我使用GCC从命令行提供的-O3的所有优化,它会通过。 最后,如果我使用GCC文档中列出的-O3的所有优化(不包括-fschedule-insns
,它将通过。
什么是真正的优化列表-O3!?! 海湾合作委员会的文件或海湾合作委员会通过命令行告诉什么? 我很困惑,也不知道如何才能对此做出正面/合理的解释。
有人遇到这种问题与海湾合作委员会?
很好的问题。 你刚刚发现,一如既往, 源头是唯一的事实 。 GCC的Bugzilla甚至有这个bug 。
我将把你的注意力引向GCC源代码中的两个地方。
在gcc-4.6.3/gcc/opts.c
第474行中,我们在默认选项的表格中看到以下内容:
{ OPT_LEVELS_2_PLUS, OPT_frerun_cse_after_loop, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fcaller_saves, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fpeephole2, NULL, 1 }, #ifdef INSN_SCHEDULING /* Only run the pre-regalloc scheduling pass if optimizing for speed. */ { OPT_LEVELS_2_PLUS_SPEED_ONLY, OPT_fschedule_insns, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fschedule_insns2, NULL, 1 }, #endif { OPT_LEVELS_2_PLUS, OPT_fregmove, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fstrict_aliasing, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fstrict_overflow, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_freorder_blocks, NULL, 1 },
在gcc-4.6.3/gcc/config/i386/i386.c
,5166行,我们看到
static const struct default_options ix86_option_optimization_table[] = { /* Turn off -fschedule-insns by default. It tends to make the problem with not enough registers even worse. */ #ifdef INSN_SCHEDULING { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 }, #endif #ifdef SUBTARGET_OPTIMIZATION_OPTIONS SUBTARGET_OPTIMIZATION_OPTIONS, #endif { OPT_LEVELS_NONE, 0, NULL, 0 } };
我们可以得出文件只是部分正确的结论; 一些通行证实际上在某些目标上被禁用,即使在他们通常被启用的O
级别上。 特别是,默认情况下,x86,mep和mcore派生的目标会禁用所有优化级别的schedule-insns
,尽管它应该在-O2
以上启用。 您仍然可以手动强制启用它,但是您首先要运行被禁用的风险。
另外,如果编译器是使用INSN_SCHEDULING
禁用构建的,则可以在所有级别上默认禁用-fschedule_insns
。