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

Hendrik Greving via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 18 12:39:30 PST 2019

Ok, thanks. Except the question was meant slightly different. Less w.r.t.
organizing the register classes, and more w.r.t. implementation. I've
noticed for instance that when trying to model this straight forwardly by
writing a vreg from spills and reading this from fills (not further
elaborated here), that the spiller can't handle vreg def-use pairs: there
are assertions making sure a spill does not have any uses , e.g. see
InlineSpiller.cpp, allDefsAreDead() calls. This made me wonder if this is
supported natively at all.

On Wed, Dec 18, 2019 at 12:02 PM Quentin Colombet <qcolombet at apple.com>

> 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/c30c6bbd/attachment.html>

More information about the llvm-dev mailing list