<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
I failed to send this to the right address, so forwarding to llvm-dev</div>
<div>
<div style="font-family: Calibri, Arial, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<div id="appendonsend"></div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> james faure <james.faure@epitech.eu><br>
<b>Sent:</b> Friday, September 10, 2021 3:55 PM<br>
<b>To:</b> David Chisnall <David.Chisnall@cl.cam.ac.uk><br>
<b>Subject:</b> Re: [llvm-dev] On passing structures in registers</font>
<div> </div>
</div>
<div dir="ltr">
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
> copy what clang does<br>
To summarize clang then:</div>
<div style="font-family:Calibri,Arial,Helvetica,sans-serif; font-size:12pt; color:rgb(0,0,0)">
<ul>
<li><span>convert returned structs <= 128bits to { i64 , i64 }<br>
</span></li><li><span>larger structs are written to "sret" pointer parameter</span></li><li><span>explode struct arguments to two %i64 parameters if <= 128 bits</span></li><li>larger structs passed by "byval" pointer</li></ul>
<div>I've also run some tests with __regcall, when clang appears to be happy to return structs as large as 6 x 64 bits by value and for arguments prefers to explode structs (not even packing the fields into 2 i64s as it does without __regcall) into max 5 function
 parameters (after which it resorts to byval again)</div>
<div><br>
</div>
<div>The situation being so messy, and me not wanting to over specify anything instantly, is there some drawback to passing all structs by value, assuming I don't care about C interop ? I reason that extra fields would spill to the stack and thus be no worse
 than writing to memory explicitly.</div>
<div><br>
</div>
<div>James</div>
<div><br>
</div>
</div>
<div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="x_divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size:11pt"><b>From:</b> llvm-dev <llvm-dev-bounces@lists.llvm.org> on behalf of David Chisnall via llvm-dev <llvm-dev@lists.llvm.org><br>
<b>Sent:</b> Friday, September 10, 2021 3:16 PM<br>
<b>To:</b> llvm-dev@lists.llvm.org <llvm-dev@lists.llvm.org><br>
<b>Subject:</b> Re: [llvm-dev] On passing structures in registers</font>
<div> </div>
</div>
<div class="x_BodyFragment"><font size="2"><span style="font-size:11pt">
<div class="x_PlainText">On 10/09/2021 14:03, james faure via llvm-dev wrote:<br>
> There are several ways to pass structures in and out of functions, and <br>
> the fastest will presumably usually be in registers.<br>
> <br>
> Return:<br>
> System V lets us use 2 64-bit registers for structure returns<br>
<br>
SysV does not.  A psABI supplement to SysV does.  I guess that you're <br>
talking about the x86-64 psABI here?<br>
<br>
, where<br>
> figuring this out seems to be the frontend's problem; If the packed <br>
> struct is <= 128 bits, pass it by value as a llvm aggregate (and use <br>
> extractvalue and insertvalue to manipulate it) otherwise write to a <br>
> pointer with "sret" attribute and return void. It seems that once I <br>
> commit to the sret style, llvm can no longer return the struct in <br>
> registers, but I am also suspicious of always returning structs by <br>
> value, and even recall reading somewhere that llvm is not good at <br>
> handling large aggregates (maybe that applies mainly to loads and stores).<br>
> <br>
> Struct arguments:<br>
> Here too we have a choice between passing a llvm aggregate or passing <br>
> down a pointer argument with "byval" attribute. As before it is unclear <br>
> which should be preferred.<br>
<br>
It is unclear.  This is, unfortunately, a known problem with LLVM. <br>
There is an implicit contract between the back end and front end on how <br>
ABI-specific information is lowered and this often impacts mid-level <br>
optimisers.  For example, if you want to return a structure of two <br>
32-bit values (for example, a pair of pointers) in registers on x86 (as <br>
the BSD / macOS 32-bit ABIs do, but the Linux 32-bit ABI does not, <br>
though I think Linux does this for _Complex(int)) then this contract <br>
says that you should return them in an i64.  This then causes problems <br>
for alias analysis because the ptrtoint / inttoptr pair are treated as <br>
escaping.<br>
<br>
The best advice (which, I admit, is very bad) is to copy whatever clang <br>
does.<br>
<br>
Various people have discussed adding an ABI library or a better way of <br>
expressing ABI constraints (e.g. function / parameter attributes <br>
requiring specific registers / stack locations) into the IR.  If you <br>
wanted to work on this, I personally would be incredibly happy, but it's <br>
a fairly large amount of work.<br>
<br>
> I'm also curious about how best to represent bitvectors, and have <br>
> noticed clang sometimes casting structures to arrays; I currently use <br>
> raw arrays of %i1 and extract|insert value.<br>
<br>
In general, avoid using anything other than i{N*8} as an in-memory <br>
representation.  i1 is typically legalised to i8 at some point in the <br>
back-end lowering, so if you want to guarantee that something is a <br>
single bit in memory then you should use an array of i8s and masking <br>
operations.  The back end will infer bitfield insert / extract <br>
instructions where available.<br>
<br>
> My final concern is that the convention needs to be predictable, both <br>
> for ABI compatibility reasons and to inform appropriate Bitcasting of <br>
> function pointers. I would also like to understand what exactly informs <br>
> the threshold for switching strategy.<br>
<br>
I completely agree that the convention should be predictable. <br>
Unfortunately, there is currently little consistency in LLVM over how <br>
these implicit contracts between back and front-end are expressed.<br>
<br>
The root cause of a lot of these problems is that LLVM occasionally <br>
pretends that the contents of memory is typed, but does not do so very <br>
well.  The opaque pointer work is slowly fixing the most obvious <br>
problems here.<br>
<br>
David<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
llvm-dev@lists.llvm.org<br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</div>
</span></font></div>
</div>
</div>
</div>
</body>
</html>