Branch Prediction – Why CPUs Guess the Future

Branch Prediction

When you write an if statement, it looks simple.
Check a condition, choose a path, move on.

For the CPU, that if is a problem.

Not because it’s complex, but because it breaks the flow of execution.

To stay fast, CPUs don’t wait for decisions.
They guess.

That guessing is called branch prediction.

Why Branches Are a Problem for CPUs

Modern CPUs use instruction pipelines.
They fetch, decode, and execute instructions ahead of time.

A branch changes the next instruction address.

Example:

if (x > 0) {
    do_a();
} else {
    do_b();
}

Until x > 0 is evaluated, the CPU does not know:

  • Should it execute do_a()?
  • Or do_b()?

If the CPU waits, the pipeline stalls.
Stalls are expensive.

So CPUs do something smarter.

They predict the future.

What Is Branch Prediction

Branch prediction is the CPU’s way of answering this question early:

“Which path will this branch most likely take?”

The CPU:

  • Makes a prediction
  • Continues fetching and executing instructions
  • Fixes things later if it was wrong

If the guess is right, execution looks smooth.
If the guess is wrong, the CPU has to undo work.

What Happens on a Correct Prediction

When prediction is correct:

  • Pipeline stays full
  • Instructions execute without interruption
  • Performance stays high

This is why:

  • Simple loops are insanely fast
  • Predictable code scales well

Most real-world branches are predictable.

What Happens on a Misprediction

When the CPU guesses wrong:

  • Speculatively executed instructions are discarded
  • Pipeline is flushed
  • Correct path is fetched again

This costs:

  • Dozens of CPU cycles
  • Sometimes more than a cache miss

A single bad branch in a hot loop can dominate runtime.

How CPUs Actually Predict Branches

Branch prediction is not random.

Modern CPUs use:

  • History of previous branch outcomes
  • Pattern detection
  • Per-branch tracking

If a branch was taken 99 times before, the CPU assumes it will be taken again.

Example:

for (int i = 0; i < 1000; i++) {
    ...
}

The branch is taken repeatedly, then not taken once at the end.

The CPU learns this pattern quickly.

Static vs Dynamic Prediction

Static Prediction

Older or simpler CPUs use fixed rules:

  • Backward branches are usually taken
  • Forward branches are usually not taken

This works okay but not great.

Dynamic Prediction

Modern CPUs use runtime behavior:

  • Records past outcomes
  • Adjusts predictions continuously
  • Maintains internal prediction tables

This is why the same code runs faster after “warming up”.

Branch Prediction and Speculative Execution

Branch prediction enables speculative execution.

The CPU:

  • Predicts the branch
  • Executes instructions on that path
  • Commits results only if prediction was correct

From your code’s point of view:

  • Everything still looks sequential
  • Incorrect speculation is invisible

Except for performance.

Why Unpredictable Branches Are Slow

Branches become expensive when:

  • Outcomes change frequently
  • Data is random
  • Input patterns vary heavily

Examples:

  • Hash-based lookups
  • Randomized conditions
  • Branches dependent on user input

The CPU cannot learn a stable pattern.

Result: frequent mispredictions.

Branchless Code (Why It Sometimes Wins)

Sometimes, removing branches helps.

Example:

x = condition ? a : b;

This can be compiled into branchless instructions.

Benefits:

  • No prediction needed
  • No pipeline flush
  • More consistent performance

Downside:

  • More instructions
  • Not always faster

Branchless code is a tool, not a rule.

Why This Matters to Software Engineers

Branch prediction explains:

  • Why tight loops are fast
  • Why unpredictable logic kills performance
  • Why benchmarks lie sometimes
  • Why “simple if statements” aren’t free
  • Why CPU performance feels data-dependent

You don’t need to optimize every branch.
But in hot paths, branches matter.

Learn More About relevant topics:

Common Misconception

“An if statement is cheap”

Sometimes it is.
Sometimes it’s one of the most expensive things in your program.

It depends on predictability, not complexity.

Final Thought

CPUs don’t wait for decisions.
They bet on them.

When your code behaves consistently, CPUs reward you.
When it behaves randomly, CPUs punish you.

Understanding branch prediction turns performance from magic into logic.

References and Sources

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top