C程序与优化相关的条件语句

时间:2016-02-18 11:27:14

标签: c optimization

即使条件语句块中没有有效语句,是否会对条件语句进行求值?如果是,如何优化代码以便在这种情况下不评估条件语句? 例如:

if( get_value() !=NULL)
{
}

if( get_value() != NULL)
{
 do{}while(0);
}

在多个地方,在现有项目中,只是为了获得调试打印,有这样的检查。使用宏函数可以使打印无效,但如何优化条件语句?手动删除这些比较非常困难

1 个答案:

答案 0 :(得分:1)

C和C ++标准要求编译器确保get_value()被评估(或者至少表现为 as as if 它被评估)。

因此,在一般情况下,将评估get_value。您可以轻松查看with godbolt

extern int* get_value();

int func() {
  if( get_value() !=NULL)
  {
  }
}

在gcc 4.4.7上生成x86程序集,如下所示:

    sub     rsp, 8
    call    get_value()
    add     rsp, 8
    ret

请注意,get_value()被调用,但是!= NULL检查没有发生,因为该比较是不可观察的。所以对于这个编译器,你可以说严格意义上没有评估完整的比较,但是由于get_value仍然必须被调用(这可能是昂贵的部分),因此没有完全消除比较。

编译器被迫采用这条路径,因为它不知道get_value可能有什么副作用,所以它必须调用它。可以忽略返回值,因为它知道比较和空if语句体没有效果。

然而,在一个特殊情况下,编译器可以消除整个语句 - 如果它可以在编译时证明get_value方法没有副作用。如果在同一个编译单元中声明了get_value方法(也许还有一些奇特的链接时优化),那么这是可能的。

我们更新示例以将get_value的实现放在编译单元中,并确保它没有副作用:

int* get_value() {
  return 0;
}

int func() {
  if( get_value() !=NULL)
  {
  }
}

现在,该方法为compiled into a no-op

func():
        rep
        ret

(对于那个显然无用的rep前缀的功能,see here ...)

所以这一切都取决于get_value的细节,以及编译器在编译空if语句时可以知道多少。