[C语言] __builtin_expect 分支预取优化
CPU预取指令在遇到分支时,会选择一个预测分支预取。分支预测器通过硬件电路在分支条件未真正计算出结果前猜测分支走向,从而让处理器继续预取和执行后续指令,提高并行度。但一旦预测错误,处理器已经执行的指令必须作废(清空流水线),然后转去正确的分支路径重新取指令,这会浪费许多 CPU 周期,故而gcc提供了__builtin_expect (long exp, long c),手动给编译器建议。
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
__builtin_expect 函数
GCC 提供了 __builtin_expect 函数,用于向编译器提供分支预测信息,以此优化代码,减少指令跳转带来的性能下降。
if (__builtin_expect (x, 0))
foo ();
exp:这是一个整型表达式,也就是需要进行预测判断的表达式,例如 (ptr != NULL)
。
c:它必须是一个编译时常量,不能是变量。该函数的语义是期望 exp 的值等于 c
if x else !x
jne X // if x
{
x //按顺序预取,默认分支不跳转
}
X{ // else !x
!x
}
但是 如果 !x的情况更常发生,可以将两种分支同时取反逻辑不变代码顺序改变,CPU默认分支不跳转预取指令时可以优先预取到可能性大的分支
if x else __builtin_expect(!x,1)
je X
{
!x // 被预取
}
{
x
}

浙公网安备 33010602011771号