kingsmasher1 kingsmasher1 - 2 months ago 21x
Linux Question

Why do we use __builtin_expect when a straightforward way is to use if-else

I came across a

in which they use

The documentation says:

Built-in Function:
long __builtin_expect (long exp, long c)

You may use
to provide the compiler with branch
prediction information. In general, you should prefer to use actual
profile feedback for this (
), 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
, which should be an integral
expression. 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
, since we expect
to be zero.

So why not directly use:

if ( x != 0 ) {}
else foo( );

instead of the complicated syntax with expect?


Imagine the assembly code that would be generated from:

if (__builtin_expect(x, 0)) {
} else {

I guess it should be something like:

  cmp   $x, 0
  jne   _foo
  call  bar
  jmp   after_if
  call  foo

You can see that the instructions are arranged in such an order that the bar case precedes the foo case (as opposed to the C code). This can utilise the CPU pipeline better, since a jump thrashes the already fetched instructions.

Before the jump is executed, the instructions below it (the bar case) are pushed to the pipeline. Since the foo case is unlikely, jumping too is unlikely, hence thrashing the pipeline is unlikely.