On Sun, 11 Mar 2012 18:30:33 -0500, Manu <turkey...@gmail.com> wrote:
On 12 March 2012 00:50, Robert Jacques <sandf...@jhu.edu> wrote:
On Sun, 11 Mar 2012 05:56:03 -0500, Manu <turkey...@gmail.com> wrote:
On 11 March 2012 03:45, Robert Jacques <sandf...@jhu.edu> wrote:
On Sat, 10 Mar 2012 19:27:05 -0600, Manu <turkey...@gmail.com> wrote:
On 11 March 2012 00:25, Sean Cavanaugh <worksonmymach...@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.