【问题标题】:g++ O1 is not equal to O0 with all related optimization flagsg++ O1 不等于 O0 与所有相关的优化标志
【发布时间】:2019-04-10 01:59:39
【问题描述】:

我知道标题有点混乱。让我用一点背景来澄清我的问题:

就执行时间而言,当我使用-O1 标志与-O0 标志编译它时,我的程序的行为很奇怪。我知道-O1 标志做了很多优化,例如fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments(根据手册页超过40)。为了弄清楚是哪些优化导致了这种行为,我计划一次删除一个标志,然后编译和测试看看是否有变化。

在做这个实验之前,我想确保用-O1 编译的程序和用-O0 编译的程序加上-O1 启用的所有标志(让我们调用-O0+)表现相似。实际上,我希望这两种方法都应该生成相同的二进制文件,因为启用了相同的优化标志。

O1编译

CC = g++

CFLAGS = -std=c++11 -Wall -fopenmp
SOURCE = a_count_f.cpp
EXEC = run
INC = inc

all: $(EXEC)
.PHONY: all

$(EXEC): $(SOURCE)
    $(CC) $(CFLAGS) -O1 -o $(EXEC) -I$(INC) $^

O0+编译

CC = g++

CFLAGS = -std=c++11 -Wall -fopenmp
SOURCE = a_count_f.cpp
EXEC = run
INC = inc

OPT_FLAGS = -fauto-inc-dec -fbranch-count-reg -fcombine-stack-adjustments -fcompare-elim -fcprop-registers -fdce -fdefer-pop -ftree-builtin-call-dce -fdse -fforward-propagate -fguess-branch-probability -fif-conversion2 -fif-conversion -finline-functions-called-once -fipa-pure-const -fipa-profile -fipa-reference -fmerge-constants -fmove-loop-invariants -fomit-frame-pointer -freorder-blocks -fshrink-wrap -fshrink-wrap-separate -fsplit-wide-types -fssa-backprop -fssa-phiopt -ftree-bit-ccp -ftree-ccp -ftree-ch -ftree-coalesce-vars -ftree-copy-prop -ftree-dce -ftree-dominator-opts -ftree-dse -ftree-forwprop -ftree-fre -ftree-phiprop -ftree-scev-cprop -ftree-sink -ftree-slsr -ftree-sra -ftree-pta -ftree-ter -funit-at-a-time

all: $(EXEC)
.PHONY: all

$(EXEC): $(SOURCE)
    $(CC) $(CFLAGS) -O0 $(OPT_FLAGS) -o $(EXEC) -I$(INC) $^

然而,事实证明-O1-O0+ 给出了完全不同的结果。尽管存在所有优化差异,-O0-O0+ 给出了非常相似的结果。 (通过结果,我的意思是执行时间)

我已经用-Q --help=optimizers 检查了这两个编译,并且输出确认两者都启用了相同的标志。

接下来对我来说是比较汇编代码。在此之前,我想在这里问一下是否有人知道为什么会发生这种情况。我没有包含源代码,因为似乎问题与源代码无关。但是,如果需要,我可以附上它。

g++ 版本:g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0

【问题讨论】:

  • 定义strangely,提供MCVE,解释你是如何为你的程序计时的。
  • 并非所有由-Ox 标志启用的优化都可以单独启用/禁用。并非所有由-Ox 标志启用的优化都记录在案。
  • 当一个程序根据优化标志表现出不同的行为时,通常是因为它调用了未定义的行为(这是程序中的一个错误)。您应该发布minimal reproducible example,以便我们(也许)可以帮助您找到您的错误。

标签: c++ c++11 gcc compiler-errors g++


【解决方案1】:

-O1 应用的优化标志仅在优化器打开时应用。您需要指定 -Onn > 0 以便优化标志实际执行任何操作。

换句话说,-O0 没有打开优化器,所以优化标志没有做任何事情。


您可以使用标志的-fno 形式关闭优化标志。比如

-fcompare-elim 

标志由-O1 开启,您可以使用

将其关闭
-fno-compare-elim 

另一件需要注意的事情,正如 T.C. 所指出的那样,是 not all optimizations have a flag,因此没有任何方法可以关闭这些特定优化。

【讨论】:

猜你喜欢
  • 2015-01-15
  • 1970-01-01
  • 2012-10-20
  • 1970-01-01
  • 2019-11-29
  • 2013-11-07
  • 2011-09-15
  • 2013-03-14
  • 1970-01-01
相关资源
最近更新 更多