Kernel : likely/unlikely macros

Submitted by Kedar Sovani
on February 11, 2005 - 4:46am

Ever wondered what the likely and unlikely macros in the linux kernel are ?

The macros are defined as :

#define likely(x)       __builtin_expect((x),1)
#define unlikely(x)     __builtin_expect((x),0)

The __builtin_expect is a method that gcc (versions >= 2.96) offer for programmers to indicate branch prediction information to the compiler. The return value of __builtin_expect is the first argument (which could only be an integer) passed to it.

To check it out how it could be beneficial, an excerpt from "info gcc" :

     if (__builtin_expect (x, 0))
                foo ();

[This] would indicate that we do not expect to call `foo', since we expect `x' to be zero.

Based on this information the compiler generates intelligent code, such that the most expected result is favored.


Let us consider it with a simple example function :
[kedar@ashwamedha ~]$ cat abc.c
int
testfun(int x)
{
        if(__builtin_expect(x, 0)) {
                              ^^^--- We instruct the compiler, "else" block is more probable
                x = 5;
                x = x * x;
        } else {
                x = 6;
        }
        return x;
}
 
[kedar@ashwamedha ~]$ gcc -O2 -c abc.c
[kedar@ashwamedha ~]$ objdump  -d abc.o
 
abc.o:     file format elf32-i386
 
Disassembly of section .text:
 
00000000 :
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   8b 45 08                mov    0x8(%ebp),%eax
   6:   85 c0                   test   %eax,%eax
   8:   75 07                   jne    11 < testfun+0x11 >
                                ^^^ --- The compiler branches the "if" block and keeps "else" sequential
   a:   b8 06 00 00 00          mov    $0x6,%eax
   f:   c9                      leave
  10:   c3                      ret
  11:   b8 19 00 00 00          mov    $0x19,%eax
  16:   eb f7                   jmp    f < testfun+0xf >

And let us see what happens if we make the "if" block more likely.

[kedar@ashwamedha ~]$ cat abc.c
int
testfun(int x)
{
        if(__builtin_expect(x, 1)) {
                              ^^^ --- We instruct the compiler, "if" block is more probable
                x = 5;
                x = x * x;
        } else {
                x = 6;
        }
        return x;
}
                                                                                                    
[kedar@ashwamedha ~]$ gcc -O2 -c abc.c
[kedar@ashwamedha ~]$ objdump  -d abc.o
                                                                                                    
abc.o:     file format elf32-i386
                                                                                                    
Disassembly of section .text:
                                                                                                    
00000000 :
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   8b 45 08                mov    0x8(%ebp),%eax
   6:   85 c0                   test   %eax,%eax
   8:   74 07                   je     11 < testfun+0x11 >
                                ^^^ --- The compiler branches the "else" block and keeps "if" sequential 
   a:   b8 19 00 00 00          mov    $0x19,%eax
   f:   c9                      leave
  10:   c3                      ret
  11:   b8 06 00 00 00          mov    $0x6,%eax
  16:   eb f7                   jmp    f < testfun+0xf >

thanks!

donquixort
on
January 6, 2006 - 9:55pm

Thanks for the info! The same problem was troubling me for some time. I couldnt figure out why there were 2 different functions with different parameters, yet returned the same value.

Thanks for the info!

vortechs
on
June 20, 2006 - 11:39am

Nice! I was wonder what the heck unlikely() was for when reading through some code. Now it makes a lot of sense.

Very helpful

ratnadeep
on
October 11, 2006 - 6:13am

Very well explained ! That helped a lot man !

I’ve still two doubts

Anonymous (not verified)
on
February 13, 2007 - 6:51am

I’ve still two doubts (sorry but I’m not so familiar with compilers):
1) In the example above we have "if {...}else{...};" I wonder which optimizations does gcc adds if the "else" statement has been omitted? In this case can we have a real improvement using likely/unlikely macros?
2) Supposing we have the following condition checks:
if (errtest1){
...
if (errtest2){
...
}
if (errtest3){
...
}
...
}
and most of time these returns false; so I want to add the unlikely macro.
Is it necessary to put the unlikely macro in each conditions or I only need to add it in the first line?

I think all the compiler

Kedar S (not verified)
on
February 14, 2007 - 11:59pm

I think all the compiler cares about is what is the next instruction that is to be executed if the "if" condition is unlikely. That next instruction could be part of the "else", or another "if", or another may be something else. Although, the space allocation of code is much more easier in case of the if/else than the others.

You could write similar problems and find out what it actually does.

unlikely is a hint about a boolean expression

farnz
on
February 15, 2007 - 12:47pm

In order:

  1. If the else block is omitted, the compiler only executes the block of code in the if block if the if expression is true; thus, by omitting the else, you ensure that the compiler only has to consider branching on one result of the expression. The likely and unlikely macros tell the compiler which result is more likely from the given expression, so that it can make a better decision about which codepath branches, and which codepath doesn't.
  2. unlikely(expression) is a hint to the compiler that expression will probably be false. You thus need unlikely() around each expression that's tested in an if, and likely to be false.

As an example, the following code can compile to two different forms:

/* before if */
if(error)
{
/* log error */
}
/* after if */

Either the compiler decides to branch if error is true, resulting in code like:

/* before if */
MOVS R0, error
BNE ifBlock
afterIf:
/* after if */
...
ifBlock:
/* log error */
B afterIf

Alternatively, it can decide to branch if error is false, resulting in code like

/* before if */
MOVS R0, error
BEQ afterIf
/* log error */
/* after if */

Taking a branch tends to be costly, so you want to avoid taking branches whenever you can. By using likely() and unlikely(), you can persuade the compiler to generate code that doesn't normally take the branch, which runs faster. In this example, putting unlikely() around error would make the compiler more likely to generate the first block of code (faster whenever error is false), whereas putting likely() around error would make the compiler more likely to generate the second block of code (faster whenever error is true).

Even if you have an else block, likely() and unlikely() can help; most CPUs have some form of static branch prediction, and likely() and unlikely() can be used by the compiler to help it generate code where the CPU's static branch predictor gets it right more often than not.

How this works on different architectures?

Asanga (not verified)
on
September 17, 2007 - 2:07am

How this works on different architectures at runtime branch prediction?

there is no connection

Anonymous (not verified)
on
January 30, 2008 - 2:16pm

there is no connection between these two. this is compiler optimization, simply, don't jump for more likely branches.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.