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.