[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