[llvm-dev] Spilling to register for a given register class

Quentin Colombet via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 18 12:02:58 PST 2019


Hi Hendrik,

This question is a recurring one. Check for instance https://lists.llvm.org/pipermail/llvm-dev/2016-February/095436.html <https://lists.llvm.org/pipermail/llvm-dev/2016-February/095457.html> for a related conversation.

What this conservation boils down to is that you can achieve that by providing a larger register class that contains the union of the registers that are used with where they can be spilled.

For instance, let say you have a register class GPR that can be spilled into SPR.
You would create three register classes: GPR, SPR and GPR_union_SPR. GPR_union_SPR is never explicitly used in any real instruction (i.e., it does not appear in any MC description), but will give a way to regalloc to relax the constraints on available registers when doing live-range splitting.

Let say you have the following code:
V1(gpr) = op
… // <— too high gpr pressure
= op V1(gpr)

What RA will do is first split the live range of V1:
V1(gpr) = op
V2 = copy V1
… // <— too high gpr pressure
V3(gpr) = copy V2
= op V3(gpr)

Now, V2 does not need to be constrained on gpr anymore and will end up using GPR_union_SPR. So effectively, if there is no GPR available for V2, an SPR will be used and thus V1 will be “spilled” to a GPR.

Disclaimer: The live-range splitting may act up and it may not be as straight forward to apply this solution but the idea remains valid.
 
AMDGPU does something a bit different IIRC, it basically runs the allocator several times:
- First they allocate GPRs and spill them into SPR, since SPR registers are not taken into account during this iteration there is no issue for creating new live ranges during spilling for these ones
- Second they allocate SPRs and they get spilled to memory.

Cheers,
-Quentin

> On Dec 17, 2019, at 1:47 PM, Hendrik Greving via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 
> Hello, for an architecture that doesn't have a good way to load/store a given register class to memory, is it instead easy to spill/fill from another register class instead?
> e.g.
> - storeRegToStack/loadRegFromStack use a pseudo instruction and add virtual register operand is not supported (spill optimization doesn't seem to like this).
> - AMDGPU backend seems to do sth. similar?
> 
> The only way to safely do it seems to use register scavenger to get a temp register, and spill this in eliminateFrameIndex? Is there an obvious way to spill to a register instead? Thanks in advance for any hints
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20191218/8c995370/attachment.html>


More information about the llvm-dev mailing list