海湾合作委员会的__builtin_expect集会转储似乎总是下降分支

时间:2016-11-02 22:02:25

标签: c++ c gcc assembly

好的,所以我一直在玩__builtin_expect,我刚刚创建了一个简单的测试程序,我通过godbolt.org获取程序集输出(https://godbolt.org/g/FZo5fP

int main(){
  volatile int num = 4;
  //if(num == 4){
  if(__builtin_expect(num,4)){
    return num*800;
  }else{
    return num*500;
  }
}

使用-O1或更高版本编译时产生:

main:
        mov     DWORD PTR [rsp-4], 4
        mov     eax, DWORD PTR [rsp-4]
        test    eax, eax
        mov     eax, DWORD PTR [rsp-4]
        je      .L2
        imul    eax, eax, 800
        ret
.L2:
        imul    eax, eax, 500
        ret

似乎test eax,eax的部分总是将零标志设置为0,除非num等于0.所以好像num未设置为0它总是乘以800而不是num=4。我对__builtin_expect的理解是,虽然它会优化以假设它将转到该分支,但仍应进行比较以确保它应该使用该分支。

如果我将__builtin_expect切换为只是==它会产生

main:
        mov     DWORD PTR [rsp-4], 2
        mov     eax, DWORD PTR [rsp-4]
        cmp     eax, 4
        mov     eax, DWORD PTR [rsp-4]
        je      .L5
        imul    eax, eax, 500
        ret
.L5:
        imul    eax, eax, 800
        ret

这对我来说更有意义,因为它实际上与4比较。我对__builtin_expect的理解是错误的吗? __builtin_expect实际上只能用0或1,即使它指定它需要很长时间吗?

1 个答案:

答案 0 :(得分:5)

来自the docs

  

返回值是 exp 的值,它应该是一个整数表达式。

所以逻辑语义为:

if(__builtin_expect(num,4)) { ... }

是:

if (num) { ... }

这与你想要的不同。如果你想写一个你期望num == 4非常可能的,你想要:

if (__builtin_expect(num == 4, 1)) { ... }

通常,您只需将它们包装在宏中:

#define likely(expr)   __builtin_expect((expr), 1)
#define unlikely(expr) __builtin_expect((expr), 0)

然后使用变得更自然:

if (likely(num == 4)) { ... }