为什么要用-O2而不是-O3编译

时间:2011-04-12 15:35:19

标签: optimization g++

我们通常使用-O2进行编译,因为-O3会“触发微妙的错误”。

对于我们的GCC版本-O3,可以实现更积极的内联,这实际上可以揭示其他未被注意的错误(例如,使用来自将其作为引用参数或对数组进行越界访问的函数的未初始化值)。在我看来,这种积极的内联还允许使用更小的函数进行更具表现力的编码方式,-funswitch-loops有助于在循环中保持变量定义更加局部化。

鉴于我们的代码中的错误比编译器错误更有可能,并且我们使用-Wall -Wextra而没有任何问题我们应该寻找什么样的错误?

如果重要,我们使用gcc-4.3.2。编译时间对我们来说不是一个主要问题。

3 个答案:

答案 0 :(得分:10)

尺寸。当然,如果大小确实很重要(有时会像嵌入式一样),那么就会使用-Os。但O3的主要区别在于(从你已经提到的)内联。这可以增加生成的代码大小(但速度更快)。也许你想要速度,但不是所有(空间)成本?否则我会发现没有理由不使用O3(除了你知道只在你的O3代码中出现的gcc编译器错误,但只要你没有错误,你就不能在O2重现,我不在乎)

答案 1 :(得分:3)

有时,积极优化可能会像您提到的那样破坏代码。如果这是您正在进行的项目,那么这可能不是问题。但是,如果有问题的代码是遗留代码,这些代码很脆弱,编写得很糟糕,而且不太了解,那么您希望尽可能少地利用这些代码。

此外,并非所有优化都得到了正式证实。这意味着他们可能以不合需要的方式改变节目的行为。

我能想到的最好的例子是Java,但它应该说明我对优化的一般看法。

通常有这样的代码

 while( keepGoing ){
      doStuff();
 }

然后keepGoing的值被另一个线程修改。 JVM将做的一个优化是,keepGoing未在循环体内修改,因此它“提升”它并在循环之前检查,实质上转换代码成:

 if( keepGoing ){
      while( true ){
           doStuff();
      }
 }

在多线程环境中哪个不一样,但在单线程中它是。这些是可以打破优化的事物。这是“source”的常见Heisenbugs

PS-在Java中,正确的答案是make keepGoingvolatile”因此它不能设定缓存的值并且会按照您的意图执行。

答案 2 :(得分:2)

不要自欺欺人地编译器错误并没有潜伏在那里让你的生活变得地狱。这是去年在Debian中出现的一个nasty one,并且该修复将重新回到-O2。