Worked examples — Pipeline hazards — structural, data (RAW - WAR - WAW), control
This page is the drill ground for the parent topic. We are going to hit every kind of situation a hazard question can throw at you: each hazard family, each degenerate case (no hazard at all), the tricky load-use timing, the reordering cases that only appear out-of-order, and the arithmetic of performance. Guess first, then check.
Before we start, one reminder of the clock-cycle grid we read all timing from. Each row is one instruction; each column is one clock cycle; the five stages IF ID EX MEM WB march diagonally down-right because a new instruction starts one cycle later than the one above it. Look at this picture and keep it in your head — every example below is just "which stage is where in which column?"

The scenario matrix
Here is the full space of cases this topic can ask about. Every worked example below is tagged with the cell it covers.
| # | Cell class | What makes it special | Example |
|---|---|---|---|
| A | No hazard (independent instructions) | the "zero / degenerate" input — nothing collides | Ex 1 |
| B | Structural — shared memory port | resource conflict, values irrelevant | Ex 2 |
| C | Data RAW, forwardable | ALU→ALU, fixed by bypass, zero stalls | Ex 3 |
| D | Data RAW, load-use | the one RAW forwarding can't fully fix → 1 stall | Ex 4 |
| E | Data WAR | anti-dependence — why it's safe in-order | Ex 5 |
| F | Data WAW | output dependence — only real out-of-order | Ex 6 |
| G | Control — branch flush | wrong instructions fetched | Ex 7 |
| H | Performance arithmetic | plug the CPI / speedup formulas | Ex 8 |
| I | Real-world word problem | translate English → hazard classification | Ex 9 |
| J | Exam twist — combined hazards + false alarm | reject a fake hazard, count real ones | Ex 10 |
Example 1 — Cell A: the degenerate "no hazard" case
Forecast: Before reading on, guess: any stalls?
- List what each instruction writes and reads. I1 writes
R1, readsR2,R3. I2 writesR6, readsR7,R8. Why this step? Every data hazard requires an overlap in the registers touched. No overlap → no true dependence to worry about. - Intersect the sets. Written-by-I1 = {R1}. Read/written-by-I2 = {R6,R7,R8}. Intersection = ∅ (empty). Why this step? An empty intersection means I2 never needs anything I1 produces, so their overlap in the pipeline changes nothing.
- Conclusion: 0 stalls. Both run back-to-back at full pipeline speed.
Verify: The register sets are disjoint, so no matter which stage each is in during any cycle, I2 never reads a stale value. This is the "zero input" that anchors all the others — a hazard needs a shared name, and here there is none. ✅
Example 2 — Cell B: structural hazard on a unified memory
Forecast: Which two instructions clash, and in which column?
- Write the grid for four instructions.
Why this step? Structural hazards are about hardware in the same column, so we must literally look down each column.c1 c2 c3 c4 c5 I1: IF ID EX MEM WB I2: IF ID EX MEM I3: IF ID EX I4: IF ID - Scan column c4. I1 is in MEM (touches memory for data), I4 is in IF (touches memory for the instruction). Why this step? Both MEM and IF use the memory port. Same resource, same cycle = clash.
- Cheapest correctness fix: stall I4 by 1 cycle (insert a bubble) so its IF slides out of c4. Why this step? A stall never breaks correctness — it just delays. The design fix is splitting into separate I-cache and D-cache, but "cheapest immediate" fix = 1 bubble.
Verify: After the 1-cycle stall, I4's IF moves to c5; in c5 the memory is used only by I4 (I1 already finished WB in c5's grid... actually I1's WB is c5 and uses the register file, not memory). No column then has two memory users. ✅ Note this clash has nothing to do with values — I1 and I4 could be totally independent. (See the [!mistake] in the parent.)
Example 3 — Cell C: RAW fixed by forwarding (zero stalls)
Forecast: R1 is needed early but written late — but we have forwarding. Stalls?
- Classify the dependence. I1 writes R1; I2 reads R1; I1 is earlier. Read-After-Write = RAW, the true dependence. Why this step? Only RAW is a real data-flow hazard; naming which one tells us which fix applies.
- Find when the value is ready vs needed. R1 is computed at end of I1's EX (c3). I2 needs R1 at the start of its EX (c4). Why this step? Forwarding works when "ready time ≤ needed time." Here ready = end of c3, needed = start of c4. Ready first! ✅
- Route it: forward the ALU output from the EX/MEM pipeline register straight into I2's EX input. Why this step? This moves the value across space (stage to stage) without waiting for WB.
- Conclusion: 0 stalls.
Verify: end-of-EX(I1) is cycle 3; start-of-EX(I2) is cycle 4; , so a forward path exists and no bubble is required. ✅
Example 4 — Cell D: the load-use RAW (forwarding can't fully fix it)
Forecast: Same shape as Ex 3 — but I1 is a LOAD now. Does forwarding still give 0 stalls?
- Find when R1 is ready. A load's data appears only at end of MEM (c4), not EX. Why this step? This is the crucial difference from Ex 3 — the produced value lives one stage later.
- Find when R1 is needed. I2 needs R1 at start of its EX, which without stalling is c4 too. Why this step? We compare ready (end c4) vs needed (start c4). Needed comes first — the value doesn't exist yet!
- Fix: insert 1 stall (bubble), pushing I2's EX to c5. Now the load's MEM result (end c4) can be forwarded into I2's EX (start c5). Why this step? Forwarding moves data through space, not back in time; the only way to make ready ≤ needed is to delay the consumer by one cycle.
- Conclusion: exactly 1 stall.

Verify: Without stall, need-start(EX) = c4 while ready-end(MEM) = c4, so need < ready → impossible → ≥1 stall. With 1 stall, need-start = c5 and ready = end c4; ✅. Exactly 1 bubble suffices. ✅
Example 5 — Cell E: WAR — why it's a non-hazard in-order
Forecast: I2 overwrites R2 that I1 reads. Danger?
- Classify. I1 reads R2; I2 writes R2; I1 is earlier. Write-After-Read = WAR, an anti-dependence (a name dependence, not true data flow). Why this step? Naming it WAR tells us the risk is only about ordering the write before the read.
- Locate the read and the write in time. I1's read of R2 happens in ID = c2. I2's write of R2 happens in WB = c6 (I2 starts c2, so WB is c2+4 = c6). Why this step? The hazard would occur only if the later write beat the earlier read.
- Compare: read at c2, write at c6. — the read is comfortably first. Why this step? Because reads are early (ID) and writes are late (WB) and instructions stay in order, the earlier instruction always reads before the later one writes.
- Conclusion: no hazard, 0 stalls. WAR becomes real only with out-of-order execution.
Verify: ID(I1)=cycle 2, WB(I2)=cycle 6, ⇒ read precedes write ⇒ WAR safe. ✅
Example 6 — Cell F: WAW — output dependence, only real out-of-order
Forecast: If the slow MUL finishes writing after the fast ADD, what's in R1?
- Classify. Both write R1; I1 earlier, I2 later. Write-After-Write = WAW, an output dependence (name dependence). Why this step? Program order demands the last write wins, i.e. I2's value must remain.
- Compute write times. I1: IF c1, ID c2, then EX = c3,c4,c5,c6 (4 cycles), MEM c7, WB c8. I2: IF c2, ID c3, EX c4, MEM c5, WB c6. Why this step? We need the actual WB cycles to see which write lands last.
- Compare: I2 writes at c6, I1 writes at c8. The slow MUL writes after the fast ADD! So R1 ends up holding MUL's stale result — wrong. Why this step? When variable-latency writes can retire out of order, the earlier instruction can finish last, violating "last write wins."
- Fix: register renaming — give each write a fresh physical register — eliminates WAW (and WAR) entirely. Why this step? WAW is caused by reusing a name; renaming removes the name collision so the two writes target different physical registers, and the read of "R1" is steered to I2's.
Verify: WB(I1) = c8, WB(I2) = c6, and ⇒ later-program-order I2 retires first ⇒ WAW hazard is real here. In the plain in-order single-cycle-EX pipeline, both would be 1-cycle EX and I1 would retire at c5 < c6, so no WAW — confirming WAW needs variable latency / reordering. ✅
Example 7 — Cell G: control hazard and the flush penalty
Forecast: Between fetching the branch and knowing it's taken, how many instructions sneak in?
- Locate resolution. Branch is fetched in c1, and its outcome is known at end of EX = c3. Why this step? Everything fetched between c1 and the resolution cycle was fetched on a guess.
- Count instructions fetched under the guess. In c2 the next sequential instruction enters IF; in c3 another enters IF. That's 2 instructions fetched before c3 finishes. Why this step? Predict-not-taken keeps fetching the fall-through path; if the branch is taken those are all wrong.
- On mispredict (taken): flush those 2 instructions and redirect IF to the branch target. Penalty cycles. Why this step? The flushed slots become bubbles; the number flushed = branch penalty.

Verify: Resolution at end of EX = pipeline position 3; instructions fetched in the interim = (resolve stage index − 1) = . Penalty . ✅ (Earlier resolution → smaller penalty; this is why designs push branch resolution into ID via a dedicated comparator, and why branch prediction matters.)
Example 8 — Cell H: performance arithmetic
Forecast: Guess the CPI — is it near 1, or blown up?
- Apply the branch-CPI formula from the parent: . Why this step? Only the fraction of instructions are branches; of those only mispredict; each such mispredict adds cycles — multiply the probabilities.
- Plug in: Why this step? fraction that mispredict; times 4 cycles = 0.08 extra cycles per instruction on average.
- Speedup using with total stall per instruction : Why this step? Single-cycle takes stage-times/instruction; the pipeline takes cycles/instruction in steady state; the ratio is the speedup. Compare with the CPI performance equation.
Verify: ; . Sanity: with zero stalls speedup would be the full ; a small shaves it slightly to — reasonable. ✅ (This ties to Amdahl's Law: the un-pipelinable stall fraction caps your gain.)
Example 9 — Cell I: real-world word problem
Forecast: Which family — structural, data, or control?
- Translate to instructions. Each iteration:
MUL Rt, Rsample, RcoefthenADD Racc, Racc, Rt. TheADDreadsRtthat theMULjust wrote. Why this step? Word problems become tractable once you name the registers and see who reads whom. - Classify.
ADDreadsRtafterMULwrites it = RAW (true dependence). The accumulatorRaccalso chains RAW across iterations. Why this step? The value genuinely flows MUL → ADD; that is real data flow, not a naming artifact. - Fix. Forwarding the multiply result into the ADD's EX removes most of it; if MUL is multi-cycle, a few stalls remain — mitigated by out-of-order execution or loop unrolling so independent MULs fill the gap. Why this step? Forwarding kills the ALU→ALU RAW; the accumulator's serial chain is a true dependence that unrolling/reassociation loosens.
Verify: The hazard is RAW because the written register Rt (and Racc) is the same one read next — shared name and genuine value flow. Not structural (no resource contest) and not control (no branch decides which instruction; the loop branch is a separate, secondary control hazard). ✅
Example 10 — Cell J: exam twist (reject a fake hazard, count the real ones)
Forecast: Two potential hazard spots. How many are real, and total stalls?
- I1→I2:
LWproduces R1 (ready end MEM),ADDconsumes R1 in EX. This is the load-use RAW of Ex 4 → 1 stall, then forward. Why this step? Load latency lands one stage late; forwarding alone can't cover it. - I2→I3: disjoint registers (
R3,R1,R4vsR5,R6,R7— intersection ∅ on produced/consumed... I3 reads R6,R7, I2 wrote R3, no overlap). No hazard. Why this step? Empty overlap = independence (Cell A logic). - I3→I4 — the trap: I3 reads R6 (ID), I4 writes R6 (WB). This is WAR. Reads (c-ID) precede writes (c-WB) in order ⇒ not a hazard, 0 stalls. Reject the fake alarm! Why this step? Exam questions plant a WAR to see if you stall for it. In-order, WAR is always safe (Ex 5).
- Total real stalls = 1 (only the load-use).
Verify: Load-use contributes exactly 1 bubble (Ex 4). The disjoint pair contributes 0. The WAR pair: ID(I3) at cycle 4 < WB(I4) at cycle 7, ⇒ safe ⇒ 0. Sum stall. ✅
Recall Self-test before you leave
Load-use hazard minimum stalls (full forwarding) ::: 1 WAR hazards in a plain in-order pipeline ::: 0 (reads precede writes) Which single dependence is a true data hazard ::: RAW CPI for b=0.25, m=0.08, p=4 ::: 1.08 Branch penalty when resolved at end of EX, predict-not-taken, taken branch ::: 2