[llvm-dev] [RFC] Granular Return Attributes
Reid Kleckner via llvm-dev
llvm-dev at lists.llvm.org
Thu Dec 10 11:07:09 PST 2020
Tim's proposal sounds good to me. Can you say more about the motivation for
doing away with the current swifterror alloca convention? It seems
self-evidently ugly, but is there something that makes removing it urgent?
Regarding sret's void return requirement, keep in mind that many targets
(x86, others) return the sret pointer in the standard return register, and
we typically don't represent that at the IR level. Perhaps this doesn't
affect swiftcc, but it's something to keep in mind.
The long term goal of replacing first-class-aggregates with multi-value
producing instructions seems like a good future design direction, but it's
probably best left for another day.
On Wed, Dec 9, 2020 at 8:21 AM Nicolai Hähnle via llvm-dev <
llvm-dev at lists.llvm.org> wrote:
> We may eventually find some use for this as well, though it's speculative.
>
> This may be a good time to raise the question: How do people feel about
> changing LLVM IR to allow multiple values defined by a single instruction?
>
> That's a pretty significant change, but I think there are very good
> reasons for wanting to do this. I know we'd appreciate not having the IR
> obfuscated by `extractvalue`, for example. Smoothing the road of LLVM IR /
> MLIR integration is another one.
>
> I understand you may not want to get your particular problem blocked by
> such a major change. Either way, it doesn't feel like the changes would be
> in conflict with each other anyway.
>
> Cheers,
> Nicolai
>
> On Wed, Dec 9, 2020 at 2:31 PM Tim Northover via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> One line proposal: I want to be able to write
>>
>> declare { i8 signext, i16 zeroext } @foo()
>>
>> I think it's probably justifiable purely on symmetry grounds, a returned
>> struct
>> is really just a glorified parameter list to fit in with LLVM's
>> requirement that
>> a call produce a single Value, and why shouldn't you have as much control
>> over
>> how that parameter passing happens as you do on the call itself?
>>
>> But I do have a real motivating bugbear. Swifterror and the unfortunate
>> fact
>> that I need a second attribute like it.
>>
>> The swifterror attribute was implemented to support a special kind of
>> function
>> parameter that gets passed and then returned in a specific register,
>> but functions
>> can change.
>>
>> The "specific register" requirement is slightly odd, but shared by
>> "swiftself"
>> parameters and not a big problem to represent.
>>
>> But because we can't currently describe that final return (of a possibly
>> different value), we perform an elaborate trick on the IR. Values are
>> given a
>> pseudo-memory location (created with a special alloca), and syntactic
>> load/store
>> operations to this get converted to normal vreg dataflow by a special
>> SwiftErrorValueTracking class that essentially implements a subset of
>> mem2reg
>> behaviour during CodeGen. The final value is then magically returned in
>> x21 (for
>> AArch64).
>>
>> So in current IR you will see functions like this (with AArch64 real
>> behaviour
>> in comments):
>>
>> define i32 @foo(i8** swifterror %loc) {
>> %errval = load i8*, i8** %loc ; mov xErrVal, x21
>> ; Use current errval.
>> store i8* %newerr, i8** %loc ; mov x21, xNewErr
>> [...]
>> ret i32 42 ; x0=42, x21=either incoming error, or new one if
>> stored at some point.
>> }
>>
>> I'd like to replace them with what's really happening:
>>
>> define { i32, i8* swifterror } @foo(i8* swifterror %errval) {
>> [...]
>> %ret.0 = insertvalue { i32, i8* } undef, i32 42, 0
>> %ret = insertvalue { i32, i8* } %ret.0, i8* %newerr, 1
>> ret { i32, i8* } %ret
>> }
>>
>> Front-ends can of course use a normal alloca to avoid explicitly
>> value-tracking
>> %newerr themselves and the real mem2reg will clean up the details.
>>
>> What about sret?
>> ----------------
>>
>> I think in this new world we'd have to relax the restriction that sret
>> functions
>> must otherwise return void, certainly to support the swifterror use-case.
>> I
>> don't think this is a huge problem though.
>>
>> Which attributes would be allowed?
>> ----------------------------------
>>
>> I'd propose starting small. Perhaps just allow signext and zeroext and
>> convert swifterror in a separate patch. If people find uses for other
>> attributes
>> they can be added later.
>>
>> How do these combine with top-level return attributes?
>> ------------------------------------------------------
>>
>> Struct return types don't currently allow attributes; you can't write
>>
>> define { i32, i32 } signext @foo() {
>>
>> I think it's fine to keep that restriction and only allow attributes on
>> first-level inner types of structs.
>>
>> We'd be essentially creating a dual to the function's parameter list, but
>> it
>> has to be written as a struct because call instructions can only produce
>> a single Value in LLVM (at one point I toyed with a new syntax like C++'s
>> "auto
>> foo() -> (i32, i32)" but discarded that idea for this reason, as well as
>> the
>> scale of that change).
>>
>> Where's the code?
>> -----------------
>>
>> I haven't implemented it yet because it's quite a big change and I wanted
>> to
>> make sure there weren't too many objections, and that I hadn't missed
>> an unmovable blocker.
>>
>> Cheers.
>>
>> Tim.
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>
>
> --
> Lerne, wie die Welt wirklich ist,
> aber vergiss niemals, wie sie sein sollte.
> _______________________________________________
> 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/20201210/6157d80e/attachment.html>
More information about the llvm-dev
mailing list