循环条件下常数的评估

时间:2014-10-14 14:08:44

标签: c++ loops optimization as-if

for(int i = 0; i < my_function(MY_CONSTANT); ++i){
    //code using i
}

在这个例子中,每次迭代都会评估my_function(MY_CONSTANT),还是会自动存储?这取决于使用的优化标志吗?

4 个答案:

答案 0 :(得分:10)

每次调用函数就好像一样。

但是,如果编译器每次都能证明函数结果是相同的,那么它可以在“as”规则下进行优化。

E.g。这通常发生在调用.end()标准容器时。


一般建议:如果对是否微观优化一段代码存有疑问,

  1. 不要这样做。
  2. 如果您仍在考虑这样做,衡量
  3. 好吧还有第三点,但我忘记了,也许是的,还在等待。
  4. 换句话说,根据代码的清晰度决定是否使用变量,而不是基于想象的性能。

答案 1 :(得分:3)

每次迭代都会对其进行评估。您可以通过执行类似

的操作来节省额外的计算时间
const int stop = my_function(MY_CONSTANT);
for(int i = 0; i < stop; ++i){
    //code using i
}

答案 2 :(得分:2)

as-if rule下的现代优化编译器可能能够在您comment here中概述的情况下优化函数调用。 as-if rule表示符合标准的编译器只模拟可观察行为,我们可以通过转到草案C ++标准部分1.9 程序执行来看到这一点,其中说:

  

[...]相反,需要符合实现来模拟(仅)   抽象机器的可观察行为,如下所述.5

因此,如果您使用常量表达式并且my_function没有可观察到的副作用,则可以对其进行优化。我们可以组合一个简单的测试( see it live on godbolt ):

#include <stdio.h>

#define blah 10

int func( int x )
{
  return x + 20 ;
}

void withConstant( int y )
{
  for(int i = 0; i < func(blah); i++)
  {
    printf("%d ", i ) ;
  }
}

void withoutConstant(int y)
{
  for(int i = 0; i < func(i+y); i++)
  {
    printf("%d ", i ) ;
  }
}

withConstant的情况下,我们可以看到它优化了计算:

cmpl    $30, %ebx   #, i

甚至在withoutConstant的情况下,它会内联计算而不是执行函数调用:

leal    0(%rbp,%rbx), %eax  #, D.2605

答案 3 :(得分:1)

如果my_function被声明为constexpr且参数实际上是常量,则在编译时计算该值,从而实现&#34; as-if&#34;和#34;顺序一致,没有数据竞争&#34;规则。

constexpr my_function(const int c);

如果你的函数有副作用,它会阻止编译器将其移出for-loop,因为它不能满足&#34; as-if&#34;规则,除非编译器可以推断它的出路。

编译器可能内联my_function,减少它就像它是循环的一部分一样,并且通过常量减少发现它实际上只是一个常量,事实上删除了调用并用常量替换它。

int my_function(const int c) {
    return 17+c; // inline and constant reduced to the value.
}

所以你的问题的答案是......也许!