Multiple return values...

Robert Jacques sandford at jhu.edu
Sun Mar 11 19:57:37 PDT 2012


On Sun, 11 Mar 2012 18:30:33 -0500, Manu <turkeyman at gmail.com> wrote:
> On 12 March 2012 00:50, Robert Jacques <sandford at jhu.edu> wrote:
>> On Sun, 11 Mar 2012 05:56:03 -0500, Manu <turkeyman at gmail.com> wrote:
>>> On 11 March 2012 03:45, Robert Jacques <sandford at jhu.edu> wrote:
>>>> On Sat, 10 Mar 2012 19:27:05 -0600, Manu <turkeyman at gmail.com> wrote:
>>>>> On 11 March 2012 00:25, Sean Cavanaugh <WorksOnMyMachine at gmail.com>

[snip]

> x86 is not the only architecture on earth, it's arguably not even a
> particularly important one commercially with respect to realtime software.
> Also from a codegen point of view, it's usually the least important
> architecture by a mile, since x86 chips don't actually run the code they
> receive, they reinterpret it to some microcode and perform a crap load of
> clever optimisations in the process. Every other architecture has many more
> registers, and uses many more of them for passing args. They also suffer
> much greater penalties than x86 in general.
>
> What I'm talking about is a language feature that implements (and
> guarantees) a policy to return many things in EXACTLY the same way that it
> passes many args TO a function. This is already the most efficient way to
> pass many things between functions in any given architecture.
>
> In addition to that, I'm also discussing the usefulness of a nice sugary
> syntax to do this at the same time, for clarity and productivity.

Why should D place this constraint on future compilers? D currently only specifies the ABI for x86. I'm fairly sure it would follow the best practices for each of the other architecture, but none of them have been established yet.

> GCC-64 for example, does the following "Entire object is returned in
>> integer registers and/or XMM registers if the size is no bigger than 128
>> bits, otherwise on the stack. Each 64-bit part of the object is
>> transferred in an XMM register if it contains only float or double, or in
>> an integer register if it contains integer types or mixed integer and
>> float. Two consecutive float’s can be packed into the lower half of one XMM
>> register.
>
>
> They shouldn't need to be packed into anything, they already live in their
> own registers. The ABI specifies a certain number of argument registers, it
> can return in those at zero cost.
> And again, you're only considering x86.

I'm was giving you an example that seemed to satisfy your complaints. An no, actually it can't return in those registers at zero cost. There is a reason why we don't use all the registers to both pass and return arguments: we need some registers free to work on them both before and after the call. And as for asymmetry, you'd expect that when you call a function it's going to work on/with most of the data; that's not true for the callee. The size of both of these is something that is probably best determined by empirical tests.

[snip]

>> Manu, if this is truly only breaking you head now, then all I can conclude
>> is that you opened this discussion on low level function return
>> optimizations with absolutely zero knowledge of the subject matter you were
>> trying to discus; I find this very frustrating.
>>
>
> I have 15+ years of experience with C on basically every architecture you
> could name, I'm absolutely aware of what C ABI's look like with regard to
> returning structures by value.
> I find the common assumption that all computers on earth are x86 perhaps
> even more frustrating, and the fact that you've missed the point about
> usage of ALL the argument registers to avoid pointless packing/unpacking
> and memory access entirely.
> C is incapable of expressing MRV, and doesn't have an ABI for it, talking
> about C compiler optimisation tricks is irrelevant. D should define an MRV
> ABI which is precisely the ABI for passing multiple args TO a function, but
> in reverse, for any given architecture. This also has the lovely side
> effect of guaranteeing correct argument placement for chain-called
> functions.

Experience with C != experience with C++ != experience with D. And since DMD is an x86 compiler, the x86 assumption is somewhat natural. x86 is also probably one of the most studied, tested and engineered (for good or ill) architectures, both in terms of hardware and software (though I did learn on RISC). I don't have a problem breaking from the C ABI, but we should probably have a good reason to. I know Go has MRV. What does its ABI look like? What does ARM prefer? I'd recommend citing some papers or a compiler or something. Otherwise, it looks like you're ignoring the wisdom of the masses or simply ignorant.

P.S. The fun(gun()) case is interesting, but it seems like a corner case. Designing the ABI around it feels wrong, if it hurts performance elsewhere.


More information about the Digitalmars-d mailing list