https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95349

--- Comment #22 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Smith from comment #20)
> (In reply to Andrew Downing from comment #19)
> > Not that it would make a difference in this particular situation, but is the
> > intent of P0593R6 to only allow implicitly creating an object in the
> > relevant storage location where one hasn't already been implicitly or
> > explicitly created?
> 
> No, the new objects are allowed to replace existing objects. For example,
> this implementation would also be correct:
> 
> std::uint64_t* s3(double* p) {
>     std::memmove(p, p, sizeof(double));
>     return std::launder(reinterpret_cast<std::uint64_t*>(p));
> }
> 
> ... on the basis that it has defined behavior if the memmove implicitly
> creates an 'uint64_t' object in the underlying storage after it (notionally)
> copies the contents elsewhere and before it (notionally) copies the contents
> back again. (The 'launder' is necessary in order to form a pointer to the
> implicitly-created uint64_t object, because p doesn't point to that object.)

Note that in GCCs view if there's a memcpy in the IL the memcpy destination
has indetermine type and accesses using any effective type lvalue are
well-defined.

The issue with the testcase at hand is that GCC elides the memcpy
(and the temporary object) completely - which was desired by the testcase
author.  But that loses this "barrier" from the IL.

Note that GCC both implements the C and the C++ language and performs
inter-CU optimization across language barriers and thus we need to find
common grounds of semantics - such as memcpy.  So for GCC the argument
"this is C++, we don't care for C semantics" isn't productive.

Note GCC also elides memcpy and memmove with identical source/destination
even though this technically has barrier semantics.

So IMHO std::start_lifetime_as would need first-class compiler support
and be appropriately represented in the IL.  Which also means it will
have a non-zero overhead but less overhead than for example keeping
a memmove (p, p, N) in the IL.

Which leads me towards the suggestion to work on memcpy semantics since
IMHO the C semantics provide the reason for what GCC does to the testcase
and I find it extremely odd (and bad for general optimization that doesn't
try to emulate std::start_lifetime_in_as) to require different semantics.

Note we're already allowing dynamic type changes of objects with a declared
type in C since that's also used in practice.  Note we're already pessimizing
C++ for re-using parts of objects.

So IMHO no GCC bug to see here.  And yes, GCC doesn't seem to be able to
implement std::start_lifetime_as without larger overhead at the moment.

Reply via email to