# What are the disadvantages of having many registers?

IA-64 is an architecture that has 128 general purpose registers, are there any disadvantages (beside being more expensive and larger instruction size) to having many registers?

• For a 'worse' example, AMD29K had 256 registers. The 32bits wide intructions had up to 3 8bits fields for addressing registers. – TEMLIB Dec 30 '14 at 18:47

Expensive context switch, save and restore all these registers. Some works (more info on William Stallings book) points that with compiler optimization theres almost no improvement when processor has more than 64 registers.

• The utility of a large number of architected registers is workload-dependent (targeting certain HPC workloads can justify large architected register sets as the SPARC64 VIIIfx) and dependent on architectural and microarchitectural aspects (Itanium used registers to support static speculation and required single-step execution to behave the same as parallel execution [so old register values die as soon as a writer to that register begins execution rather than when the operation completes; a swap, e.g., requires 3 operations and a temporary register where a traditional VLIW uses 2 move ops]). – Paul A. Clayton Dec 30 '14 at 16:47

The disadvantage is higher latency per instruction. Either you need to run the processor clock slower or you need to pipeline the register file, so each instruction will take more cycles. (Pipelining the register file is difficult, and rarely done.) A register file is a physical thing, thus must obey the laws of physics. (In particular, that our universe has only three spatial dimensions, and that the speed of light is a constant.) Suppose your register file is 2 dimensional (as all are today). Then the register bits are typically arranged in a rectangle with width $b$ (where $b$ is the number of bits stored in each register) and height $N$ (where $N$ is the number of registers.) (This assumes that the circuit to implement the bit is approximately square.)

Here's a picture of a 3-ported 4x4 register file that I found at http://gyan.fragnel.edu.in/~surve/COA/ISA/Images/Figure4.37.jpg:

Each time you read a register you need to propagate a read-enable signal to each bit of that register across the width of the array. If the read-enable wires are buffered then the delay to propagate a signal down the wire is proportional to the length of the wire. (Neither the horizontal nor vertical wires in this diagram are buffered. Buffering the vertical wires is actually hard, because that's a many-to-1 bus, not a 1-to-many point-to-point signal, so you may not be able to do that at all. In the case that you can't buffer a wire, the wire will have a delay proportional to something like the square of the length of the wire.)

So at best a register file access is going to take time proportional to $O(b+N)$. (That doesn't count the time for the decoder, and assumes that you somehow figure out how to buffer all the wires.)

To sum up: the more bits you are storing, the slower the storage.

• Would banking the register file (which might be desired for increasing access bandwidth) make pipelining access slightly easier? I also wonder if width pipelining would help (by allowing the 'b' dimension to shrink for a given physical array) both for simplifying the pipelining of register file access (if the aspect ratio of the memory cells was biased to make the 'b' dimension larger, a 32-bit wide 64-entry array might have comparable delay in both directions and lower than 64x64 array) and for reducing latency in the common case where half of the data is more time critical. – Paul A. Clayton Dec 30 '14 at 17:00

As noted in the question, increasing the number of registers tends to increase instruction size (clustering, functional specialization, windowing, and other features can reduce the encoding overhead of a larger number of registers) and the area used by the core.

As Wandering Logic's answer notes, a larger register file will have higher access latency. Increasing cycle time to avoid pipelining register file access has obvious performance implications. Pipelining register file access complicates the design of the register file and the forwarding network (results from more cycles will be sourced from the forwarding network rather than the register file). (The Alpha 21464 was designed with three cycle register file access latency and register caching to simplify forwarding. "Design of an 8-wide Superscalar RISC Microprocessor with Simultaneous Multithreading", Ronald P. Preston et al.: IEEE reference.) Pipelining introduces inefficiencies as well with latch overhead, clock skew, stage imbalance, etc. Process variation may also discourage longer pipelines because the timing for a given core is constrained by the pipeline stage with the longest delay.

(Width pipelining, where part of a value is available earlier, can also reduce the latency for some uses that do not require the full value at the start of execution. A width-pipelined (a.k.a. staggered) ALU (which can provide bitwise logical operations, addition/subtraction, and left shift) could tolerate extra latency for the more significant bits of a value. Similarly, address generation for a load could provide cache index and enough virtual address tag bits for a decent way prediction with only 24 bits available initially. Obviously this technique could be applied to a smaller register file, but the benefit of a faster clock has diminishing returns.)

Access energy is also increased. Power delivery and thermal dissipation are significant design issues in modern high performance processors.

If a register alias table is used to support register renaming under out-of-order execution, the access cost of such is also increased like the register file and the size of each entry will be larger because renaming increases the number of registers.

For in-order execution the cost of determining result availability and selecting a result is also increased because the number of bits in a name is increased. (This effect is present for out-of-order execution as well. With only 32 architected registers, supporting 32 uncommitted results only requires 64 names, so source readiness only involves 6-bit compares; with 128 architected registers, more than 7 bits would be needed to name a register. This can be avoided by only checking for pending result names, but such introduces some complexity.)

Checkpointing register state for speculation recovery also becomes more expensive. Checkpointing would apply to some (not yet implemented) out-of-order execution designs and some forms of supporting transactional memory.

If each context is required to be full-sized, a larger register set makes multithreading more expensive. (For highly ported register files, additional register sets can be provided at lower cost under the restriction that different sets cannot be accessed at the same time. This three dimensional register file technique was developed for SPARC's register windows and used for Itanium's switch-on-event multithreading.)

As robot_s's answer notes, the cost of context switches increases. The cost of function call save/restore depends on the call interface. Itanium provided stacked integer registers rather than a generic function call interface, so there were not fixed registers to be saved and, in theory, save and restore could be handled asynchronously and involve a separate storage area (avoiding data cache thrashing). Whole-program optimization could also avoid some register save and restore that would be required from a static function interface.

Multicycle register file access also increases the number of cycles between when a fetch address is used (speculatively) and when it is confirmed or corrected (i.e., the branch misprediction penalty increases).

With a "flat" register set, software would tend to assume all registers have equal access cost and are fully paid-for (i.e., "free"). This makes some hardware optimizations more difficult;. Clustering, windowing, hierarchical capacity, exposed banking and other architectural features can reduce the impact of larger context storage (but make software optimization more complex and constrain hardware implementations).

The benefit of having a large number of registers depends on the workload and the latency and parallelism of the hardware. Fujitsu's SPARC64 VIIIfx provided more registers than Itanium, but specifically targeted high performance computing.

Itanium was designed under the assumption of static scheduling and high instruction level parallelism with support for single-stepping (so a register name cannot be used under the shadow of execution latency). High ILP means many results per cycle, and results would "occupy" the register for the entire execution latency in addition to any use lifetime. Static scheduling (especially with predication to increase the size of extended basic blocks) tends to increase the number of architectural registers used in order to cover latency and provide parallelism. Itanium also supported "prefetch" of values into registers, where the value would be reloaded if there was a store to the address of the load before the value is used; this would naturally increase register pressure (the register name is taken from the moment the load instruction issues just as with other instructions, so a load advanced ten cycles before use effectively wastes that register name for ten cycles).