Register deprivation: spills and runtime under forced register scarcity
We compiled nine small kernels while progressively reserving registers with gcc -ffixed-<reg> , then measured spills and runtime on one machine. Reserving registers reliably increases spills, but the static spill count is a weak predictor of the runtime cost, and one kernel gains 23 spills with no slowdown at all.
Code is at https://github.com/rjpower/spillbench; the numbers behind every figure below are in results.json .
TL;DR
Removing registers slows 8 of 9 kernels by 14–76% at the tightest budget; the ninth (SipHash) does not move. Results are bit-identical at every budget, so the reservation only changes generated code, not the computation.
Added spill instructions correlate weakly with slowdown (Pearson r = 0.55 over 105 points). The cost of one added spill ranges from about 0%/spill (SipHash) to 2.2%/spill (FIR filter), a ~30× spread.
The effect is specific to the register file the kernel uses. Reserving XMM registers on SHA-256 costs +5.6%; reserving GP registers costs +33%. Reserving GP registers on a double-precision matmul is flat; reserving XMM costs +34%.
GCC auto-vectorizes part of SHA-256 with SSE at -O2 , so reserving XMM is not inert for that integer kernel: its stack-spill count rises 8→65 while runtime moves +5.6%.
, so reserving XMM is not inert for that integer kernel: its stack-spill count rises 8→65 while runtime moves +5.6%. Measured with gcc 15.2.0 -O2 on an Intel Xeon E-2236, wall-clock, minimum of 15 repetitions on one pinned core.
Setup
... continue reading