You already met the load-use hazard in Load-use hazard and stalls . That parent note showed you one clean case: lw then add, one stall, done. But the real world throws messier shapes at you — stores, zero registers, chains of dependents, branches right after a load. This page walks through every distinct case class , one at a time, so you never meet a scenario you haven't already seen solved.
Before any example, let's name the five things every pipeline stage is and does, so no symbol sneaks up on you. Then we define stall , bubble , and the exact three-condition test — everything you need is on this page.
Definition The five stages (our whole alphabet)
A MIPS instruction (see Five-stage MIPS pipeline ) moves through five stages, one per clock cycle:
IF — Instruction Fetch : grab the instruction from memory.
ID — Instruction Decode : read the register values it needs.
EX — Execute : do the arithmetic in the ALU (the calculator).
MEM — Memory : read from or write to data memory.
WB — Write Back : store the result into a register.
A data hazard means an instruction needs a value that an earlier, still-in-flight instruction hasn't finished producing.
N instructions take N + 4 cycles" (the pipeline fill/drain model)
A 5-stage pipeline is like a 5 -station assembly line. The first instruction must pass through all 5 stages before anything finishes — that's 5 cycles to fill the line. After that, one new instruction finishes every cycle, because the stages overlap. So:
total cycles = first finishes 5 + one per cycle after ( N − 1 ) = N + 4.
The "+ 4 " is the pipeline fill cost (the 4 extra cycles the first instruction needs beyond one). Example: N = 2 ⇒ 6 ; N = 3 ⇒ 7 . Every "ideal" cycle count below uses this; stalls add on top of it.
Definition Stall and bubble (used on every line below)
A stall is a decision to hold an instruction still for one cycle instead of letting it advance to the next stage. The empty slot this leaves in the pipeline behind the held instruction is called a bubble — think of it as a fake "do-nothing" instruction (a NOP) sliding down the pipe. "Insert 1 bubble" and "stall 1 cycle" mean the same thing: the dependent instruction waits one cycle in ID, and a hole travels through EX/MEM/WB doing no work.
Definition The three-condition stall test (self-contained)
The Hazard detection unit compares fields carried in the ID/EX pipeline register — a set of latches holding the info of whatever instruction is currently in EX. Two fields matter:
ID/EX.MemRead — a 1-bit flag that is 1 only when the EX-stage instruction is a load.
ID/EX.RegisterRt — the destination register number that a load will write into.
It also reads the incoming instruction's source-register numbers, IF/ID.RegisterRs and IF/ID.RegisterRt . A stall is inserted exactly when all three hold:
(1) ID/EX.MemRead = 1 (2) ID/EX.RegisterRt = IF/ID.RegisterRs OR ID/EX.RegisterRt = IF/ID.RegisterRt (3) ID/EX.RegisterRt = 0 ( a load is in EX ) ( the loaded reg is used next ) ( not the $0 register )
Definition Forwarding paths we rely on
Forwarding (from Data hazards and forwarding ) is a wire that sends a freshly-computed value straight to where it's needed , skipping the slow write-to-register-then-read-back route. Three paths appear on this page — see the figure below the definition:
MEM/WB → EX : sends a value that has just left MEM into the ALU inputs of a later instruction's EX stage.
MEM/WB → MEM : sends a value into a later store's MEM stage (so a store can write freshly-loaded data).
MEM/WB → ID : sends a value into a later instruction's ID stage — this one only exists in designs that resolve branches early (they compare registers in ID). We need it in Example 6.
Read the forwarding figure this way: each stage box is drawn once, and the curved arrows show where a value born at the MEM/WB latch (the red source on the right) can be teleported. The red-highlighted WB box is where the value physically lives; the curved arrows peel off it and land on EX , MEM , or ID of a later instruction. There is no arrow pointing backwards in time — every arrow lands on a stage happening in a later cycle, which is the whole point.
Intuition The one fact that drives everything on this page
A lw (load word) produces its value at the END of MEM — that's the moment the number arrives from memory. Every question below is really: "Does the instruction that wants this value need it BEFORE the end of that MEM cycle, or AFTER?" If before → stall. If after → forwarding alone saves us.
Read the timeline figure below this way: the five boxes are the five stages of a single lw, laid left-to-right in cycles 1–5. Four boxes are black; only the MEM box is red , because MEM is where the memory read happens. The red arrow points at the right edge of that MEM box — the instant (end of cycle 4) when the loaded number first exists. Nothing can read this value before that edge. Memorise this "ready at end of MEM" landmark; every example measures its need-cycle against it.
Here is every case class this topic can produce. Each later example is tagged with the cell it fills.
#
Case class
What makes it distinct
Stall?
A
Load → ALU use (immediate)
consumer needs data in EX , one cycle after load
1 stall
B
Load → independent instr → use
a gap absorbs the delay
0 stalls
C
Load → store of that value
consumer needs data in MEM , later than EX
0 stalls
D
Load into $zero (degenerate)
condition-3 guard: $0 never really changes
0 stalls
E
Load → use as base address of another load
lw→lw chained through address register
1 stall
F
Load → branch using loaded value
branch resolves early → needs data even sooner
2 stalls
G
Two dependents in a row after a load
only the first dependent triggers the stall
1 stall
H
Word problem: CPI of a real loop
limiting/aggregate behaviour over many instrs
—
I
Exam twist: which of 4 pairs stalls
apply the 3-condition test coldly
mixed
We'll hit all of A–I below.
Worked example Example 1 — Cell A: Load → ALU use (the canonical stall)
lw $2, 20 ($1)
add $4, $2, $3
Forecast: guess now — how many stall cycles, and in which cycle does add finally execute EX?
Step 1. Write both timelines aligned by cycle.
Why this step? You cannot reason about "too early / too late" without seeing the two EX/MEM cycles side by side.
Cycle: 1 2 3 4 5
lw IF ID EX MEM WB <- $2 ready END of cycle 4
add IF ID EX ... <- wants $2 START of cycle 4
Step 2. Compare the need cycle to the ready cycle : add needs $2 at start of cycle 4; it's ready at end of cycle 4. Need is earlier → hazard .
Why this step? This is the whole test — a comparison of two integers (need-cycle vs ready-cycle).
Step 3. Insert 1 bubble: hold add in ID one extra cycle (a NOP slides through EX behind it).
Why this step? One cycle of delay pushes add's EX from cycle 4 to cycle 5, which is after the data is ready — that's the earliest EX the ALU can legally start.
Cycle: 1 2 3 4 5 6
add IF ID (stall) EX MEM <- forward MEM/WB -> EX at cycle 5
Step 4. Count total cycles for both instructions: the last stage (WB of add) lands in cycle 7, so 7 cycles total.
Why this step? Total run time is just "cycle number when the last WB finishes"; counting it lets us price the hazard.
Verify: 2 instructions ideally finish in 2 + 4 = 6 cycles (fill/drain model). With 1 stall → 7 cycles. Extra cycles = 7 − 6 = 1 . ✓ Matches "load-use costs exactly one stall."
Worked example Example 2 — Cell B: an independent instruction hides the delay
lw $2, 20 ($1)
and $7, $8, $9
add $4, $2, $3
(The and is independent of $2; the add uses $2.)
Forecast: stall or no stall?
Step 1. Line them up.
Why this step? The and sits between load and use — position matters more than count.
Cycle: 1 2 3 4 5 6
lw IF ID EX MEM WB
and IF ID EX MEM WB
add IF ID EX MEM <- $2 needed at start of cycle 5
Step 2. add's EX is now in cycle 5. $2 is ready at end of cycle 4. Ready ≤ need → no hazard .
Why this step? The independent and used up cycle-4's EX slot, sliding add one cycle later for free.
Step 3. Forward from MEM/WB → EX at cycle 5 (the MEM/WB → EX wire from our forwarding definition above).
Why this step? Even without a stall, the value still needs a spatial shortcut from where it emerged (MEM/WB) to where it's read (EX); forwarding provides it so we skip the slow write-then-read.
Verify: 3 instructions, ideal 3 + 4 = 7 cycles (fill/drain model); actual 7 cycles, 0 stalls. ✓ This is exactly what Compiler instruction scheduling tries to arrange automatically.
Worked example Example 3 — Cell C: load then store the loaded value
lw $2, 0 ($1)
sw $2, 4 ($1)
(The sw stores $2 — it needs $2 in its MEM stage, not in EX.)
Forecast: the two instructions are adjacent and dependent on $2. Stall or not?
Step 1. Recall when a store reads its data register : a sw uses its store-data value in the MEM stage (that's the cycle it writes to memory), not in EX.
Why this step? The whole answer hinges on which stage consumes $2.
Cycle: 1 2 3 4 5
lw IF ID EX MEM WB <- $2 ready END cycle 4
sw IF ID EX MEM <- $2 consumed in MEM = cycle 5
Step 2. Need cycle = 5 (store's MEM). Ready cycle = 4 (load's MEM). Ready < need → no hazard .
Why this step? Stores are forgiving: they need the value late.
Step 3. A MEM/WB → MEM forwarding path (from our forwarding definition) delivers $2 into cycle 5. No bubble.
Why this step? The value left MEM/WB at end of cycle 4 and must reach the store's MEM at cycle 5 — a purely spatial hop that this second forwarding wire exists precisely to make.
Verify: 2 instructions, ideal 2 + 4 = 6 cycles, actual 6 , stalls = 0 . ✓
Worked example Example 4 — Cell D: loading into
$zero (degenerate)
lw $0, 8 ($1)
add $4, $0, $3
(The load's target is $0, the hardwired zero register.)
Forecast: the "next instruction uses the loaded register" — looks like Example 1. Does it stall?
Step 1. Recall MIPS rule: register $0 is hardwired to 0 ; a write to it is discarded.
Why this step? If the destination is $0, no real value is produced, so there is nothing to wait for.
Step 2. Apply condition (3) of our three-condition test: it stalls only if ID/EX.RegisterRt ≠ 0. Here the load's destination field ID/EX.RegisterRt holds the number 0 (register $0), so condition (3) is false .
Why this step? ID/EX.RegisterRt is the exact latch the detector inspects; when it equals 0 the detector is designed to not fire, avoiding a useless bubble.
Step 3. add reads $0 = 0 (always available), no dependency exists → no stall .
Verify: 2 instructions, ideal 6 cycles, actual 6 , stalls = 0 . ✓ (Condition-3 guard fires exactly here.)
Worked example Example 5 — Cell E: load feeds the
address of another load
lw $2, 0 ($1)
lw $5, 0 ($2)
(The second lw uses $2 as its base address.)
Forecast: the second lw uses $2 to build its memory address. Which stage needs $2, and does it stall?
Step 1. Where is an address computed? In EX (the ALU adds base + offset).
Why this step? Even though this is a load, the register $2 is consumed in EX, exactly like an ALU input — so condition (2) of the test matches on IF/ID.RegisterRs.
Cycle: 1 2 3 4 5 6
lw $2 IF ID EX MEM WB <- $2 ready END cycle 4
lw $5 IF ID EX MEM <- $2 needed START cycle 4 (to add offset)
Step 2. Need = start of cycle 4, ready = end of cycle 4 → hazard , same shape as Example 1.
Why this step? Both loads and ALU ops read their address/operand register in EX, so the timing mismatch is identical.
Step 3. Insert 1 stall; second load's EX slides to cycle 5; forward MEM/WB → EX.
Why this step? The bubble delays the address computation until after $2 is ready, and the MEM/WB → EX wire hands $2 to the address adder in cycle 5.
Verify: 2 instructions, ideal 6 cycles, with 1 stall = 7 cycles, extra = 1 . ✓ "Load feeding an address is still a load-use hazard."
Worked example Example 6 — Cell F: load feeds a branch condition
lw $2, 0 ($1)
beq $2, $3, LABEL
(Assume the branch is resolved in the ID stage — a common optimization; see Branch hazards and prediction .)
Forecast: when does beq need $2, and how many stalls?
Step 1. In an early-resolve design, the branch compares its registers in ID , not EX.
Why this step? Moving the comparison earlier speeds up branches but makes them hungry for their operands sooner.
Cycle: 1 2 3 4 5
lw $2 IF ID EX MEM WB <- $2 ready END cycle 4
beq IF ID ... <- $2 needed in ID = cycle 3
Step 2. Need = cycle 3, ready = cycle 4. To make the branch's consuming ID land after $2 is ready (end of cycle 4), its ID must be pushed to cycle 5.
Why this step? The earlier the consumer needs data, the more bubbles are required to close the gap.
Step 3. Insert 2 stalls so beq's ID lands at cycle 5, after $2 is ready.
Why this step? Moving the ID from cycle 3 to cycle 5 is a shift of two cycles, so two bubbles are needed.
Cycle: 1 2 3 4 5
beq IF (stall)(stall) ID <- $2 forwarded in via MEM/WB -> ID
Step 4. Deliver $2 at cycle 5 using the MEM/WB → ID forwarding path (the third path we defined above, which only exists in early-resolve designs).
Why this step? $2 left the MEM/WB latch at end of cycle 4; the branch's comparator lives in ID; the MEM/WB → ID wire is exactly the bypass that carries the value from that latch into the ID comparator at cycle 5.
Verify: need-cycle 3, ready-cycle 4; stalls required to push the ID to cycle 5 = 5 − 3 = 2 . ✓ Loads before early-resolved branches are the worst load-use case.
Worked example Example 7 — Cell G: two dependents in a row
lw $2, 0 ($1)
add $4, $2, $5
sub $6, $2, $7
(Both add and sub use $2.)
Forecast: two instructions use $2. How many stalls total — one, or two?
Step 1. Only the instruction in ID while the load is in EX triggers the detector.
Why this step? The hazard detection unit's condition (1) checks the EX-stage load; it fires once, on the immediately-following dependent.
Cycle: 1 2 3 4 5 6 7
lw IF ID EX MEM WB
add IF ID (stall)EX MEM WB <- stalled once, EX cycle 5
sub IF (stall)ID EX MEM <- rides the same bubble
Step 2. After the single stall, add executes EX in cycle 5 and forwards $2 in via MEM/WB → EX. Because the bubble shifted everything behind it by one cycle, sub's EX now lands in cycle 6.
Why this step? A bubble is a wall: every later instruction slides one cycle back, so we must re-check sub at its new position.
Step 3. Re-test sub: its EX (cycle 6) is far after $2 is ready (end of cycle 4), so its need-cycle exceeds the ready-cycle → no extra stall for sub.
Why this step? The rule "need vs ready" applies to every consumer; sub passes it for free once it has been pushed back by the first bubble.
Verify: 3 instructions, ideal 3 + 4 = 7 cycles (fill/drain model), with 1 stall = 8 cycles, extra = 1 . Total stalls = 1 , not 2. ✓
Worked example Example 8 — Cell H: CPI of a real loop (aggregate/limiting behaviour)
A program runs 1000 instructions. Of these, 30% are loads, and 40% of loads are immediately followed by a dependent use (each such case costs one stall). Starting from an ideal pipeline CPI = 1.0 , find the actual CPI and the percent slowdown. (CPI = average C ycles P er I nstruction.)
Forecast: guess the CPI to two decimals before computing.
Step 1. Fraction of instructions that cause a stall = 0.30 × 0.40 = 0.12 .
Why this step? Only loads-with-immediate-use stall; multiply the two probabilities.
Step 2. Each such instruction adds exactly 1 stall cycle, so
CPI = 1.0 + 0.12 × 1 = 1.12.
Why this step? This is the parent note's formula CPI = 1.0 + ( stall freq ) × 1 .
Step 3. Percent slowdown = ( 1.12 − 1.0 ) /1.0 = 0.12 = 12% .
Why this step? Slowdown is the fractional increase in cycles per instruction.
Verify: stall cycles over the run = 1000 × 0.12 = 120 ; total cycles = 1000 × 1.12 = 1120 ; 1120/1000 = 1.12 . ✓ Faster memory (see Memory hierarchy and cache ) reduces misses , but not this structural hazard.
Worked example Example 9 — Cell I: the exam twist — which pairs stall?
For each pair, state stall / no stall using only the three-condition test (see Pipeline control signals ).
(a) lw $8, 0 ($9) ( b ) lw $8, 0 ($9) (c) lw $0, 0 ($9) (d) add $8, $9, $10
sub $4, $8, $5 sw $8, 0 ($9) add $4, $0, $5 sub $4, $8, $5
Forecast: guess how many of the four stall.
Step 1 (a). Condition (1) load in EX ✓, condition (2) $8 used in sub's EX ✓, condition (3) $8 ≠ $0 ✓. All three true → stall .
Step 2 (b). Condition (1) ✓, but the consumer is a store needing $8 in MEM (Cell C), so no EX-stage read → no stall .
Step 3 (c). Destination is $0, so condition (3) fails → no stall .
Step 4 (d). First instr is add, not a load → condition (1) (MemRead) fails. This is an ALU-ALU hazard fixed by forwarding → no stall .
Why these steps? Each pair breaks a different one of the three conditions — that's the point of the twist.
Verify: stalling pairs = { a } , count = 1 of 4 . ✓
Recall Quick self-test
A load produces its value at the end of which stage? ::: MEM
A store consumes its data register in which stage? ::: MEM
What is a bubble? ::: a NOP (do-nothing) slot inserted by a stall, sliding down the pipe
Why does loading into $0 never stall? ::: $0 is hardwired to 0, so no real value is produced (condition 3 fails)
Load feeding an early-resolved branch needs how many stalls? ::: 2
Two dependents right after a load cause how many total stalls? ::: 1
Where does "+ 4 " in "N + 4 cycles" come from? ::: pipeline fill: the first instruction needs 4 extra cycles to pass all 5 stages
CPI if 30% loads and 40% of loads have immediate use? ::: 1.12
Mnemonic The one-line test for every case
"When is it needed vs when is it ready?" Load is ready at end of MEM. Compare to the consumer's need-stage: EX → 1 stall, MEM → 0 stalls, ID (early branch) → 2 stalls, $0 target → 0.