[LLVMdev] Representing a safepoint as an instruction in the x86 backend?

Philip Reames listmail at philipreames.com
Tue Feb 25 17:32:21 PST 2014


I've got a pseudo instruction with some tricky semantics I need help 
figuring out how to encode properly.  For those interested, this is to 
support fully relocating garbage collection.  I'm going to try to 
express the requirements clearly so that you don't need to understand 
the use case in detail.

My end goal is to capture a list of registers and/or stack offsets for a 
list of virtual registers (known explicitly inside SelectionDAGBuilder) 
at the PC following a call instruction.  In particular, I need to be 
able to update all physical copies of these virtual registers.  I've 
decided to approach this by introducing a new psuedo instruction with 
these semantics, but if anyone has an alternate approach they'd 
recommend, I'm open to that too.

Here's the semantics of my 'instruction':
- It must immediately follow a call instruction, before any return value 
copies, or frame manipulation.  Not every call has a following safepoint.
- It has a variable number of arguments (virtual registers).  All can be 
both read and written.
- It can handle any combination of stack locations and registers. 
Ideally, it should not effect register allocation.

The approach I've taken to date is based in part on the work done for 
PATCHPOINT.  Here's what I've done:
- Introduced a SAFEPOINT psuedo instruction
- Reverse engineered the CALLSEQ_* series of nodes to insert my node 
after the CALL node in both glue and chain sequences.  (BTW, is there 
any documentation on the call sequence?  I think I've reverse engineered 
it correctly, but I'm not completely sure.)
- Introduced folding logic in foldMemoryOperand (analogous to 
PATCHPOINT, but which marks both load and store) -- this is where my 
problem currently lies
- Inserted code during MCInstLower to record the statepoint

The problem with this is that a reload from a stack slot will sometimes 
be inserted between the CALL and the SAFEPOINT.  This is problematic 
since we are no longer recording the list of locations at the site of 
the call itself.  If the recorded information is used during the 
lifetime of the subroutine call, the wrong locations would be updated.  
That would be "bad".

The reason for this is that the folding logic only applies if there's a 
single use of the physical register.  If there's more than one use, it's 
assumed to be cheaper to reload than to perform two folded operations 
against memory.  (I don't know if this is true always, but more 
importantly for me, it breaks my intended semantics.)

Does anyone know of a way to avoid the fold step to begin with?  I'd 
really like the register allocation to not give preference to register 
uses for this instruction.  If a virtual register is already in the 
stack, it shouldn't attempt to reload before this instruction. I haven't 
been able to find the appropriate hook for this.

I can go ahead and hack the folding code to unconditionally fold into 
SAFEPOINTs and move the load after the SAFEPOINT, but that feels like an 
utter hack.  Before going down the road, does anyone have a better 
suggestion?

I'm very open to suggestions here.  If I'm taking the wrong approach or 
something sounds like it doesn't work the way I've described, please 
point it out.  I will freely admit this is my first serious endeavour 
into the x86 backend and that I'm learning as I go.

Philip

Note: For the moment, this is all x86 specific.  Most of it could be 
made architecture independent without too much effort.



More information about the llvm-dev mailing list