Discussion Thread: DIP 1040--Copying, Moving, and Forwarding--Community Review Round 1

H. S. Teoh hsteoh at quickfur.ath.cx
Fri Mar 5 22:57:24 UTC 2021


On Fri, Mar 05, 2021 at 09:29:26PM +0000, tsbockman via Digitalmars-d wrote:
> On Friday, 5 March 2021 at 21:04:23 UTC, Ben Jones wrote:
> > On Friday, 5 March 2021 at 20:29:01 UTC, tsbockman wrote:
> > > Very small structs are often placed in registers when passed by
> > > value.
> > 
> > > This optimization would need to be disabled for any type with a
> > > move constructor.
> > 
> > I'm not sure it would need to be disabled.  I think the only part
> > that would really apply here is who has to call the constructor.
> 
> If the main use case for move constructors is to update pointers into
> a struct instance, how can that work for an instance that no longer
> has an address in memory at all?
> 
> The move constructor itself takes its `this` parameter by reference.
> How would you even call the move constructor?

I think this is confusing semantics with implementation details.

An optimizing compiler may decide to keep the struct inside registers
but that doesn't mean it can't also allocate the struct on the stack,
the location of which will serve as the address of the struct. As long
as the registers are written back to the stack at the point where a
pointer might be dereferenced, that's good enough.  And if the pointer
is never actually dereferenced, then the whole thing could be elided
completely and the struct will exist only in registers.

It's entirely possible that a struct that keeps a pointer to itself with
a move ctor that updates the pointer may never actually call the move
ctor (e.g., it's used only as a local variable with no escaping
references); an optimizing compiler can deduce that no address is
actually taken of the struct so it can be held completely in registers.
Or there may be some calls to the move ctor implied by the original text
of the code, but after eliding some dead code it's determined that the
updated pointer never gets read, then the optimizer can just elide the
whole thing and enregister the struct.

None of this has to do with the semantics of the move ctor specified by
the language. The language specifies certain semantics for certain
constructs, but the optimizer is free to arbitrarily transform the
program, as long as the *overall* semantics do not change. (Case in
point: programs that always produce the same output are sometimes
optimized into an empty main() by LDC, because none of the implied
complex semantics actually matter as far as actual output is concerned.
However, this is not in the purview of the language spec.)


T

-- 
Customer support: the art of getting your clients to pay for your own incompetence.


More information about the Digitalmars-d mailing list