Exercises — Control hazards and pipeline flushes
These problems build from recognising what a flush is up to designing penalty budgets and predictor behaviour. Every solution is hidden inside a collapsible callout so you can test yourself first. If a term feels unfamiliar, re-read Control hazards and pipeline flushes — nothing here is used before it appears there.
Prerequisite muscles: 5.2.01-Pipelining-fundamentals (the five stages IF, ID, EX, MEM, WB), 4.3.08-Branch-instructions (what a branch is), and 5.2.05-Data-hazards-and-forwarding (bubbles as a concept).

Look at the figure: the branch is in teal, resolving in EX at cycle 3. The two orange boxes fetched behind it (cycles 2 and 3) are the wrong-path instructions. The gap between "where we fetch" (IF) and "where we resolve" (EX) is exactly the number of instructions we must throw away.
Level 1 — Recognition
Exercise 1.1
In a classic 5-stage RISC pipeline (IF, ID, EX, MEM, WB) where a branch resolves in the EX stage, how many instructions must be flushed when the branch is taken?
Recall Solution
The branch is fetched (IF) at cycle . It reaches EX at cycle (IF→ID→EX is two hops). Meanwhile the fetcher ran ahead:
- Cycle : fetched the instruction now sitting in ID.
- Cycle : fetched the instruction now sitting in IF.
That is 2 instructions on the wrong path. Using the stage numbering from the top of the page (, ): Answer: 2 instructions.
Exercise 1.2
Fill in the blank: A flushed instruction is turned into a bubble, which means its control signals RegWrite and MemWrite are set to what value, and why?
Recall Solution
Both are set to 0 (recall the control-signal definition at the top of the page).
RegWrite = 0→ the instruction writes no register.MemWrite = 0→ the instruction writes no memory.
Setting these to 0 makes the instruction architecturally invisible: it flows through the remaining stages like any other instruction, but changes nothing the programmer can observe. We do not delete it, because deleting a slot mid-flight would desynchronise the perfectly-clocked stages.
Level 2 — Application
Exercise 2.1
A program has 20% branch instructions. The pipeline resolves branches in EX (2-cycle penalty) and flushes on every taken branch. If 60% of branches are taken, what is the average extra cycles per instruction (the CPI penalty)?
Recall Solution
Only taken branches cost a flush (this design assumes predict-not-taken implicitly — a taken branch means the fetched not-taken instructions were wrong), so here . Apply the product rule from the intuition box: Answer: 0.24 extra cycles per instruction (i.e. CPI rises from 1 to 1.24).
Exercise 2.2
Same machine as 2.1 but a hardware trick lets branches resolve in ID (1-cycle penalty). Recompute the CPI penalty, and state the percentage improvement over 2.1.
Recall Solution
Flush cycles drop from 2 to 1: Improvement: Answer: 0.12 cycles/instruction, a 50% reduction in branch penalty. Why: resolving one stage earlier means the fetcher has run ahead by only one wrong instruction instead of two, so exactly half the wasted work disappears.
Level 3 — Analysis
Exercise 3.1
A processor uses static predict-not-taken, 2-cycle EX resolution. Branches are 20% of instructions. Measurements show branches are taken 65% of the time. (a) What is the average branch penalty per instruction? (b) The architect proposes static predict-taken with target computed in ID (1-cycle penalty when the guess is wrong). Assume predict-taken is wrong exactly when the branch is not taken. Which scheme is better?
Recall Solution
(a) Predict-not-taken. Wrong whenever branch is taken (penalty 2):
(b) Predict-taken. Wrong whenever branch is not taken (), penalty 1:
Compare: , so predict-taken is better here — it both guesses the more common outcome and pays a smaller penalty (1 vs 2 cycles) when wrong. Answer: (a) 0.26; (b) 0.07 — predict-taken wins.
Exercise 3.2
Trace a 2-bit saturating counter (states: 00 Strongly-NT, 01 Weakly-NT, 10 Weakly-T, 11 Strongly-T; predict taken if state ≥ 10). It starts at 11 (Strongly Taken). A loop branch is taken 4 times then not-taken once (loop exit), and this whole pattern repeats. How many mispredictions occur per full loop pass in steady state?
Before solving, study the state machine in Figure 2 — it shows exactly how "taken" and "not-taken" outcomes push the counter left and right, and why the two middle "weak" states give it memory.

