Branch Prediction Friendly Code
Branch prediction friendly code arranges the hot path so the conditional branches are highly predictable, avoiding misprediction pipeline flushes that cost tens of cycles per branch.
Definition
Branch prediction friendly code is written so that the conditionals on the hot path are biased strongly toward one outcome — data sorted so the early-out rarely triggers, branches eliminated by predication where possible — so the CPU branch predictor is correct nearly always and the pipeline is not flushed by a misprediction.
Context and scope
Applied in tight loops, parser hot paths, and any performance-sensitive code where a 10-cycle misprediction penalty is a measurable fraction of the per-element cost.
Common misconceptions
- Branch prediction is the hardware problem — it is a software opportunity; the predictor is right when the code makes the branch biased, and the programmer controls the bias
- Predication eliminates all branch cost — predication eliminates the misprediction; it computes both sides and selects, which costs execution resources even when one side is unused
Anti-patterns
- Putting the rare case first in an if-else, so the predictor learns the wrong bias on the cold path
- Branching on data-dependent conditions in a loop over sorted-then-unsorted data, training the predictor on one phase and mispredicting in the other
Related concepts
Authoritative source
What it is
Branch prediction friendly code is written so that the conditionals on the hot path are biased strongly toward one outcome — data sorted so the early-out rarely triggers, branches eliminated by predication where possible — so the CPU branch predictor is correct nearly always and the pipeline is not flushed by a misprediction. Applied in tight loops, parser hot paths, and any performance-sensitive code where a 10-cycle misprediction penalty is a measurable fraction of the per-element cost. The central difficulty is that interleaving is nondeterministic: the set of possible executions grows super-exponentially with the number of operations, and testing samples a vanishing fraction.
How it works
Correctness is established by reasoning about happens-before relationships, not by running more tests. Synchronization primitives are chosen for the specific guarantee needed — mutual exclusion, publication, or ordering — and composed only with a documented proof of absence of deadlock. Bounded resources apply backpressure rather than unbounded queuing that hides overload until memory exhausts.
When to apply and pitfalls
Apply whenever multiple flows share mutable state or resources. The dominant pitfall is reasoning sequentially about concurrent code — “this can’t happen because A finishes before B” — when in fact the scheduler can interleave at any instruction boundary. The second is using a coarse lock for simplicity and turning parallelism back into serialization.