`in` parameters made useful

tsbockman thomas.bockman at gmail.com
Tue Aug 4 23:18:56 UTC 2020

First off, this is a great change and I am excited to be able to 
use it in my own projects. Thanks for championing this.

On Friday, 31 July 2020 at 21:49:25 UTC, Mathias LANG wrote:
> B) It makes `in` take the effect of `ref` when it makes sense. 
> It always pass something by `ref` if the type has elaborate 
> construction / destruction (postblit, copy constructor, 
> destructors). If the type doesn't have any of those it is only 
> passed by `ref` if it cannot be passed in register. Some types 
> (dynamic arrays, probably AA in the future) are not affected to 
> allow for covariance (more on that later). The heuristics there 
> still need some small improvements, e.g. w.r.t. floating points 
> (currently the heuristic is based on size, and not asking the 
> backend) and small struct slicing, but that should not affect 
> correctness.

This optimization should be implemented by querying the backend, 
not calculated from scratch in the frontend, which is redundant 
and error-prone; the rules in the current PR are not accurate.

The correct rules are complex, platform-dependent, and depend on 
the types of each function's full parameter list as a whole, not 
just each parameter individually. I haven't found anywhere that 
documents them, but by experimentation with LDC I have discovered 
the following:

1) The size limit for most types to be passed in registers in 
x86_64 is twice as large as the PR's threshold, at least on LDC. 
(Array slices are passed by register because of their size and 
member types, and do not need to be special-cased. A custom 
slice-like struct with a pointer and a size member will be passed 
by register, too.)

2) I say *most* types because there are exceptions; __vector 
types, and *sometimes* structs that transitively contain only a 
single __vector member (like 3d homogenous coordinates in 
graphics programming) are also passed via register, although they 
may be 8 times the size of a general purpose register when using 
AVX2 in a 32-bit program, and probably even larger on some other 

3) There are limits to how many arguments can be passed via 
registers. I say "limits", plural, because different data types 
may consume different types of registers; for example on x86, 
`int` uses general purpose registers, whereas `float` uses SIMD 
registers. These limits are architecture-dependent.

More information about the Digitalmars-d mailing list