这两个都是宏,展开形式如下:
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
(现在的源代码中可能还加入了ftrace的功能,用于统计预测成功率,改善程序性能,参见ftrace简介)
__builtin_expect(!!(x), 1)用来表示程序员预测x值为1的可能性比较大,这可以帮助编译器来优化汇编代码。
比如,下面的代码:
int main(int argc, char *argv[])
{
//如果使用编译时常量,经过优化后,if语句可能就不会翻译了,直接翻译正确的执行路径
int a = atoi(argv[1]);
if (__builtin_expect(!!(a == 1), 1))
{
a++;
}
else
{
a--;
}
int b = atoi(argv[2]);
if (__builtin_expect(!!(b == 1), 0))
{
b++;
}
else
{
b--;
}
printf("%d\n", a + b);
return 0;
}
使用gcc -S -O2 进行汇编,得到关键部分代码如下:
//得到a
movq 8(%rsi), %rdi
call atoi
//我们预测a == 1,如果a != 1,发生跳转
cmpl $1, %eax
jne .L8
movl $2, %ebp
.L2:
//得到b
movq 16(%rbx), %rdi
xorl %eax, %eax
call atoi
//我们预测b != 1,如果b == 1,发生跳转
cmpl $1, %eax
je .L5
subl $1, %eax
可见,对if语句翻译成汇编代码后的跳转策略发生了变化,如果实际结果与预期相同,则不发生跳转,否则发生跳转。发生跳转会带来什么问题呢?会清空处理器流水线,可能带来一些性能上的损失。

本文介绍了GCC编译器中的__builtin_expect宏如何帮助优化代码性能。通过预测条件语句的结果,编译器可以生成更高效的汇编代码,减少不必要的处理器流水线清空,从而提升程序运行效率。

被折叠的 条评论
为什么被折叠?



