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