[llvm-dev] Finding scratch register after function call
Michael Stellmann via llvm-dev
llvm-dev at lists.llvm.org
Sat Jul 21 12:14:40 PDT 2018
For a Z80 backend, "eliminateCallFramePseudoInstr()" shall adjust the
stack pointer in three possible ways, e.g. after a function call,
depending on the amount (= adjustment size) *and some other rules*:
1. via one or more target "pop <reg>" instructions (SP increments +2 per
instruction), using an unused reg (disregarding the contents after the
operation), followed by an optional +1 increment on the SP for odd
amounds (SP can be inc/dec'd by 1 directly).
2. incrementing the SP register directly with a special target operation
(increments +1 per operation), without using any other register.
Requires twice as much instructions as "pop" in sequence, though.
3. via a long sequence of target-specific arithmetic instructions that
involves a scratch reg (which would have to be saved before and restored
after the call). This should only be used for larger sizes of call frame
index.
Option 1 ("pop"s) is by far preferred for small call frame sizes.
However, this requires finding a suitable register. And this is where it
gets complicated:
"Suitable" for option 1 means that it shall be any of the 4 physical
registers AF, HL, DE, BC. When invoked after a function call to do
caller-cleans-stack, none of the register(s) used for return value of
the function call shall be used. The calling convention uses
- one specific pysical 8 bit register (lower 8 bits of AF) for 8 bit
return values
- one specific physical 16 bit register (reg HL) for 16 bit
- two 16 bit regs (regs HL + DE) for 32 bits return value
When determining if one of those registers is available for the option 1
way of cleaning-up the stack after a function call, reverse-order
priority is preferred: BC, DE, HL, AF - due to the highly asymmetric
command set of the Z80, the "least otherwise usable" register should be
used for that operation, starting with "BC".
Now my questions are:
A) Is there a way to check if any of those registers are free at that
point (in eliminateCallFramePseudoInstr()) - i.e. not used as return or
to hold other values?
B) If it could be determined that none of the registers are free, option
2 (adjusting the SP by a series of +1) should be used for small amounts
of call frame size, option 1 with the forced register "BC" for "pop" for
mid amounts, and option 3 for larger amounts.
Now if register "BC" is forced to be used to clean the stack up after a
function call, it should be saved (via "push") on the stack before the
function is called, or to be specific, even *before* the first function
parameter for the upcoming function call is pushed to the stack. And
restored after call frame cleanup (after tha last
call-frame-elimination-"pop") - by another "pop", restoring the original
value.
Would "createVirtualRegister" with a register class containing only that
register do exactly that?
Or is there a better way to do this?
Thanks,
Michael
More information about the llvm-dev
mailing list