The 2-bit counter was invented twice: by Tom McWilliams and Curt Widdoes in 1977 for the Lawrence Livermore S-1 supercomputer, and independently by Jim Smith at Control Data in 1979. Smith published it at ISCA 1981 in "A Study of Branch Prediction Strategies"; his 1999 Eckert–Mauchly award citation lists "saturating counters for branch prediction" first, and almost every microprocessor since builds on that paper.
Learning from the past: 1-bit and 2-bit history tables, and the BTB
After this lesson you will fill the exam's predictor table for any loop and any initial state, explain why one bit of memory does worse than no memory at all on a loop, and say what the branch target buffer adds that no direction predictor can.
A loop runs ten times. Its closing BNE is taken nine times and falls through once: it goes the same way 90 % of the time. The dumbest rule of the previous lesson, "always predict taken", is right 9 times out of 10.
Now give the hardware a memory: one bit per branch that stores what the branch did last time, and predict that. Remembering must beat guessing. Run the loop again and count — the one-bit predictor is right 8 times out of 10. Learning made it worse.
By the end of the lesson you will know where the two lost predictions go, why a second bit wins one of them back, and why even a perfect direction predictor cannot fetch the next instruction without a second, smaller table: the branch target buffer.
Hardware that learns at run time
Lesson 4 left the branch problem half solved. A static rule — always not taken, always taken, backward taken and forward not — is fixed before the program runs, so it cannot tell a loop that runs a million times from an if that flips with the data. In the five-stage pipeline of this course the branch outcome and its target are computed in ID, so every wrong guess costs one cycle: the wrong-path instruction becomes a NOP and fetch restarts at the right address.
Dynamic branch prediction — hardware that observes how each branch behaved in the past, at run time, and predicts its next outcome from that history (notes, p. 54). Nothing is decided by the compiler: the same binary adapts to its input.
The notes state the key assumption plainly (p. 54): "if a branch behaved a certain way in the past, it's likely to behave the same way again". It is temporal locality applied to control flow. The hardware that exploits it is two tables, both consulted in the Instruction Fetch stage:
- the Branch Outcome Predictor answers whether — Taken (T) or Not Taken (NT) — from the run-time history of this branch, or of other branches too. In this chapter it is a Branch History Table (BHT);
- the Branch Target Buffer (BTB) answers where: it returns the Predicted Target Address (PTA), the address the processor will fetch from if the branch is predicted taken. It is "useful only when BOP predicts Taken; irrelevant if Not Taken" (p. 54), because the not-taken successor is simply PC + 4.
A fetch then works in three steps (p. 54): the outcome predictor says T or NT; if T, the BTB supplies the PTA; the next instruction is fetched from the PTA or from PC + 4. Notice when: at the end of IF, before the instruction is decoded. Both tables are indexed with the PC of the instruction being fetched — the hardware does not yet know that it is a branch. Keep that in mind: it is why one of the two tables needs tags and the other does not.
The notes list the four cases of a right or wrong guess (p. 55); with the branch resolved in ID a wrong guess always costs the same one cycle:
| Prediction | Actual outcome | What the pipeline does | Penalty |
|---|---|---|---|
| Not Taken (fetch PC + 4) | Not Taken | correct: nothing | 0 |
| Not Taken (fetch PC + 4) | Taken | flush the sequential instruction (NOP), fetch from the BTA computed in ID | 1 cycle |
| Taken (fetch from the PTA) | Taken | correct: nothing | 0 |
| Taken (fetch from the PTA) | Not Taken | flush the target instruction (NOP), fetch PC + 4 | 1 cycle |
Look at the symmetry of that table. A dynamic predictor does not change what a misprediction costs — the pipeline fixes that: one cycle here, fifteen to twenty in a deep out-of-order core (Agner Fog's measurements on real Intel and AMD cores; background, not in the notes). It changes how often you pay. In the formula sheet's "CPI = 1 + stall cycles per instruction" the branch term reads as follows (lesson 4 wrote the same thing as \(1 + f_b \cdot \text{penalty} \cdot p_{\text{mis}}\)):
- \(f_b\)
- fraction of the executed instructions that are branches
- \(a\)
- prediction accuracy; \(1 - a\) is the misprediction rate
- \(P\)
- misprediction penalty in cycles: 1 in this pipeline, since the branch is resolved in ID
Two predictors, two stakes. With one instruction in five a branch (\(f_b = 0.2\)) and \(P = 1\), a predictor that is right 80 % of the time adds \(0.2 \times 0.2 \times 1 = 0.04\) to the CPI; one that is right 90 % adds \(0.02\). Make the penalty 15 cycles and the same two numbers become \(0.60\) and \(0.30\) — a \(1.6\times\) against a \(1.3\times\) slowdown on a base CPI of 1. That is why the industry kept inventing predictors long after the first one worked.
The predictor decides how often you pay for a branch; the pipeline decides how much.
One bit per branch: remember the last outcome
The simplest learning machine remembers one thing per branch: what it did last time.
Branch History Table (BHT; Hennessy & Patterson say branch prediction buffer) — a table indexed by the address of the branch instruction, whose entry is a tiny finite-state machine; the state of the machine is the prediction (notes, p. 56).
Two phrases of p. 56 are worth keeping verbatim for an open question: the BHT is "a cache-like structure that maps branch addresses to prediction states", and its history is implicit — "rather than storing an explicit sequence of past outcomes, each entry implicitly encodes the recent behavior of the branch through its FSM state". Explicit history registers come in the next lesson; here the whole past of a branch is compressed into one or two bits.
With one bit the machine has two states. The bit is the last outcome: if it says T, predict Taken; if NT, predict Not Taken. After the branch resolves, a correct prediction leaves the bit alone and a wrong one flips it — which is the same as writing the actual outcome into the bit.
Indexing: low-order bits of the PC, and no tags
Which entry belongs to which branch? The notes (p. 57): "use k lower bits (right side) of the branch's address as the index", which gives \(2^k\) entries; and, in bold, "No tags: any branch with the same low-order bits shares the entry (can cause interference)". One practical detail: instructions are four bytes long and aligned, so the lowest two address bits are always 00 and a real table takes its \(k\) bits just above them; the exam phrase "low-order bits" is fine.
Why is a table without tags acceptable? Because the worst a wrong entry can do is a wrong prediction, which the pipeline catches when the branch resolves: correctness is never at stake, only accuracy — and a tag would cost more bits than the one or two it protects. Two branches whose addresses agree in the \(k\) index bits overwrite each other's state: the conflict problem (p. 57), called branch predictor aliasing in the deepening on the next lesson's pages. The partial cures (p. 58) are the obvious ones: a bigger table, so that fewer branches collide, and hashing the address bits to spread out branches that share low-order bits.
Example 5 of the notes: two misses on a loop
Now the puzzle of the hook, on the loop the exam papers use. The 10 June 2025 paper writes it with ADDI.U $R1, $R0, 0 and ADDI.D $F2, $F0, $F0; the 2026 paper drops the dollar signs, and so does this notebook:
INIT: ADDUI R1, R0, 0
ADDUI R2, R0, 40 ; R2 = 20 in the June 2025 paper
LOOP: LD F0, 0(R1)
FADD F2, F0, F0
SD F2, 0(R1)
ADDUI R1, R1, 4
BNE R1, R2, LOOP
With R2 = 40 the BNE is executed ten times: taken nine times and not taken at the exit — the pattern the notes write as T T T T T T T T T NT (p. 57). Suppose the loop has been run before, so the entry still holds the NT of the previous exit. Walk the ten executions:
| Execution of the BNE | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| Bit before (= prediction) | NT | T | T | T | T | T | T | T | T | T |
| Branch outcome | T | T | T | T | T | T | T | T | T | NT |
| Result | miss | hit | hit | hit | hit | hit | hit | hit | hit | miss |
| Bit after | T | T | T | T | T | T | T | T | T | NT |
Two misses, and both have a reason. At the exit the bit still says T, because the branch was taken nine times in a row; the NT is mispredicted and flips the bit. At the next entry the bit says NT, because that is what the branch did last — the T is mispredicted and flips it back. "With 100% of 10 iterations, the BHT only catches 8 out of 10 iterations, the accuracy is 80%" (p. 57). A one-off anomaly costs two misses: the surprise itself, and its echo one execution later, when the predictor has just learned the anomaly and the old behaviour resumes. A one-bit predictor is always exactly one step behind. That is half of the puzzle.
The notes name two shortcomings (p. 57): the bit flips after a single misprediction, unstable on exactly the loops it should excel at, and the conflicts above. A bigger table does nothing for the loop exit: that miss is not interference, it is the inability of one bit to represent "nine times T, then NT".
Counting rules for the exam. A loop closed by a BNE at the bottom with \(N\) iterations executes its branch \(N\) times (\(N - 1\) taken, then not taken). A loop tested at the top (BEQ … DONE, then J LOOP at the bottom) executes the exit branch \(N + 1\) times (\(N\) not taken, then taken). The misprediction rate divides by the number of executions of the branch — the number of BHT accesses, warm-up misses included — and "the state left in the BHT" is the state after the last update. The May 2025 midterm asked for a top-tested loop with R1 = 0 … 100 on a 1-bit entry initialised Taken: 101 accesses and 2 mispredictions, the first one because the entry said T and the branch fell through, the last one at the exit.
Two bits: tolerate one surprise
The cure is a predictor that does not change its mind after one surprise. The notes call the 1-bit behaviour flip-flopping: "1 misprediction is enough to change the prediction", two misses per loop, "exiting the loop (NT mispredicted as T)" and "re-entering the loop (T mispredicted as NT)" (p. 59). The fix is a second bit that records not the last outcome but the predictor's confidence.
2-bit Branch History Table — each entry is a four-state machine: Strongly Taken (ST) and Weakly Taken (WT) predict Taken; Weakly Not Taken (WNT) and Strongly Not Taken (SNT) predict Not Taken (notes, p. 59). With the encoding ST = 11, WT = 10, WNT = 01, SNT = 00 the prediction is simply the high bit.
The rule of motion: an outcome that agrees with the prediction pushes the state toward the strong end; an outcome that contradicts it moves the state toward the other side. From a strong state it lands in the weak state of the same direction — the prediction survives one anomaly. From a weak state it crosses the line and the prediction flips; how far it crosses is where the two drawings of this machine differ. The notes' figure (p. 59) is reproduced below; the two dashed arcs are the alternative described right after it.
Look closely at the two vertical arrows of the notes' figure: from WT a Not Taken jumps straight to SNT, and from WNT a Taken jumps straight to ST. That is the machine of Hennessy & Patterson's figure, the course's reference book. A pure saturating counter — count up on Taken, down on Not Taken, stop at 3 and at 0 — would instead go WT → WNT and WNT → WT, the dashed arcs. On every loop pattern of this course the two machines give identical tables; they differ only when the outcome alternates while the machine sits in a weak state:
| Execution | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| Branch outcome | NT | T | NT | T | NT | T |
| Saturating counter: state / prediction | WT / T | WNT / NT | WT / T | WNT / NT | WT / T | WNT / NT |
| Result | miss | miss | miss | miss | miss | miss |
| Notes' figure: state / prediction | WT / T | SNT / NT | WNT / NT | SNT / NT | WNT / NT | SNT / NT |
| Result | miss | miss | hit | miss | hit | miss |
Neither machine learns the alternation — the saturating counter is always one step behind, the notes' machine at least settles on NT and gets every other outcome right. Both are "2-bit predictors". For the exam: write the state names, which are unambiguous, reproduce the figure you were shown in class, and if a pattern alternates say which machine you use.
Effect on the loop: one miss instead of two
Back to the ten-iteration loop, second run, the entry left in WT by the previous exit (p. 60):
| Execution of the BNE | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|
| State before | WT | ST | ST | ST | ST | ST | ST | ST | ST | ST |
| Prediction | T | T | T | T | T | T | T | T | T | T |
| Branch outcome | T | T | T | T | T | T | T | T | T | NT |
| Result | hit | hit | hit | hit | hit | hit | hit | hit | hit | miss |
| State after | ST | ST | ST | ST | ST | ST | ST | ST | ST | WT |
"Exit NT causes 1 misprediction, but FSM moves from Strongly Taken to Weakly Taken. So the prediction remains Taken" (p. 60). At the next entry the branch is taken, the prediction is Taken, and the state returns to ST. "Only 1 misprediction per loop, improving accuracy to 90% (from 80%)." The weak state absorbed the exit without forgetting the bias.
Before: 1 bit — 80 %
After: 2 bits — 90 %
Why two bits and not four? The studies Hennessy & Patterson report show that 2-bit counters get almost all the benefit of longer ones, and a longer counter is slower to follow a real change of behaviour — the balance between "prediction stability" and "adaptability" of p. 60. A bias of nine to one is as much as a counter can ever learn.
The exam table: 10 June 2025, Question 5
The only official exercise on these pages is a quiz worth 3 points. The loop is the one above with R2 = 20, so R1 takes 4, 8, 12, 16, 20 at the BNE: five executions, outcomes T T T T NT. The twist: a "single-entry 2-bit Branch History Table initialized in the state Strongly Not-Taken" — the loop has never run, and the entry starts as far from Taken as it can. The paper's table has three rows and one column per iteration, with the first column filled in:
| Iteration | 1st | 2nd | 3rd | 4th | 5th |
|---|---|---|---|---|---|
| Prediction State | Strongly Not Taken | Weakly Not Taken | Weakly Taken | Strongly Taken | Strongly Taken |
| Prediction | Not Taken | Not Taken | Taken | Taken | Taken |
| Branch Outcome | Taken | Taken | Taken | Taken | Not Taken |
| (hit or miss) | miss | miss | hit | hit | miss |
Three misses in five executions: a misprediction rate of 3/5 = 60 %, and the state left after the last update is ST → Weakly Taken. Three sanity checks save you from the distractors (60, 90, 99, 100, 80 %): 100 % and 99 % are impossible, because any counter that has seen two Taken in a row predicts the third right; 90 % is not a whole number of misses out of five (read as an accuracy, it is the notes' ten-iteration loop); 80 % would be four misses, and an entry started in SNT already predicts right at the third execution — read as an accuracy, 80 % is 1 miss in 5, the answer of someone who counted the exit and forgot that the two warm-up misses count. In the third column the notes' figure gives Strongly Taken instead of Weakly Taken (WNT → ST on a Taken); the prediction is Taken either way, and so is the rest of the table.
One thing no counter can do, whatever its width: predict a pattern. The exit of a counted loop is perfectly predictable — after nine Taken comes a Not Taken, every time — and so is a branch that alternates T NT T NT; both defeat every counter, because a counter stores a bias, not a sequence. Capturing the sequence needs explicit history: lesson 6.
Where to? The branch target buffer
Suppose the BHT is perfect. In IF the processor knows the BNE will be taken. Where does it fetch from? The target is PC plus the offset encoded in the instruction, and in our pipeline that sum is computed in ID — one cycle too late. The notes' deepening says it in one sentence (p. 63): "even if we can predict that the branch will be taken, we still don't know where to fetch from". The fetch unit must "stall instruction fetch, or fetch sequentially and later flush": one bubble on every taken branch, even when the direction was predicted correctly.
Before: BHT only, target unknown in IF
After: BTB hit in IF
BNE, correctly predicted taken, with and without a BTB. Without one, the fetch unit has nowhere to go until ID has computed the target: the sequential SUBI is fetched and thrown away. With a hit (highlighted) the PTA replaces PC + 4 at the end of C1 and the LD at the top of the loop follows at once.Branch Target Buffer (BTB) — "a specialized cache used to store target address of taken branches" (notes, p. 61): a table indexed by the branch address whose data is the Predicted Target Address, so that fetch can continue from the target in the same cycle. The core idea in one line, also from p. 61: the BHT "predicts whether a branch will be taken", the BTB "predicts where the program should go if the branch is taken".
The structure is that of a direct-mapped cache (p. 61). The branch address is split into a tag and an index; the index selects one entry; the stored tag is compared with the address tag, and only an equal tag is a hit — the tags "ensure the indexed entry really belongs to the current branch". Each entry holds the tag and the PTA, "often combined with T/NT bits from a Branch History Table (1-bit or 2-bit)" (Figure 17 of the notes), so one lookup answers both questions. Only taken branches are stored, and an entry is written when a taken branch resolves and its target is known (p. 64): the first execution of every branch is a cold miss, as in any cache.
The notes summarise the behaviour in their Table 4 (p. 62). The cost column is the one you add yourself, for the course pipeline:
| Prediction | BTB use | Action | Cost if taken | Cost if not taken |
|---|---|---|---|---|
| Predict Not Taken | BTB not used | Fetch from PC + 4 | 1 cycle | 0 |
| Predict Taken (BTB hit) | BTB used | Fetch from the PTA stored in the BTB | 0 | 1 cycle |
| Predict Taken (BTB miss) | BTB miss | Stall or default to PC + 4, then calculate the BTA in ID; allocate the entry | 1 cycle | 0 |
On a hit with a Taken prediction "the next PC is immediately set to the target address, in the same cycle" (p. 64): a correctly predicted taken branch now costs nothing. On a miss "it's as if there's no BTB for that branch at all" (p. 64): fetch defaults to PC + 4, ID computes the real target, a taken branch costs its usual cycle — and the entry is allocated, so the next execution hits. "Clearly, the best option is to have a BTB with a certain rate of misses rather than no BTB at all." The two advantages the notes list (p. 62) are the words for an open question: it "eliminates delay from calculating the branch target address manually" and "enables speculative instruction fetch from correct target, improving pipeline efficiency".
Why the BTB has tags and the BHT has none
Here the "indexed before decode" remark pays off. A BTB hit means "the instruction at this address is a taken branch, and here is where it goes" — and the fetch unit acts on it at once. Without tags, any instruction whose low-order address bits match a stored branch would hit, and the fetch of an ordinary FMUL would be redirected into the middle of a loop: a wrong-path fetch that must be detected and undone. With tags a miss safely means "treat this as not a branch". The BHT can live without tags because its one or two bits are only used once the instruction is known to be a branch, and a wrong bit costs accuracy, never correctness.
The BHT predicts whether and may be wrong; the BTB predicts where and must not redirect a non-branch — so the BTB carries tags.
"The BTB is a direct-mapped cache … tags are used for associative lookup." The notes (p. 61) mix two words. In a direct-mapped structure the index selects one entry and a single tag comparison validates it — what Figures 16 and 17 draw. "Associative lookup" means comparing the address with all stored tags in parallel, a fully associative buffer. Both organisations exist; at the exam write "a cache: index, tag compare, hit or miss" and you are safe either way.
What a BTB is worth, in cycles and in bits
Hennessy & Patterson's textbook example gives the expected penalty per branch when a BTB is present. Call \(p_{hit}\) the hit rate, \(p_{ok}\) the accuracy of the prediction on a hit and \(p_{taken}\) the fraction of taken branches. A branch costs \(P\) cycles in two situations only:
-
A branch costs \(P\) cycles exactly when fetch went the wrong way. With a BTB there are two ways for that to happen; a miss on a not-taken branch is not one of them, because PC + 4 was the right choice anyway.
-
Case A — a hit whose prediction was wrong. Probability \(p_{hit}\,(1 - p_{ok})\), cost \(P\):
\[ p_{hit}\,(1 - p_{ok})\,P \] -
Case B — a miss on a branch that turns out taken: fetch defaulted to PC + 4. Probability \((1 - p_{hit})\,p_{taken}\), cost \(P\):
\[ (1 - p_{hit})\,p_{taken}\,P \] -
Add the two. With the textbook's numbers — 90 % hits, 90 % accuracy on a hit, 60 % of branches taken — and \(P = 1\):
\[ \begin{aligned} \text{penalty} &= p_{hit}\,(1 - p_{ok})\,P \\ &\quad + (1 - p_{hit})\,p_{taken}\,P \end{aligned} \] \[ = 0.9 \times 0.1 + 0.1 \times 0.6 = 0.15 \]cycles per branch. (The textbook's own pipeline resolves branches a stage later, \(P = 2\), and gets 0.30.) Multiply by \(f_b\) for the contribution to the CPI.
And why keep two tables instead of one big BTB with direction bits? Count the bits. With 32-bit addresses and 1024 entries the tag has \(32 - 10 - 2 = 20\) bits, the PTA 30 (word-aligned) and the counter 2: 52 bits per entry, 6.5 KB for the table. A 2-bit BHT with 4096 entries — four times as many branches — costs \(4096 \times 2\) bits = 1 KB. Direction is cheap and tolerates collisions, so it gets a large untagged table; targets are expensive and must not collide, so they get a small tagged one. Hence what the BTB does not do (p. 64): it does not decide the direction, does not compute the target, does not replace the BHT; "it simply remembers previously computed target addresses for quick access during fetch, like a cache for branch targets". And only taken branches, because the "target" of a not-taken branch is PC + 4, which the fetch unit already has.
The puzzle resolved, and the words for the open question
Back to the loop of the hook: always taken 90 %, one bit 80 %, two bits 90 %. The dynamic predictor only ties with the static rule — so what was it for? For every branch whose bias the compiler cannot know: the loop that runs twice in one run and a million times in another, the if that follows the data. There the static rule is a coin toss and the counter learns in two executions — with no delay slots, no profiling run, no recompilation. And with a BTB beside it the nine correctly predicted taken branches cost 0 cycles instead of 1 each. The simplest learner lost to the dumbest rule on the one loop where that rule was already perfect; the second bit and the target buffer are what make learning pay.
The January 2026 paper asked "What are the main benefits to introduce the dynamic branch prediction in a modern microprocessor?", and the June 2026 paper wants "the main concepts and benefits" of "dynamic branch prediction and speculative execution" in five lines. Five lines, each with its why:
- Fewer mispredictions, lower CPI. The predictor shrinks \(1 - a\) in \(\text{CPI} = \text{CPI}_{\text{ideal}} + f_b(1 - a)P\); the penalty \(P\) is untouched.
- Adapts at run time. Input-dependent branches, trip counts and program phases that no compile-time rule can know; "if a branch changes its behavior at runtime, future predictions adjust accordingly" (p. 55).
- Essential in deep and wide pipelines. The work lost per misprediction grows with depth times issue width: in Onur Mutlu's ETH Zürich example (background, not in the notes) a 20-stage, 5-wide machine with a branch every five instructions fetches 500 instructions in 100 cycles at 100 % accuracy, 120 at 99 %, 300 at 90 %, 900 at 60 %.
- Enables speculative execution. Instructions beyond an unresolved branch are fetched, issued and executed, and must not update registers or memory before it resolves — here the flush before WB guarantees it, in a speculative Tomasulo machine the reorder buffer does (lesson 17).
- Independent of compiler and ISA. No delay slots to fill, no profile, no hints; the same binary runs faster on a better core.
The matching five lines for "Explain the main purpose to introduce the Branch Target Buffer" (January 2026, Question 2) are the model answer in the exam section below. Their skeleton: whether versus where; the target is computed in ID; a tagged cache read in IF; the stored target in the same cycle, zero cycles on a hit; filled when a taken branch resolves; PC + 4 and the normal penalty on a miss.
Exam-style questions
Let's consider the Dynamic Branch Prediction techniques used in modern microprocessors. (a) What are the main benefits to introduce the dynamic branch prediction in a modern microprocessor? (b) Explain how works a Branch History Table.
Show model answer
(a) The hardware predicts each branch at run time from its past behaviour, so the pipeline keeps fetching instead of stalling. Benefits: fewer mispredictions and hence a lower CPI (in \(\text{CPI} = \text{CPI}_{\text{ideal}} + f_b (1 - a) P\) the predictor raises the accuracy \(a\), the penalty \(P\) is fixed by the pipeline); adaptation to the actual input data and program phases, which a static compile-time rule cannot see; it is essential in deep and wide pipelines, where every misprediction wastes depth × width instructions; it enables speculative execution past unresolved branches, with results committed only when the branch resolves; it needs no compiler support, delay slots or profiling, so existing binaries benefit.
(b) A Branch History Table is a table indexed by the low-order bits of the branch PC, without tags (so two branches may share an entry: aliasing). Each entry is a small finite-state machine: 1 bit storing the last outcome, or a 2-bit machine with the states Strongly Taken, Weakly Taken, Weakly Not Taken, Strongly Not Taken, predicting Taken in the first two. The table is read in IF with the fetch PC and the prediction decides whether to fetch PC + 4 or the target; when the branch resolves the entry is updated with the outcome. With 2 bits a single anomaly, such as a loop exit, moves a strong state to the weak state of the same direction without changing the prediction, so a loop branch is mispredicted once per execution of the loop instead of twice.
The first two of the five sub-points of Question 2 of the January 2026 paper; the June 2026 paper asks the same in one sub-point of the 8-point question. A complete answer has the mechanism (indexed by the PC, no tags, FSM per entry, read in IF, updated at resolution), the 1-bit vs 2-bit contrast with the loop-exit argument, and benefits stated as cause and effect, not as adjectives. Do not write "reduces the penalty": it reduces the rate.
Explain the main purpose to introduce the Branch Target Buffer.
Show model answer
The branch target address is computed in the ID stage, so even a correct Taken prediction in IF leaves the fetch unit without an address: one bubble on every taken branch. The Branch Target Buffer removes this control hazard. It is a small cache indexed by the branch PC, with tags, whose data is the predicted target address of taken branches (often together with the T/NT prediction bits). On a hit with a Taken prediction the next PC is set to the stored target in the same IF cycle, so a correctly predicted taken branch costs zero cycles. An entry is written when a taken branch resolves and its target is known; on a miss, fetch defaults to PC + 4 and the branch pays the normal penalty if taken. The tags are necessary because a false hit would redirect the fetch of a non-branch instruction — unlike the BHT, which only predicts the direction and can be untagged.
The third sub-point of Question 2 of the January 2026 paper. The examiner looks for "whether versus where", "in the same cycle", "indexed by the PC with tags", "stores taken branches, filled at resolution", and the three cases (predict NT; predict T and hit; predict T and miss). Do not write "eliminates the control hazard" without qualification: it eliminates it on a hit with a correct prediction.
Let's consider the following LOOP to be executed on a processor with a single-entry 2-bit Branch History Table initialized in the state Strongly Not-Taken:
INIT: ADDUI R1, R0, 0
ADDUI R2, R0, 20
LOOP: LD F0, 0(R1)
FADD F2, F0, F0
SD F2, 0(R1)
ADDUI R1, R1, 4
BNE R1, R2, LOOP
After the last iteration, how much is the misprediction rate on the BNE instruction? Motivate your answer by completing the table (rows Prediction State / Prediction / Branch Outcome, one column per iteration; the first column is given: Strongly Not Taken, Not Taken, Taken).
Show model answer
The BNE is executed with R1 = 4, 8, 12, 16, 20: five times, Taken four times and Not Taken at the exit.
| Iteration | 1st | 2nd | 3rd | 4th | 5th |
|---|---|---|---|---|---|
| Prediction State | Strongly Not Taken | Weakly Not Taken | Weakly Taken | Strongly Taken | Strongly Taken |
| Prediction | Not Taken | Not Taken | Taken | Taken | Taken |
| Branch Outcome | Taken | Taken | Taken | Taken | Not Taken |
Mispredictions at the 1st, 2nd and 5th execution: misprediction rate = 3 / 5 = 60 % (Answer 1). With the FSM of the lecture figure the 3rd state is Strongly Taken (WNT → ST on a Taken); the predictions and the rate are the same.
The 10 June 2025 paper, Question 5, worth 1 point for the answer and 1 for the table. Count the executions from the register values, not from the word "iterations", and count the warm-up misses. Write the state names in full, as the paper does.
Same loop and same Branch History Table. After the last iteration, what is the state of the prediction left in the Branch History Table?
Show model answer
Before the 5th execution the state is Strongly Taken (after four Taken). The outcome is Not Taken, so the state moves one step: Strongly Taken → Weakly Taken (Answer 2). The question asks for the state after the last update, one transition beyond the last column of the table.
Second part of the same quiz. The trap is to answer with the state used for the last prediction (Strongly Taken) instead of the state left by it.
Let's consider a processor with a 1-entry 1-bit Branch History Table initialized as Taken, executing the following code (only the BEQ accesses the BHT):
ADDUI R1, R0, 0
ADDUI R2, R0, 100
LOOP: BEQ R1, R2, DONE
ADD R5, R5, R4
ADDUI R1, R1, 1
J LOOP
DONE:
How many mispredictions occur on the BEQ? (State also the number of BHT accesses.)
Show model answer
The BEQ is executed with R1 = 0, 1, …, 100: 101 accesses to the BHT. Outcomes: Not Taken 100 times, then Taken at R1 = 100. The entry starts as Taken: 1st access, predict Taken, outcome Not Taken → misprediction, bit ← NT; accesses 2 to 100 predict Not Taken correctly; 101st access, predict Not Taken, outcome Taken → misprediction. Total: 101 accesses, 2 mispredictions (rate 2/101 ≈ 2 %).
Quiz 5 of the May 2025 midterm as the notes report it (its options paired accesses and mispredictions; "101 and 2" is the right pair). A top-tested loop executes its exit branch N + 1 times; the first miss comes from the initialisation, the second from the exit — both are changes of direction, and a 1-bit entry pays one miss per change.
An inner loop of 8 iterations, closed by a BNE (taken 7 times, then not taken), is executed 3 times by an outer loop. Only the inner BNE accesses a single-entry Branch History Table. (a) With a 1-bit BHT initialized Not Taken, give the number of BHT accesses, the number of mispredictions, the misprediction rate and the final state. (b) Same with a 2-bit BHT initialized Strongly Not Taken. (c) How many mispredictions per execution of the inner loop does each predictor make in steady state?
Show model answer
(a) 3 × 8 = 24 accesses; outcomes T T T T T T T NT, three times. The 1-bit entry mispredicts at access 1 (NT predicted, T), at 8 (exit), at 9 (re-entry: the entry holds NT), at 16, 17 and 24: 6 mispredictions, 6/24 = 25 %, final state Not Taken (the last outcome).
(b) From Strongly Not Taken: access 1 predicts NT (miss, → WNT), access 2 predicts NT (miss, → WT with a saturating counter, → ST with the lecture figure), accesses 3–7 predict T correctly (the state is ST from access 4 at the latest), access 8 predicts T but the branch exits (miss, ST → WT); access 9 predicts T from WT correctly (→ ST), accesses 10–15 hit, 16 misses (→ WT), 17 hits, 18–23 hit, 24 misses (→ WT). Mispredictions at 1, 2, 8, 16, 24: 5, rate 5/24 ≈ 21 %, final state Weakly Taken.
(c) Steady state: 2 per inner-loop execution with 1 bit (exit and re-entry), 1 with 2 bits (exit only). The 2-bit predictor also paid one extra warm-up miss from Strongly Not Taken.
An exercise in the style of the June 2025 quiz with the counting extended over several executions of the loop. The examiner checks the three sources of misses — initialisation, exit, re-entry — and that you know which one the second bit removes. Both 2-bit variants give the same numbers here.
During the execution of a program, the number of mispredictions depends on the initialization and the size of the Branch History Table (BHT). True or False? Motivate your answer.
Show model answer
True. (1) Initialization: the initial state of the entry decides whether the first executions of a branch are predicted correctly — a loop branch whose entry starts Strongly Not Taken costs two warm-up mispredictions, one that starts Weakly Not Taken costs one, one that starts Taken costs none. (2) Size: the BHT is indexed by k low-order bits of the PC without tags, so with 2^k entries all branches sharing those bits share the entry and interfere (aliasing); a larger table spreads the branches over more entries and reduces the interference. (The number of mispredictions also depends on the predictor's FSM, 1-bit or 2-bit, and on the program's branch patterns.)
Quiz 4 of the May 2025 midterm, a True/False with "motivate". The motivation earns the point: name both mechanisms and the word aliasing.
Check yourself
A loop branch is taken 9 times and not taken once, and the loop is executed many times. In steady state, what accuracy does a 1-bit BHT reach on this branch?
A 2-bit entry is in the state Weakly Taken. Which statements are true?
A picture to remember: strong = "I am sure, one surprise will not move me"; weak = "I am still Taken, but one more and I switch".
In \(\text{CPI} = \text{CPI}_{\text{ideal}} + f_b (1 - a) P\), what does replacing a 1-bit BHT by a 2-bit BHT change?
Why does the BTB need tags while the BHT does not?
The BHT predicts Taken, the BTB misses (the fetch unit defaults to PC + 4), and the branch turns out Not Taken. How many cycles are lost in this pipeline?
When does a branch get an entry in the BTB?
Which of these branch behaviours are perfectly predictable in principle, yet defeat every 1-bit or 2-bit counter even after warm-up?
Patterns need history, not wider counters — the subject of the next lesson.
Key take-aways
- Dynamic prediction is hardware that learns each branch's behaviour at run time; it changes how often a branch is mispredicted, never what a misprediction costs — one cycle in this pipeline, set by where the branch resolves.
- The BHT is indexed by k low-order PC bits without tags: two branches with the same bits share an entry (aliasing), which costs accuracy but never correctness.
- A 1-bit entry repeats the last outcome and pays two misses for every change of direction: 80 % on a ten-iteration loop, worse than "always taken".
- A 2-bit entry (ST, WT, WNT, SNT) tolerates one anomaly from a strong state and flips after one from a weak state: one miss per loop, 90 %. The notes' figure is Hennessy & Patterson's machine, not a pure saturating counter; they agree on every loop and differ on alternation.
- The exam table: count the executions of the branch from the register values, start from the given state, count the warm-up misses, and report the state after the last update — 60 % and Weakly Taken in the June 2025 quiz.
- The BTB is a tagged cache indexed by the branch PC that stores the predicted target of taken branches and supplies it in IF, so a correctly predicted taken branch costs zero cycles; it carries tags because a false hit would redirect the fetch of a non-branch.
What to watch and read
-
How Branch Prediction Works in CPUs
Computerphile, Matt Godbolt26 min
The whole idea in one sitting, with drawings: why the pipeline must guess, from "always guess the same" to counters. The intuition this lesson builds on.
-
2 Bit Predictor
Georgia Tech HPCA (Udacity)6 min
The four-state counter on a whiteboard and why it beats one bit on loops — watch it after the FSM clicker, before the exam table.
-
BTB: Branch Target Buffer
Georgia Tech HPCA (Udacity)2 min
Two minutes on why the direction is not enough: the target must be predicted too. Pairs with the BTB lookup widget.
-
One-Two Bit Branch Prediction simulation
Virtual Labs, IIIT Hyderabad15 min
Paste a small assembly program, generate its branch trace and run a 1-bit or 2-bit predictor on it: check a hand-made exam table against the tool.
-
A Study of Branch Prediction Strategies
James E. Smith, ISCA 19819 pages
The paper that started dynamic prediction: the 1-bit-versus-2-bit story in the author's own words, with accuracies that swing from 35 % to 98 % between programs.