作用
likely
unlikely
是为编译器提供对分支优化的提示,基本用于if-else
的分支优化场景。if-else
在汇编时会将else分支的命令生成跳转语句(jmp),而跳转会影响程序性能,所以如果大部分情况下都是else
分支成立的话,程序每次都会执行跳转,从而影响效率,使用likely
和unlikely
即可以告诉编译器大部分情况下哪个分支更有可能成立,从而将该分支的语句编译到前面,提高运行效率。
实现
likely
和unlikely
是通过宏定义实现的:
#define likely(x) __builtin_expect(!!(x),1)
#define unlikely(x) __builtin_expect(!!(x),0)
GCC文档对__builtin_expect()
的解释如下:
-- Built-in Function: long __builtin_expect (long EXP, long C)
You may use `__builtin_expect' to provide the compiler with branch
prediction information. In general, you should prefer to use
actual profile feedback for this (`-fprofile-arcs'), as
programmers are notoriously bad at predicting how their programs
actually perform. However, there are applications in which this
data is hard to collect.
The return value is the value of EXP, which should be an integral
expression. The value of C must be a compile-time constant. The
semantics of the built-in are that it is expected that EXP == C.
For example:
if (__builtin_expect (x, 0))
foo ();
would indicate that we do not expect to call `foo', since we
expect `x' to be zero. Since you are limited to integral
expressions for EXP, you should use constructions such as
if (__builtin_expect (ptr != NULL, 1))
error ();
when testing pointer or floating-point values.
使用
举个栗子🌰
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
int main(char *argv[], int argc)
{
int a;
/* Get the value from somewhere GCC can't optimize */
a = atoi (argv[1]);
if (unlikely (a == 2)) //等同于if(a==2)
a++;
else
a--;
printf ("%d\n", a);
return 0;
}
注意,编译时需要加 -O2选项
可以用objdump -S XXX 来查看汇编指令
使用unlikely()
时,汇编指令为je(相等则跳转)
而使用likely()
时,汇编指令为jne (不相等则跳转)
网友评论