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