Day 45: The load-use hazard: why one stall is unavoidable
The load-use hazard
Forwarding handles most dependencies — but not this one. A load produces its value in the MEM stage, one stage later than the ALU. If the *very next* instruction needs that loaded value in its EX stage, the data simply isn't ready in time — there's nothing to forward yet. This is the load-use hazard, and it requires exactly one stall cycle (a bubble), after which forwarding from MEM/WB covers it.
lw x1, 0(x2) IF ID EX ME WB
add x3, x1, x4 IF ID EX ME WB <- needs x1 in EX...
lw produces x1 at end of MEM (cycle 4).
add wants x1 in EX (cycle 4) -> too early by one cycle.
Insert one bubble:
lw x1, 0(x2) IF ID EX ME WB
add x3, x1, x4 IF ID -- EX ME WB <- now MEM/WB forwards x1 in timeThe interview classic
'Why does a load-use hazard need a stall even with full forwarding?' is asked constantly. The crisp answer: the load's data exists only after MEM, which is *after* the dependent instruction's EX — you can't forward data that hasn't been produced. One bubble delays the consumer by a cycle so forwarding can then reach it. A smart compiler fills that slot with an independent instruction.
Key terms
- Load-use hazard
- A load immediately followed by an instruction using its result; needs one stall despite forwarding.
- Bubble / stall
- A no-op cycle inserted to delay an instruction until its data is available.
- Load-use hazard detection
- Logic detecting a load in EX whose destination is a source of the instruction in ID.
- Delay slot filling
- A compiler scheduling an independent instruction into the stall slot to avoid the penalty.
Before moving on, you should be able to
Why can’t forwarding fully eliminate the load-use hazard?