https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64191
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #6)
> (In reply to Richard Biener from comment #3)
> > It also seems that DCE cannot remove the empty loop with the clobber,
> > because
> > it's marked useful and thus its SSA requirements are marked useful (we
> > explicitely exclude the VDEF but _not_ the SSA uses on the LHS of
> > *ssa_2 = {} clobbers). Even if we don't make that SSA use necessary we
> > still have made the clobber itself necessary and thus marked control
> > dependent
> > edges necessary.
> >
> > Thus IMHO we shouldn't make clobbers necessary at all but only keep those
> > live that we can keep live (all uses still live). That makes cddce1
> > kill bar_dtor_loop:
> >
> > void bar_dtor_loop(Bar*, unsigned int) (struct Bar * p, unsigned int n)
> > {
> > struct Bar * e;
> >
> > <bb 2>:
> > return;
> >
> > }
> >
> > but of course it probably will DCE all indirect clobbers on an address
> > that is otherwise unused. Jakub - do you think this will be a problem?
> >
> > Index: gcc/tree-ssa-dce.c
> > ===================================================================
> > --- gcc/tree-ssa-dce.c (revision 218479)
> > +++ gcc/tree-ssa-dce.c (working copy)
> > @@ -292,8 +292,7 @@ mark_stmt_if_obviously_necessary (gimple
> > break;
> >
> > case GIMPLE_ASSIGN:
> > - if (TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
> > - && TREE_CLOBBER_P (gimple_assign_rhs1 (stmt)))
> > + if (gimple_clobber_p (stmt))
> > return;
> > break;
> >
> > @@ -813,8 +812,9 @@ propagate_necessity (bool aggressive)
> > }
> > }
> >
> > - FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
> > - mark_operand_necessary (use);
> > + if (!gimple_clobber_p (stmt))
> > + FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
> > + mark_operand_necessary (use);
> >
> > use = gimple_vuse (stmt);
> > if (!use)
> > @@ -1362,6 +1362,24 @@ eliminate_unnecessary_stmts (void)
> > /* If GSI is not necessary then remove it. */
> > if (!gimple_plf (stmt, STMT_NECESSARY))
> > {
> > + /* Keep clobbers that we can keep live live. */
> > + if (gimple_clobber_p (stmt))
> > + {
> > + ssa_op_iter iter;
> > + use_operand_p use_p;
> > + bool dead = false;
> > + FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
> > + {
> > + gimple def = SSA_NAME_DEF_STMT (USE_FROM_PTR (use_p));
> > + if (!gimple_plf (def, STMT_NECESSARY))
> > + {
> > + dead = true;
> > + break;
> > + }
> > + }
> > + if (!dead)
> > + continue;
> > + }
> > if (!is_gimple_debug (stmt))
> > something_changed = true;
> > remove_dead_stmt (&gsi, bb);
>
> Or rather
>
> /* Keep clobbers that we can keep live live. */
> if (gimple_clobber_p (stmt))
> {
> ssa_op_iter iter;
> use_operand_p use_p;
> bool dead = true;
> FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
> {
> gimple def = SSA_NAME_DEF_STMT (USE_FROM_PTR (use_p));
> if (gimple_nop_p (def)
> || gimple_plf (def, STMT_NECESSARY))
> {
> dead = false;
> break;
> }
> }
>
> so we keep the indirect clobbers in destructors (with use of parameter
> SSA default defs).
Or
/* If GSI is not necessary then remove it. */
if (!gimple_plf (stmt, STMT_NECESSARY))
{
+ /* Keep clobbers that we can keep live live. */
+ if (gimple_clobber_p (stmt))
+ {
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ bool dead = false;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
+ {
+ gimple def = SSA_NAME_DEF_STMT (USE_FROM_PTR (use_p));
+ if (!gimple_nop_p (def)
+ && !gimple_plf (def, STMT_NECESSARY))
+ {
+ dead = true;
+ break;
+ }
+ }
+ if (!dead)
+ continue;
+ }
to not remove all direct clobbers but still keep indirect clobbers
on default defs.