2026-05-23
Register renaming gives the CPU a pool of physical registers far larger than the architectural register set — say 224 physical registers backing 16 logical x86-64 GPRs on a modern Intel core. But that pool is only useful if the CPU knows, at every cycle, which physical registers are free to hand out and which are still holding live data. That bookkeeping lives in two structures: the free list and the active list (sometimes called the busy table).
The free list is a queue of physical register numbers that nobody currently owns. When the allocator renames a new destination, it pops a number off the free list and writes it into the rename map. When an instruction retires and its previous mapping is overwritten by a later instruction that has also retired, that older physical register goes back onto the free list. The key insight: a register isn't freed when its consumer reads it — it's freed when a newer write to the same logical register commits, because only then can no future instruction possibly need the old value.
The active list (or "busy bit vector") is a 1-bit-per-physical-register array tracking whether a register's value has been produced yet. Writeback sets the bit; the wakeup logic reads it to know an operand is ready. A separate in-flight list records, in program order, which physical register each in-flight instruction allocated — this is what retirement walks to reclaim registers and to roll back on misprediction.
Concrete example: On Intel Sunny Cove, the integer PRF is 280 entries. With a 352-entry ROB, the free list must sustain allocation of up to 5 destinations per cycle and reclamation of up to 8 retiring instructions per cycle. If the free list empties, allocation stalls — every dispatch slot wastes a cycle even if the ROB and scheduler have room. Performance counter RESOURCE_STALLS.RS or ...PRF tells you when this happens.
Rule of thumb: physical_registers ≈ logical_registers + ROB_size × (average destinations per µop). For x86-64 with ~0.7 dest/µop and a 352 ROB: 16 + 352×0.7 ≈ 262. Intel ships 280 — comfortable margin. If you ship fewer, the free list throttles you long before the ROB fills.
On branch misprediction, recovery walks the in-flight list backward, returning each speculatively-allocated physical register to the free list and restoring the rename map from a checkpoint. Fast recovery requires the free list to accept bulk returns in one cycle — usually implemented as a circular buffer with separate head/tail pointers for committed vs. speculative state.
