likely/unlikely
Sergey AbbakumovMany people ask a question about the last article: what is the [[unlikely]]
attribute? This attribute is taken from a draft C++20 standard: https://en.cppreference.com/w/cpp/language/attributes/likely
It tells the compiler which branch of the condition or case in the switch statement is executed more often.
On x86/x64, the compiler will place the likely branch in assembler immediately after checking the condition, maximally utilizing the processor's instruction cache. There is no static branch prediction here. However, I won’t be surprised if in some PowerPC architecture there will be a special instruction to help the branch predictor.
There is no support for likely/unlikely attributes in compilers yet, but there are extensions:
#define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0)
An example (only Clang and GCC), where we expect IsValid() to return true more often:
bool IsValid(); int Bar(); int Baz(); int Foo() { if (likely(IsValid())) return Bar(); else return Baz(); }
Assembler:
Foo(): # @Foo() push rax call IsValid() test al, al je .LBB0_2 pop rax jmp Bar() # TAILCALL .LBB0_2: pop rax jmp Baz() # TAILCALL
An example where we expect IsValid() to return false more often:
bool IsValid(); int Bar(); int Baz(); int Foo() { if (unlikely(IsValid())) return Bar(); else return Baz(); }
Assembler:
Foo(): # @Foo() push rax call IsValid() test al, al jne .LBB0_1 pop rax jmp Baz() # TAILCALL .LBB0_1: pop rax jmp Bar() # TAILCALL
You may notice that the compiler puts a branch of code corresponding to our help immediately after the checking (test command). This can potentially give good acceleration if everything is marked correctly (notice that you can give an incorrect hint).
You also need to keep in mind that now processors are very well at branch prediction, so the difference can be very small.
Telegram channel: https://t.me/sea_plus_plus