https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64191
--- Comment #6 from Richard Biener <rguenth at gcc dot gnu.org> --- (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).