[llvm-dev] [RFC] Granular Return Attributes

Philip Reames via llvm-dev llvm-dev at lists.llvm.org
Wed Dec 9 08:58:01 PST 2020


+1, this seems like clear goodness to me.

Philip

On 12/9/20 5:30 AM, Tim Northover via llvm-dev 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


More information about the llvm-dev mailing list