https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58483
--- Comment #11 from Marc Glisse <glisse at gcc dot gnu.org> --- (In reply to Richard Biener from comment #10) > Wit GCC 9 and trunk we are left with > > <bb 2> [local count: 118111600]: > MEM[(int *)&D.30957] = 85899345930; > D.30957[2] = 30; > _33 = operator new (12); > __builtin_memcpy (_33, &D.30957, 12); > _41 = MEM[(const int &)_33]; > __init_42 = _41 + 100; > _50 = MEM[(const int &)_33 + 4]; > __init_19 = __init_42 + _50; > _14 = MEM[(const int &)_33 + 8]; > __init_16 = _14 + __init_19; > operator delete (_33); > D.30957 ={v} {CLOBBER}; > return __init_16; > > here I think operator new clobbers D.30957 which escapes at the memcpy call. I thought we had code saying that nothing can escape through memcpy? > This prevents a late FRE from doing its job (not sure if a late one is > really needed). With #include <new> inline void* operator new(std::size_t n){return __builtin_malloc(n);} inline void operator delete(void*p)noexcept{__builtin_free(p);} inline void operator delete(void*p,std::size_t)noexcept{__builtin_free(p);} I get _33 = __builtin_malloc (12); MEM[(char * {ref-all})_33] = 85899345930; MEM[(char * {ref-all})_33 + 8B] = 30; _12 = MEM[(const int &)_33]; __init_49 = _12 + 100; _38 = MEM[(const int &)_33 + 4]; __init_36 = _38 + __init_49; _14 = MEM[(const int &)_33 + 8]; __init_16 = _14 + __init_36; __builtin_free (_33); return __init_16; where FRE should work.