5.3.4 · D5Advanced Microarchitecture

Question bank — Register renaming

2,085 words9 min readBack to topic

This page is a misconception hunter. Every item below targets a place where students think they understand Register renaming but hold a subtly wrong picture. Read the prompt, say your answer out loud with a reason, then reveal. If your justification is different from the given one — even if your yes/no matches — you found a gap worth closing.

Before we start, four words we lean on constantly, restated in plain English so nothing is assumed:

  • Architectural register — a name the programmer/compiler writes (like R1). It is a label, not a storage box.
  • Physical register — an actual storage box in hardware (like P0). This is where a number really lives.
  • RAT (Register Alias Table) — the little lookup table that says "right now, the label R1 means box P2." Renaming is nothing more than editing this table as instructions decode.
  • ROB (Reorder Buffer) — a queue that remembers every instruction still "in flight" (decoded but not yet finalized), in program order. It stores each instruction's old register mapping so it can undo mistakes and finalize ("commit") results in the right order. Full detail lives in Reorder Buffer (ROB).

A picture of the three bookkeepers

Everything on this page comes down to three little structures passing physical boxes around. The figure below shows their jobs and how a box moves between them — glance at it before answering, and return to it whenever an item mentions the RAT, the free list, or the ROB.

Notice the arrows of ownership: a box leaves the free list when a destination is allocated (orange), the RAT points to it while it is the current value of a label (blue), the ROB holds the previous box until commit, and at commit the old box is pushed back to the free list (green). Every physical box is always in exactly one of these homes.

The R1 → P0 → P2 story, step by step

The single example the parent note keeps returning to is three instructions that all write R1. Watch which box the label R1 points to as we decode them — this one figure is the intuition behind half the reveals below.

The punchline: R1 the label is one thing, but over three instructions it means three different physical boxes (P10 → P0 → P2). The reader that needed the old R1 (the MUL) keeps reading P0; the later writer scribbles into P2. Different boxes, zero conflict — that is the whole trick.

When each thing happens

Several "ordering trap" items depend on when in an instruction's life the source-read, the rename, the execute, and the commit occur. The timeline below fixes that order once so you can reason about the traps.

Read it left to right: sources are read from the RAT and the destination renamed at decode (in program order), execution may happen out of order and much later, but the free of the old box waits all the way until commit (back in program order). Keep this strip in mind for every edge case.


True or false — justify

Register renaming removes RAW (true) dependencies too.
False. Renaming only kills the false ones (WAR and WAW) by giving each writer its own box; a RAW is a genuine data need, so the consumer must still wait for the producer's value.
If two instructions write the same architectural register, one of the writes is wasted work the hardware could skip.
False. Both writes execute (they may produce values that intermediate readers need); renaming just routes them to different physical boxes so they don't block each other.
After renaming, the WAR hazard on R1 between MUL R4,R1,R5 and ADD R1,R6,R7 still physically exists, we just hide it.
False. It genuinely ceases to exist: the MUL reads box P0 and the ADD writes a brand-new box P2 (see figure s02). Two distinct boxes cannot conflict — there is nothing left to hide.
The RAT stores the values of registers.
False. The RAT stores mappings (label → box number), not data. The values themselves live in the physical register file; the RAT is just an index into it.
A physical register can be freed the instant the instruction that wrote it finishes executing.
False. It is freed only when the next writer of the same architectural register commits — until then, an exception could force us to restore the old mapping, so the old box must survive (timeline s03).
Renaming requires out-of-order execution to be useful.
Mostly true in spirit: renaming exists to feed Out-of-Order Execution more independent work. In a strictly in-order pipeline the false dependencies rarely stall you anyway, so renaming buys little.
With enough architectural registers, a smart compiler makes renaming unnecessary.
False. The compiler allocates statically and can't foresee runtime ordering, loop unrolling depth, or interrupts; more architectural registers also break binary compatibility and bloat encoding. Hardware renaming solves it transparently.
Every physical register is, at any instant, in exactly one of: the free list, mapped by the RAT, or held as an old mapping in the ROB.
True. The free list holds available boxes; the RAT points at each label's current box; the ROB holds superseded boxes waiting to be freed at commit. There is no fourth home — this is exactly the three-home picture in figure s01.
Renaming changes the results a program computes.
False. It only changes where intermediate values are stored and when instructions may run. The committed architectural state — the numbers the program sees — is identical to a serial run.

Spot the error

