likely and unlikely are hints to a compiler that a conditional is likely (or not) to run, informing its decision about how to lay out branches in a way that's good for the pipeline and/or I-cache locality, or whether or not to make branchless asm.
likely
and unlikely
are hints to a compiler that a block of code controlled by a run-time condition is likely (or not) to run. This will influence its decisions about how to lay out branches in a way that's good for the pipeline and/or I-cache locality (prefer not-taken branches in the common case).
Also, either hint will discourage compilers from making branchless asm, since predictable branches can be better than cmov. (e.g. in a case like gcc optimization flag -O3 makes code slower than -O2 without profile-guided optimization, gcc -O3
guesses the branch will be hard to predict and makes branchless asm, but since it is predictable in practice -O2
's branchy asm is faster. A likely
or unlikely
hint might have had the same effect, even if the actual data is evenly split between taken and not-taken.)
The GCC compiler provides __builtin_expect
, and likely()
and unlikely()
are macros that wrap it builtin. ISO C++20 introduces [[likely]]
and [[unlikely]]
attributes that attach to blocks (actually labels or statements) instead of conditions.
These hints do not affect run-time dynamic branch prediction by typical modern high-end CPUs; this is a common misconception.
A few superscalar / out-of-order CPUs have supported runtime branch hints embedded into machine code, for example PowerPC. Pentium 4 also supported hints, but earlier and later x86 CPUs ignore them. likely/unlikely hints may or may not result in a compiler using run-time hints on the rare targets that do support them.
Static prediction based on the branch being forward or backward does still happen in some CPUs (when the dynamic predictors don't have a prediction for a branch). See Why did Intel change the static branch prediction mechanism over these years? for more info on how x86 microarchitectures have evolved. However, laying out blocks of code to minimize taken branches on the fast (likely) path usually optimizes for this anyway, whether it's relevant for the target CPU or not (e.g. modern x86).
Resources / examples:
- Is there a compiler hint for GCC to force branch prediction to always go a certain way? - no, only to lay out code for good results when the dynamic prediction does learn that it always goes a certain way (and/or with static prediction).
- How do the likely/unlikely macros in the Linux kernel work and what is their benefit? example of x86-64 asm output from gcc4.8
- Why doesn't likely and unlikely macros have any effect on ARM assembly code? - the compiler decided to use branchless anyway, since ARM has powerful conditional execution.
- Ulrich Drepper's What Every Programmer Should Know About Memory, pages 56 and 57, and the discussion of static branch prediction and bubbles in the pipeline.
- https://xania.org/201602/bpu-part-two - Matt Godbolt's experiments with CPU branch predictors in Nehalem vs. later Intel microarchitectures.
See also the branch-prediction tag; in some ways runtime branch prediction is a different subject from compile-time branch hints.