bjorn3 opened issue #9343:
If I have a call whose call arguments were previously spilled to the stack, the fill instructions get the source location of the instruction right before the call rather than the source location of the call itself despite the fill instructions being part of the call sequence.
cfallin commented on issue #9343:
Unfortunately there's no way for Cranelift to know what regalloc-inserted moves/spills/reloads are "for"; even at the RA2 level, we have an abstraction of liveranges, and we know that the liverange moves from here to there, but we don't know that it's because it was forced by the next instruction, or an instruction much later, or actually this is a spill and the old location was forced by something else.
In other words, the fill instructions are not for the call; in simple cases a human may be able to look at the code and say "of course they're caused by the call", but in more complex cases that is lost behind the abstraction. In a very real sense, the fills are not part of the call sequence; they are part of the regalloc's data movement, and the regalloc just happened to do its movement here or there.
A few examples where attribution is not simple:
- if the call is inside a loop, RA2 might hoist a liverange split outside of the loop, so the "fill" that is definitely caused by the call happens before we enter the loop. Should that be attributed to the call as well?
- if there are multiple calls that all use a value, it might be pulled back into a register by the first, but used by all of them. Is that attached to the first call or all?
- if RA2 needed a register free for some period of time, it may spill then reload (e.g. to get a temp for a blockparam shuffle). Say that value then flows into a call. Is the reload "for" the call or is it part of the spill-reload sequence that moves it out of the way?
(The point with all of these is that data movement happens, and calls may be one source of constraints on that data movement, but it's far more complex than one call -> one set of reloads)
The simple solution we arrived at for debug sourcelocs is to attribute every regalloc-inserted move/spill/reload to the previous instruction's sourceloc, which is about as good as one can do when spills/reloads are not actually attached to a cause.
It would be useful to know more about your context: are you hoping for this in order to try to work out why spills/reloads occur? Or are you trying to find the code-size cost of callsites? Or something else?
Last updated: Dec 23 2024 at 12:05 UTC