Expand description
How much of the frame the register allocator had to use, function by function.
Design: spec/safe-memory/13-performance.md section 13.1, whose table of metrics has a row for
spill and fill counts, and section 13.2.1, which says why: a capability in flight is four words
in registers, and if materializing one pushes something else onto the stack in a hot loop then
no amount of check elimination saves us and the representation is what has to change. Milestone
S4 in spec/safe-memory/16-milestones.md asks for the delta on the pointer heavy benchmarks,
and cargo xtask pressure is what reads these numbers back.
§What is counted
Three numbers per function. The slots are how many values the allocator could not keep in a register at all, which is what the frame grows by. The stores are how many times one of them is written to its slot and the reloads are how many times one is read back, which is what the program pays at run time and is not the same number: a value spilled once and read in a loop costs one store and as many reloads as the loop has instructions that want it.
A move from one slot to another counts as both, because it is both. That happens on an edge carrying a spilled value into a parameter that was itself spilled, and no machine here has an instruction for it, so it goes through a scratch register and really is a load and a store.
§What the numbers are not
Not a claim about the best allocator we could have. There is one allocator in this compiler and
it is the single pass one spec/10-backend.md section 10.4 describes, so a function that spills
here might not spill under the backtracking allocator M4 brings. What the delta between two
builds of the same program says is how much more pressure the instrumented one puts on whatever
allocator is reading it, and that comparison is fair as long as both sides go through the same
one.