https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96354
--- Comment #14 from Richard Biener <rguenth at gcc dot gnu.org> --- OK, looks like inlining C<3>::C into foo<3, 3> produces this debug stmt. foo<3, 3> (struct D D.2506, struct C D.2507) { <bb 2> : C<3>::C (&<retval>); return <retval>; and inlined from C<3>::C (struct C * const this) { <bb 2> [local count: 1073741824]: *this_2(D) ={v} {CLOBBER}; # DEBUG D#1 => &this_2(D)->d # DEBUG this => D#1 # DEBUG INLINE_ENTRY baz # DEBUG this => NULL # DEBUG D#2 => MEM[(double *)this_2(D)] # DEBUG c => D#2 return; so if the MEM wouldn't be dead we'd face the same situation in regular stmts I guess. And we do. But then the inliner sees _10 = &D.2565[_9]; C<3>::C (_10); _12 = &D.2564[_9]; C<3>::C (_12); so value-substitution shouldn't happen here anyway... which means it is eventually a over-eager mapping registered due to debug for unused decls or so? So we should fix this more "upstream" I bet. In declare_return_variable we're doing insert_decl_map (id, result, var) with var == D.2567[_9] which is problematic. We might want to gimplify this there into ptr_42 = &D.2567[_9] and map <result> to MEM[ptr_42] instead? That might simplify code elsewhere but eventually affects code generation. Note this will only happen for return slots I think.