On Thu, Aug 28, 2025 at 04:24:46PM +0200, Richard Biener wrote:
> That said, if we ever want to improve on this (and solve the redundant
> store elimination issue), we need an actual GIMPLE/RTL statement
> doing what std::start_lifetime_as <T> does (but not generate code).
> 
> Meaning, I'd vote for a p = __builtin_start_lifetime_as (p, (T *)0);

I thought earlier about just providing size.
null pointer with the new type would provide even more information,
iff we only support constant size types.
And we can then handle it in GIMPLE as if it is (or could be)
void *__builtin_start_lifetime_as (void *p)
{
  union { old_type old; T new; } u;
  __builtin_memcpy (u.old, p, sizeof (T));
  __builtin_memcpy (p, u.new, sizeof (T));
  return p;
}
(but of course for the const case or even for data races we actually
don't want either of those copies).
Now, I bet any kind of user function could do something like that if
it isn't inlined/exposed to the compiler, so not sure if we need to
handle it in too many places through GIMPLE, perhaps say that it
does or could access directly just the [p, p + sz) bytes (and indirectly
anything reachable).
But how to lower it into RTL is unclear, having it as CALL_EXPR will
mean it has to follow the call ABIs and all extra overhead.
UNSPEC_VOLATILE might be nice, but I guess we don't have a precedent
of backend independent constants for those.
Or expand it (just for RTL?) as inline asm,
  asm volatile ("" : "=g" (ptr), "m" (*(T *)ptr) : "0" (ptr), "m" (*(const T 
*)ptr));
?

        Jakub

Reply via email to