Recall Solution
Walk the counter, using Figure 2 to track each step. "Predicts T" means state ≥ 10. Taken → count up (max 11); Not-taken → count down (min 00).
| Actual | State before | Predict | Correct? | State after |
|---|---|---|---|---|
| T | 11 | T | ✓ | 11 |
| T | 11 | T | ✓ | 11 |
| T | 11 | T | ✓ | 11 |
| T | 11 | T | ✓ | 11 |
| NT (exit) | 11 | T | ✗ | 10 |
| T (re-enter) | 10 | T | ✓ | 11 |
After the exit the counter only slips to 10 (still "taken", the right-hand teal region of Figure 2), so the very next taken iteration is predicted correctly and pulls it back to 11. Answer: exactly 1 misprediction per loop pass — the exit.
This is why 2 bits beats 1 bit: a single anomaly (the exit) can't flip the prediction, because two bits demand two consecutive wrong outcomes to change the trend.
Level 4 — Synthesis
Exercise 4.1
Design-budget problem. You have a 5-stage pipeline, base CPI = 1. Instruction mix: 20% branches, and among branches 70% taken. You may spend transistors on one of:
- Option A: move branch resolution to ID → penalty 1 cycle on wrong guess, keep predict-not-taken.
- Option B: add a dynamic predictor with 90% accuracy, keep 2-cycle EX resolution.
Compute the resulting CPI for each and pick the winner.
Recall Solution
Recall , and branch penalty .
Option A (predict-not-taken, wrong only when taken, penalty 1):
Option B (predictor wrong 10% of all branches regardless of direction, penalty 2):
Compare: , so Option B (the dynamic predictor) wins. Its high accuracy (only 10% wrong) beats the cheaper-flush-but-still-often-wrong Option A. Answer: CPI_A = 1.14, CPI_B = 1.04 → choose Option B.
Exercise 4.2
Combine both improvements from 4.1: dynamic predictor at 90% accuracy and resolution moved to ID (penalty 1). Same mix (20% branches). What is the CPI, and what speedup does it give over the base machine that flushes 2 cycles on every taken branch (70% taken)?
Recall Solution
Base machine (no prediction, predict-not-taken, 2-cycle EX):
Combined machine (10% mispredict, 1-cycle penalty):
Speedup (same clock, same instruction count → ratio of CPIs, since fewer cycles per instruction means proportionally less total time): Answer: CPI ≈ 1.02, speedup ≈ 1.25× (about 25% faster).
Level 5 — Mastery
Exercise 5.1
Using the 7-stage deep pipeline defined just above, a branch resolves in EX3 (stage 5) while fetch happens in stage 1. Instruction mix: 25% branches, 60% taken. A predictor has accuracy . (a) Write the general penalty formula in terms of the flush count , misprediction rate , and branch fraction . (b) Find the minimum accuracy needed so the branch penalty per instruction is at most 0.05 cycles.
Recall Solution
(a) Flush count instructions. A flush happens only on a misprediction, at rate , and only for the branch fraction — the same three-factor product as every earlier exercise:
(b) Require penalty : Answer: (a) penalty ; (b) need accuracy. Note the taken-fraction 60% never appears — with a directional predictor, what matters is whether the guess is right, not which way the branch actually went. Deep pipelines (large ) demand very accurate predictors precisely because each mistake costs 4 flushed slots.
Exercise 5.2
Cycle-count synthesis. The loop below runs its body 1000 times. The bottom branch BNE is taken 999 times (loops back) and not-taken once (exit). Resolution is in EX (2-cycle flush). Compare total flush cycles under (a) predict-not-taken and (b) a 2-bit predictor starting Strongly-Taken.
loop: ... # loop body (no branches)
BNE loop # taken 999, not-taken 1
Recall Solution
(a) Predict-not-taken. The predictor always guesses "not taken", so it is wrong on every taken branch (999 of them), each costing 2 flush cycles. The single not-taken exit is predicted correctly (0 cost).
(b) 2-bit predictor, starts Strongly-Taken (11). It predicts taken correctly for all 999 taken iterations (counter pinned at 11, never leaves the strongly-taken state). It mispredicts only the single exit (1 event), costing 2 cycles:
Answer: (a) 1998 cycles wasted, (b) 2 cycles wasted — a 999× reduction.
Concluding discussion: the 2-bit predictor is dramatically better for loops because it correctly guesses the common (taken) case, whereas predict-not-taken is exactly backwards for a backward-branching loop — it guesses wrong on essentially every iteration. This single example is why real machines never rely on predict-not-taken for loops and instead use dynamic prediction (or at minimum the "backward branches predicted taken" heuristic). Almost all of the 1998 wasted cycles simply vanish.
Recall Self-check summary (reveal after attempting all)
Branch penalty is always one product ::: Flush count formula ::: (resolve stage index) − (fetch stage index) What CPI means ::: average cycles per instruction; base 1, raised by every flush Why 2-bit beats 1-bit in loops ::: one anomaly (loop exit) can't flip a 2-bit prediction, so re-entry is still predicted correctly What a bubble actually is ::: an in-flight instruction with RegWrite=0, MemWrite=0 — flows through but changes nothing
See also: 5.2.11-Speculative-execution for what happens after a good prediction (running ahead), and the 5.2.08 Control hazards and pipeline flushes (Hinglish) walkthrough in Hinglish.