[llvm-dev] Marking a register as reserved midway through register allocation
Dylan McKay via llvm-dev
llvm-dev at lists.llvm.org
Mon May 1 14:36:19 PDT 2017
>
> Why not do it the other way around?
> Mark Y as reserved, and then at the end of the function if there was
> exactly one spill then put that variable in Y instead.
> If there were no spills then you lost nothing by reserving Y. If there
> were more than one then you need Y for this stack adjustment. So exactly
> one spill is the only case where you lost anything by reserving Y.
> Which is probably pretty rare, to be honest.
This is definitely an interesting idea. I think this would be doable, but
it would be a little dirtier than I'd like. We'd probably need to add a
custom pass, and we'd also need to persist some spilling information on a
TargetMachineFunction.
This is what most llvm CPU targets do:
> - Perform register allocation with all registers available
> - PrologEpilogInsertion will determine the final positions for the
> spill/reload stack slots. If we require additional instructions/registers
> to actually compute the addresses for the spills/reload then we use vregs
> for that. [1]
> - doScavengeFrameVirtualRegs() will use a RegisterScavenger instance to
> allocate the vregs: If there is a free register around it is used;
> Otherwise we do an emergency spill around the vreg lifetime. Targets have
> to ensure they reserved an emergency spillslot that can be accessed without
> additional registers in advance if there is a possibility that we need it.
> If I understand you correct that strategy does not work on AVR somehow?
> Then you are probably out of luck and need to extend llvms CodeGen with new
> strategies.
That sounds like a very similar situation to what I have, but I think that
you're right in that we would not be able to guarantee a free emergency
spillslot because we'd need SP in the Y register in order to store the
current value in the Y register, which is impossible.
I think I can see three different options
1. Implement Bruce's idea of always reserving the Y register and
converting a spill (if we have one) to use it so that we do not waste a
register
- Upsides
- Works for all register allocators at all optimisation levels
- Does not change behaviour for any other targets
- Downsides
- A small amount of support code required
2. Teach the register allocator to check reserved registers after
performing the first spill (or maybe at the end of allocation of a
function) and see if any more registers have been reserved. It could then
use similar code to the GitHub PR I posted above to unassign any
newly-reserved registers and rewind back.
- Upsides
- Will work for all targets
- Is the most general solution
- Downsides
- More corner cases the register allocator is handling
3. Subclass the register allocators specifically for AVR and add the
functionality to a register allocator specifically for AVR
- Upsides
- All code required self-contained in one file
- Downsides
- Need to add subclasses for all register allocators
- No other target subclasses a register allocator
Thoughts welcome (and wanted)!
On Tue, May 2, 2017 at 8:23 AM, Matthias Braun <mbraun at apple.com> wrote:
>
> On Apr 30, 2017, at 8:27 PM, Dylan McKay via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
> Hey all,
>
> I'm attempting to rewrite something that the AVR backend used to support
> (through an extremely dirty hack that was reverted before the upstreaming
> of the target).
>
> The removal of the hack can be seen on GitHub
>
> https://github.com/avr-llvm/llvm/pull/226/files
>
> On the AVR architecture, the stack pointer is not in a standard register,
> but rather it is a special register which can only be accessed via I/O
> instructions. In order to implement stack spilling/restoring we need to
> adjust the stack pointer, which is a problem because we need the value of
> SP to be in a general purpose register for us to perform arithmetic on it.
>
> In AVR-GCC, a frame pointer (the 'Y' register) is reserved if there are
> any spills in a method. This works fine because we can easily perform
> arithmetic on it and then save it into the real stack pointer via IO
> instructions.
>
> I would like to do the same for LLVM. This is tricky however, because we
> don't know if we need a frame pointer until we've finished register
> allocation and we've seen a spill.
>
> In the event that we do see a spill, it is likely that the 'Y' register
> has already been allocated to some other variable, and so we somehow need
> to deallocate it and then rewind the regalloc. That is what the old hack
> above does.
>
> Is there any way today I can deallocate a register and rewind allocation
> upon spilling?
>
>
> This is what most llvm CPU targets do:
>
> - Perform register allocation with all registers available
> - PrologEpilogInsertion will determine the final positions for the
> spill/reload stack slots. If we require additional instructions/registers
> to actually compute the addresses for the spills/reload then we use vregs
> for that. [1]
> - doScavengeFrameVirtualRegs() will use a RegisterScavenger instance to
> allocate the vregs: If there is a free register around it is used;
> Otherwise we do an emergency spill around the vreg lifetime. Targets have
> to ensure they reserved an emergency spillslot that can be accessed without
> additional registers in advance if there is a possibility that we need it.
>
> If I understand you correct that strategy does not work on AVR somehow?
> Then you are probably out of luck and need to extend llvms CodeGen with new
> strategies.
>
> - Matthias
>
> [1] There's some restrictions on how vregs may be used here, like the
> defs/uses must stay within the same block.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20170502/2e36ab30/attachment.html>
More information about the llvm-dev
mailing list