<div dir="ltr">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?<div><br></div><div>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.<br><div><br></div><div>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.</div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Dec 9, 2020 at 8:21 AM Nicolai Hähnle via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>We may eventually find some use for this as well, though it's speculative.<br></div><div><br></div><div>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?</div><div><br></div><div>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.<br></div><div><br></div><div>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. <br></div><div><br></div><div>Cheers,</div><div>Nicolai<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Dec 9, 2020 at 2:31 PM Tim Northover via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">One line proposal: I want to be able to write<br>
<br>
    declare { i8 signext, i16 zeroext } @foo()<br>
<br>
I think it's probably justifiable purely on symmetry grounds, a returned struct<br>
is really just a glorified parameter list to fit in with LLVM's requirement that<br>
a call produce a single Value, and why shouldn't you have as much control over<br>
how that parameter passing happens as you do on the call itself?<br>
<br>
But I do have a real motivating bugbear. Swifterror and the unfortunate fact<br>
that I need a second attribute like it.<br>
<br>
The swifterror attribute was implemented to support a special kind of function<br>
parameter that gets passed and then returned in a specific register,<br>
but functions<br>
can change.<br>
<br>
The "specific register" requirement is slightly odd, but shared by "swiftself"<br>
parameters and not a big problem to represent.<br>
<br>
But because we can't currently describe that final return (of a possibly<br>
different value), we perform an elaborate trick on the IR. Values are given a<br>
pseudo-memory location (created with a special alloca), and syntactic load/store<br>
operations to this get converted to normal vreg dataflow by a special<br>
SwiftErrorValueTracking class that essentially implements a subset of mem2reg<br>
behaviour during CodeGen. The final value is then magically returned in x21 (for<br>
AArch64).<br>
<br>
So in current IR you will see functions like this (with AArch64 real behaviour<br>
in comments):<br>
<br>
    define i32 @foo(i8** swifterror %loc) {<br>
      %errval = load i8*, i8** %loc     ; mov xErrVal, x21<br>
      ; Use current errval.<br>
      store i8* %newerr, i8** %loc      ; mov x21, xNewErr<br>
      [...]<br>
      ret i32 42 ; x0=42, x21=either incoming error, or new one if<br>
stored at some point.<br>
    }<br>
<br>
I'd like to replace them with what's really happening:<br>
<br>
    define { i32, i8* swifterror } @foo(i8* swifterror %errval) {<br>
      [...]<br>
      %ret.0 = insertvalue { i32, i8* } undef, i32 42, 0<br>
      %ret = insertvalue { i32, i8* } %ret.0, i8* %newerr, 1<br>
      ret { i32, i8* } %ret<br>
    }<br>
<br>
Front-ends can of course use a normal alloca to avoid explicitly value-tracking<br>
%newerr themselves and the real mem2reg will clean up the details.<br>
<br>
What about sret?<br>
----------------<br>
<br>
I think in this new world we'd have to relax the restriction that sret functions<br>
must otherwise return void, certainly to support the swifterror use-case. I<br>
don't think this is a huge problem though.<br>
<br>
Which attributes would be allowed?<br>
----------------------------------<br>
<br>
I'd propose starting small. Perhaps just allow signext and zeroext and<br>
convert swifterror in a separate patch. If people find uses for other attributes<br>
they can be added later.<br>
<br>
How do these combine with top-level return attributes?<br>
------------------------------------------------------<br>
<br>
Struct return types don't currently allow attributes; you can't write<br>
<br>
    define { i32, i32 } signext @foo() {<br>
<br>
I think it's fine to keep that restriction and only allow attributes on<br>
first-level inner types of structs.<br>
<br>
We'd be essentially creating a dual to the function's parameter list, but it<br>
has to be written as a struct because call instructions can only produce<br>
a single Value in LLVM (at one point I toyed with a new syntax like C++'s "auto<br>
foo() -> (i32, i32)" but discarded that idea for this reason, as well as the<br>
scale of that change).<br>
<br>
Where's the code?<br>
-----------------<br>
<br>
I haven't implemented it yet because it's quite a big change and I wanted to<br>
make sure there weren't too many objections, and that I hadn't missed<br>
an unmovable blocker.<br>
<br>
Cheers.<br>
<br>
Tim.<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div><br clear="all"><br>-- <br><div dir="ltr">Lerne, wie die Welt wirklich ist,<br>aber vergiss niemals, wie sie sein sollte.</div></div>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>