C++ g++;O1不等于具有所有相关优化标志的O0

C++ g++;O1不等于具有所有相关优化标志的O0,c++,c++11,gcc,compiler-errors,g++,C++,C++11,Gcc,Compiler Errors,G++,我知道标题有点混乱。让我用一点背景来澄清我的问题: 在执行时间方面,当我使用-O1标志与-O0标志编译程序时,程序的行为异常。我知道-O1标志进行了许多优化,例如fauto inc dec-fbranch count reg-fcombine stack adjustments(根据手册页,超过40个)。为了弄清楚是哪些优化导致了这种行为,我计划一次删除一个标志,然后进行编译和测试,看看是否有什么变化 在做这个实验之前,我想确保用-O1编译的程序和用-O0编译的程序加上-O1启用的所有标志(让我

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

在执行时间方面,当我使用
-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
只有在打开优化器时,
-O1
应用的优化标志才会应用。您需要使用
n>0
指定
-On
,以便优化标志实际执行任何操作

换句话说,
-O0
不会打开优化器,因此优化标志不会做任何事情


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

-fcompare-elim 
标志由
-O1打开,您可以使用

-fno-compare-elim 


另一件需要注意的事情是,正如所指出的,因此没有任何方法可以关闭这些特定的优化。

奇怪地定义
,提供MCVE,解释如何对程序计时。并非所有由
-Ox
标志启用的优化都可以单独启用/禁用。并非所有由
-Ox
标志启用的优化都有文档记录。当一个程序根据优化标志的不同行为时,通常是因为它调用了未定义的行为(这是程序中的一个错误)。你应该发布一篇文章,这样我们可以(也许)帮助你找到你的bug。谢谢你的回复,那么,我如何启用/禁用各个优化标志呢?现在我有40多个标志,它们导致了我感兴趣的行为。这些标志的任何子集都可能是真正的原因。我怎样才能找到它们?另外。