Alex Bradbury via llvm-dev
2017-Mar-07 17:42 UTC
[llvm-dev] Current preferred approach for handling 'byval' struct arguments
As many of you will know, handling of struct arguments in LLVM is actually slightly more fiddly than you might expect. For targets where aggregates are always passed on the stack it's easy enough, the Clang ABI code marks these arguments as byval and the call lowering code in LLVM will copy the object to the stack when needed. There are more options for when the target has more complex ABI rules, e.g. that as much of a struct that will fit should be passed in argument registers. One option is to let Clang (or the frontend of your choice) mark the argument as byval, but then have the LLVM call lowering code assign registers where possible. Alternatively, you can alter the frontend's ABI handling so it decomposes the struct for you - the challenge being ensuring that the appropriate packing/alignment is maintained. Because of this for some targets byval does mean "pass on the stack", but not others. There's been some discussion of this issue previously: * In the context of PowerPC, which will coerce structs below a certain size to an integer array <http://lists.llvm.org/pipermail/llvm-dev/2015-March/083554.html> * Previous suggestions that we really want an "onstack" attribute <http://lists.llvm.org/pipermail/llvm-dev/2012-May/049406.html> I'm working with a calling convention (https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md) where structs of up to two words in length should be passed in registers, but otherwise on the stack (EXCEPT in the case where there is only one argument register left, in which case the struct is split between that register and the stack). Is there a consensus now on how this should be handled? Thanks, Alex
Reid Kleckner via llvm-dev
2017-Mar-07 17:58 UTC
[llvm-dev] Current preferred approach for handling 'byval' struct arguments
Today, the vast majority of target in Clang coerce aggregates passed this way into appropriate word-sized types. They all use their own custom heuristics to compute the LLVM types used for the coercions. It's terrible, but this is the current consensus. I would like to improve the situation so that passing LLVM aggregates directly does the right thing when the LLVM struct type and C struct type are effectively the same, so that custom frontend lowering is required for hard cases involving things like _Complex and unions. On Tue, Mar 7, 2017 at 9:42 AM, Alex Bradbury via llvm-dev < llvm-dev at lists.llvm.org> wrote:> As many of you will know, handling of struct arguments in LLVM is > actually slightly more fiddly than you might expect. For targets where > aggregates are always passed on the stack it's easy enough, the Clang > ABI code marks these arguments as byval and the call lowering code in > LLVM will copy the object to the stack when needed. There are more > options for when the target has more complex ABI rules, e.g. that as > much of a struct that will fit should be passed in argument registers. > One option is to let Clang (or the frontend of your choice) mark the > argument as byval, but then have the LLVM call lowering code assign > registers where possible. Alternatively, you can alter the frontend's > ABI handling so it decomposes the struct for you - the challenge being > ensuring that the appropriate packing/alignment is maintained. Because > of this for some targets byval does mean "pass on the stack", but not > others. > > There's been some discussion of this issue previously: > * In the context of PowerPC, which will coerce structs below a certain > size to an integer array > <http://lists.llvm.org/pipermail/llvm-dev/2015-March/083554.html> > * Previous suggestions that we really want an "onstack" attribute > <http://lists.llvm.org/pipermail/llvm-dev/2012-May/049406.html> > > I'm working with a calling convention > (https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md) > where structs of up to two words in length should be passed in > registers, but otherwise on the stack (EXCEPT in the case where there > is only one argument register left, in which case the struct is split > between that register and the stack). > > Is there a consensus now on how this should be handled? > > Thanks, > > Alex > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://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/20170307/ce9bb140/attachment.html>
Alex Bradbury via llvm-dev
2017-Mar-08 09:02 UTC
[llvm-dev] Current preferred approach for handling 'byval' struct arguments
On 7 March 2017 at 17:58, Reid Kleckner <rnk at google.com> wrote:> Today, the vast majority of target in Clang coerce aggregates passed this > way into appropriate word-sized types. They all use their own custom > heuristics to compute the LLVM types used for the coercions. It's terrible, > but this is the current consensus. > > I would like to improve the situation so that passing LLVM aggregates > directly does the right thing when the LLVM struct type and C struct type > are effectively the same, so that custom frontend lowering is required for > hard cases involving things like _Complex and unions.Thanks for the response Reid. Looking more closely, it appears that the relationship between the target's ABI and whether aggregates are represented as byval structs, and whether these are coerced to something else in Clang's ABI handling)is more complex than I first described. For instance, looking at X86 code in clang/lib/CodeGen/TargetInfo.cpp I see that small aggregates are coerced as long as all argument registers are known to be used (i.e. we know the backend will place it on the stack, as demanded by the calling convention). ARM will also coerce structures below a certain size, however the call lowering code in ARMISelLowering still has logic to split a byval aggregate between the stack and registers (why not I have to say looking at AArch64ISelLowering and the clang code it's not immediately obvious to me where aggregates get split between the stack and registers (which is quite clear in MipsTargetLowering::passByValArg). What am I missing here? It seems to me there are a few possibilities for targets where the ABI indicates aggregates may be passed in registers: * Clang always passes aggregates as byval, LLVM call lowering may assign some or all of the aggregate to registers. Seemingly nobody does this * Clang's ABI lowering code is aware of how many argument registers have been used. If they have been exhausted, then leave the aggregate as byval. If aggregate will be partially in registers and partially on the stack, then coerce to two arguments - one byval and one direct. Seemingly nobody does this. * Split responsibilities between the Clang ABI lowering and the LLVM backend lowering. If an aggregate is below a certain size, then coerce and pass it direct. Depending on the ABI, the LLVM backend still has the possibility that a byval aggregate may be passed partially in registers and the stack and should handle that appropriately. This seems to be more common Best, Alex
Reasonably Related Threads
- Current preferred approach for handling 'byval' struct arguments
- [LLVMdev] Optimizing out redundant alloca involving byval params
- [LLVMdev] Optimizing out redundant alloca involving byval params
- RISC-V LLVM sync-up call 12 November 2020
- [LLVMdev] Optimizing out redundant alloca involving byval params