Why Compiler Spills Do Not Always Slow Down Your Code
Register deprivation: spills and runtime under forced register scarcity

I compiled nine small kernels while progressively reserving registers to simulate scarcity. While removing registers reliably increases spills, the static spill count is a weak predictor of runtime cost. Surprisingly, one kernel gained twenty-three spills with no slowdown at all, proving that the location of a spill matters more than the total count.
The cost of one added spill ranges from about 0% per spill to 2.2% per spill, a thirty-fold spread.
- nyrikki
IMHO this may be because with hyper-restrictive calling convention or register budgets, the compiler typically resorts to writing explicit MOV or stack PUSH/POP instructions to free up space.
Because modern CPUs have hundreds of hidden physical registers, the CPU's Register Renaming unit looks at those forced stack move instructions, realizes they are just recycling the same local variables, and maps them to hidden hardware registers anyway. The CPU essentially executes the "stack spills" at the hardware register level, rendering the compiler's bad register constraints almost completely harmless.
Particularly the siphash result makes me think this is what is happening.
Unfortunately I don’t think there is a way to observe this as a consumer.
- Scene_Cast2
I wonder how much effect the CPU's register remapping has on these results. Also, they ran it on an ancient CPU, but I'm not sure how much that matters.
- derdi
This is pretty meaningless without showing any assembly code. What does the inner loop for siphash look like? How many GPRs does it use? Where are the spills placed? What does perf say about any of this?