条件vs运算符?

时间:2013-12-23 11:57:00

标签: c++ c gcc if-statement conditional-operator

在GCC(版本4.8.2)手册中,陈述如下:

  

-ftree-loop-if-convert-stores
         尝试if-convert包含内存的条件跳转          写道。对于多线程,此转换可能不安全          程序,因为它将条件存储器写入转换为          无条件记忆写入。例如,

   for (i = 0; i < N; i++)
      if (cond)
        A[i] = expr;
     

转换为

   for (i = 0; i < N; i++)
       A[i] = cond ? expr : A[i];
     

可能产生数据竞赛。

但是,我想知道使用operator?if语句是否有性能提升。

  • 在第一段代码中,如果符合条件,则A[i]仅设置为expr 。如果不满足,则跳过语句中的代码。
  • 在第二个中,无论条件如何,A[i]似乎都被写入;条件只影响它设置的值。

使用operator?,我们也在检查;但是,在不满足条件的情况下,我们会增加一些开销。我错过了什么吗?

1 个答案:

答案 0 :(得分:6)

所说的是条件跳转转换为条件移动指令,即cmove指令族。它们可以提高速度,因为它们不会像跳转一样停止处理器管道。

使用跳转指令,您不知道要加载哪些指令,因此使用预测并在管道中加载分支。如果预测是正确的,一切都很好,下一条指令已经在管道上执行。但是,在评估跳转之后,如果预测错误,则管道中已有的所有以下指令都是无用的,因此必须释放管道,并加载正确的指令。现代处理器包含16-30级管道,分支误预测会严重降低性能。条件移动绕过了它,因为它们不在程序流中插入分支。

  

但cmove总是会写吗?

来自Intel x86指令集参考:

  

CMOVcc指令检查EFLAGS寄存器[..]中的一个或多个状态标志的状态,并在标志处于指定状态(或条件)时执行移动操作。 [..]如果条件不满意,一招   未执行,并继续执行CMOVcc指令后的指令。

修改

在进一步调查gcc手册后,我感到困惑,因为据我所知,编译器没有优化将C代码转换为另一个C代码,但使用内部数据结构如控制流图,所以我真的不知道是什么他们的意思是他们的榜样。我认为它们意味着产生的新流量的C等价物。我不确定此优化是否与生成cmoves相关。

修改2

由于cmove使用寄存器而不是内存,因此

if (cond)
  A[i] = expr

无法生成cmove

但是这个

 A[i] = cond ? expr : A[i];

即可。

假设我们有bx expr值。

load A[i] into ax
cmp // cond
cmove ax, bx
store ax into &A[i]

因此,为了使用cmove,你必须读取A [i]值并将其写回如果cond为false,这与if语句不同,但与三元运算符相同。