Is there a canonical way to ensure a value will be in a specific register prior to a call? I’d like the intervening code to be able to reuse the register, so I’d like to avoid reserving it. The value is valid for the lifetime of the frame, but can likely be recomputed efficiently. Since the value isn’t needed except at call sites, I’d like to ensure that the register allocator, and any other optimizations can leverage this information.
As an example, assume on X86 that I’d like to use
R11 as part of this protocol, but I’d still like to use it as a free register between calls. Which register it is, doesn’t matter, and I picked
R11 rather arbitrarily since its a scratch register, but in practice it may actually end up being a callee saved reg (still TBD). I’d also like to do this for targets other than X86, so I’m after a general method rather than any specific advice regarding X86.
In the snippet below, the prologue executes normally, but we additionally use
R11 before computing its new value in the callee. After the callee returns,
R11 can be freely used again. Ideally the optimizer would decide if it should be loaded, spilled, or recomputed prior to the call to
BB2. The callee
foo() may or may not participate in the protocol, but either way, we’d like
R11 to hold the correct value at the call site.
prologue: // Handle Callee saved regs, etc. // use passed in R11 // compute new R11 value for current frame // ... R11 can be used as a free register until the next CALL instruction BB2: // Marshall arguments (omitted) // Rematerialize R11 for callee (may be recomputed, reloaded, or copied) // Call foo(...) // R11 is free again ...
I’m pretty sure there are many approaches that would work here, but this seems like a common enough task that I figured it would be best to just ask before running off and experimenting.
I did spend some time digging through
Target but I haven’t found anything obvious yet. Most of my experience has been doing analysis and transforms on LLVM IR rather than modifying the backend, so I’m not familiar w/ many of the codegen and target specific transforms.
Any pointers here are very much appreciated.