"We read the sources from the free list to find their current values."
Error: sources are read from the RAT, not the free list. The RAT tells you which box currently holds each source; the free list only supplies a fresh empty box for the destination (figure s01).
"At commit we push the new physical register back to the free list."
Error: we push the old box (the one this architectural register used to map to). The new box holds the just-committed value and stays live until a future writer supersedes it.
"Because P0 and P2 are different boxes, I2 (which reads P0) and I3 (which writes P2) have a RAW dependency."
Error: there is no dependency between them at all. Different boxes, different roles — that independence is exactly the WAR hazard renaming removed (figure s02).
"We allocate the destination box before reading the sources, so the destination is fresh."
Error/ordering trap: read sources from the RAT first, then allocate + update the RAT (see the decode step in s03). If a source is the destination (R1 = R1 + R2), reading after updating would grab the wrong box.
"The minimum physical register count is just the ROB size."
Error: the minimum is . You need one box per architectural register for committed state plus one per in-flight instruction that has claimed a destination.
"Register pressure means the physical register file is physically overheating."
Error: register pressure is a scheduling stall — decode halts because the free list is empty (all boxes in use), nothing to do with temperature.
"Renaming eliminates hazards, so the Reorder Buffer (ROB) is no longer needed for precise exceptions."
Error: the ROB is still essential. It records the old mappings for recovery and enforces in-order commit so exceptions look precise — renaming feeds the ROB, it doesn't replace it.

Why questions

Why do we record the old mapping in the ROB rather than just overwriting the RAT and forgetting it?
Because an exception or branch mispredict may require us to roll the RAT back. The saved old box lets us restore "R1 meant P0" and reclaim the now-defunct P2.
Why can't we free the old physical register at execute-time instead of commit-time?
Instructions execute out of order, but architectural state must be precise. Until the overwriting instruction commits, an earlier exception could make the old value the correct architectural state again — so we keep the old box (timeline s03).
Why does WAW block execution without renaming, even though only the last write "matters"?
Without renaming both writes target one box, so hardware must serialize them to guarantee the last write in program order wins. With separate boxes, the ordering is enforced only at commit, freeing them to compute in parallel.
Why is the RAT read and written for a single instruction?
Read: to find where the sources currently live. Write: to publish the destination's new box so later instructions reading that architectural register pick up this result instead of the stale one.
Why do physical register counts tend to be powers of two (e.g. 256)?
The register index is a binary field in every internal tag; a power of two uses all bit patterns and keeps indexing/decoding hardware simple and dense.
Why does renaming help Superscalar Execution specifically?
A superscalar core decodes several instructions per cycle and needs many independent ready operations to fill its wide back-end. Killing false dependencies exposes exactly that extra Instruction-Level Parallelism (ILP).

Edge cases

Instruction R1 = R1 + R1 — same register as both sources and destination. What happens?
Both source reads return the same current box (say P5), then a fresh box P8 is allocated and the RAT set to R1→P8. Reading sources before updating is what keeps this correct.
The free list is empty when a new instruction wants a destination box.
Decode stalls (register pressure). No mapping can be made without a free box, so the front end waits until a committing instruction returns one to the list.
A register is written but never read again before the program ends.
It still gets a physical box and is renamed normally; its box is simply freed when a later writer of that architectural register commits (or reclaimed at pipeline drain). Renaming doesn't detect "unused" results.
An instruction is renamed but then a branch mispredict kills it before commit.
On recovery the RAT is rolled back to the state before the wrong-path instructions, and their allocated boxes are returned to the free list — as if they never claimed anything. See Branch Prediction.
A load and store to the same memory address — does renaming resolve their ordering?
No. Renaming only tracks register names. Memory ordering is a separate problem handled by Memory Disambiguation; renaming is blind to which addresses a load/store touch.
Two independent instructions both write different architectural registers — is any renaming interaction needed?
None. They pull separate boxes from the free list and update separate RAT entries; there was never a false dependency to remove, so renaming just proceeds independently for each.
An instruction reads an architectural register that no earlier in-flight instruction has written.
The RAT still returns a valid box — the one holding that register's last committed value. Every architectural register always maps to some live box, so a read is never undefined.
Recall Fast self-test

The single most-missed idea on this page ::: ==Old boxes are freed at commit, not at execute==, because precise exceptions may still need the old value (timeline s03). The second most-missed idea ::: Sources are read from the RAT and destinations pulled from the free list — two different structures with two different jobs (figure s01).

Related deep material: Tomasulo's Algorithm (renaming via reservation stations), Scoreboarding (an earlier scheme that stalls on false hazards instead of renaming them away), and the parent Register renaming.