内核中likely(x)和unlikely(x)宏:
知道__builtin_expect()函数的作用之后,我们就知道内核中likely(x)和unlikely(x)宏的作用了,通过likely(x)和unlikely(x)宏定义,我们可以得出他们的作用:int testfunc(int x)
{
if (__builtin_expect(!!(x), 1)) ///
{
x = 123;
}
else
{
x = 456;
}
return x;
}
这个函数中指明了
if条件成立的可能性比较大,gcc可以据此优化程序指令序列。
00400780 :
400780: 10800003 beqz a0,400790
400784: 2402007b li v0,123
400788: 03e00008 jr ra
40078c: 00000000 nop
400790: 03e00008 jr ra
400794: 240201c8 li v0,456
从汇编代码中可以看出,如果if成立,即x==1,则第一条跳转指令不成功,指令得以顺序执行。而如果else成立,则需要多执行一次跳转。
如果testfunc()如下实现:int testfunc(int x)
{
if (__builtin_expect(!!(x), 0)) ///
{
x = 123;
}
else
{
x = 456;
}
return x;
}
这个函数中指明了
else条件成立的可能性比较大,gcc可以据此优化程序指令序列。
00400780 :
400780: 14800002 bnez a0,40078c
400784: 2402007b li v0,123
400788: 240201c8 li v0,456
40078c: 03e00008 jr ra
400790: 00000000 nop
从汇编代码中可以看出,如果else成立,即x==0,则第一条跳转指令不成功,指令得以顺序执行。
而如果if成立,则需要多执行一次跳转。
其他说明:
likely(x)宏传入__builtin_expect(!!(x), 0)的第一个参数为!!x,这样写是因为__builtin_expect的第一个参数需要为long型,而我们如果想传入指针或字符串类型,则需要使用!!x将x变成long型,例如,如果一个指针ptr==NULL,则!ptr=1,而!!ptr=0。
注意有些gcc版本没有实现__builtin_expect内建函数,所以这个函数不会起实际作用,相应的,likely(x)和unlikely(x)也就没有效果了。