Expand description
How often each block runs, carried from the IR down to the machine IR.
Design: spec/optimizer/38-scheduling-and-layout.md sections 38.4 and 38.6, and
tamnd/rucc#364, which is the observation that a branch weight is worked out and then thrown
away because nothing downstream could read one.
rucc_opt::Frequencies answers, for an IR function, how often every block runs next to the
once the function is entered, and how likely each arm of each branch is to be the one taken.
Every one of its consumers so far has been a pass in the middle end, and the consumer this is
for is crate::layout, which is at the far end of selection, allocation and the prologue.
None of those could work the numbers out for itself: by then a loop is a backward branch and
the loop forest the frequency was summed over is gone.
So the numbers are copied onto the blocks and the arms as soon as there are blocks and arms to
copy them onto, which is the moment selection finishes. mir::Weight is the same scale the
frequency is in, so the copy is a copy.
§Why it is a pass over what selection left rather than part of selection
Selection makes one machine block per IR block, in the same order, with the arms in the same
order, and says so by handing back crate::lower::Lowered::blocks. That correspondence is
the whole of what this needs, and it is a fact worth spending rather than a reason to thread a
second table of numbers through four thousand lines of instruction selection.
§What is not carried
Nothing keeps a weight in step with the graph after this. A pass that makes a block says how
often it runs if it knows, and crate::split::critical does, and everything else leaves the
new block running as often as the function does. That is a heuristic going slightly stale, not
a fact going wrong, and mir::Weight says so where it is defined.
Functions§
- carry
- Writes onto a machine function how often each of its blocks runs and each of its arms is taken, worked out from the IR function it was selected from.