Pipelining & Hazards

a control hazard

You are driving toward a fork in the road, but the navigator has not finished saying 'turn left' or 'go straight.' To keep moving you have to commit to one road before you know which is right — and if you guessed wrong, you must back up and lose time. A control hazard is the processor's fork in the road: a branch instruction decides which instruction runs next, but that decision is not ready in time to fetch the next instruction without guessing.

Here is the timing. A conditional branch like beq x1, x2, target is fetched in IF, but whether it is taken — and therefore what address to fetch from next — is not known until the comparison finishes a stage or two later. Yet the pipeline wants to fetch a new instruction every single cycle. So in the cycles right after the branch, the machine has already fetched the instructions that physically follow it, before knowing whether those are the right ones. If the branch turns out to be taken, those fetched-ahead instructions are wrong and must be discarded — a flush — and the correct target fetched instead, costing the cycles already spent.

Control hazards are costly because branches are everywhere — loops, if-statements, function calls — often one in every five or six instructions. Three responses exist. Stall: freeze fetching until the branch resolves (simple, but wastes cycles every branch). The delayed branch: an old trick that always executes the instruction right after the branch, turning the wasted slot into useful work. And the dominant modern answer, branch prediction: guess the outcome, fetch speculatively down the guessed path, and only flush on the rare mistake. A good predictor is right well over ninety percent of the time, so control hazards mostly vanish — until a misprediction, which costs a full pipeline flush.

A loop: beq x1, x0, exit decides whether to loop again or leave. While it is still comparing in EX, the pipeline has already fetched the next two instructions assuming fall-through. If the branch is actually taken to exit, those two are wrong: flush them and fetch from exit instead, paying the wasted cycles.

A branch's outcome arrives late, so instructions fetched right after it may be wrong and need flushing — the control hazard.

Branch prediction is a performance feature, not a correctness one: a wrong guess never produces a wrong answer, because mispredicted instructions are flushed before they commit. The cost of a misprediction is lost cycles, not lost correctness.

Also called
branch hazardcontrol-flow hazard分支危障控制流危障