This fixes DCE to remove pointless clobbers which then enables to DCE empty loops (with just clobbers). This is IMHO important to get rid of empty constructor calling loops which are not uncommon.
The way this now works is to treat clobbers as not necessary - but avoid removing them if required uses are not DCEd. Thus they get treated similar to debug stmts. Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk sofar. Richard. 2014-12-10 Richard Biener <rguent...@suse.de> PR tree-optimization/64191 * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Do not mark clobbers as necessary. (eliminate_unnecessary_stmts): Keep clobbers live if we can. * g++.dg/pr64191.C: Make sure we can DCE empty loops with indirect clobbers. 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; @@ -1362,6 +1361,25 @@ 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) + { + tree name = USE_FROM_PTR (use_p); + if (!SSA_NAME_IS_DEFAULT_DEF (name) + && !bitmap_bit_p (processed, SSA_NAME_VERSION (name))) + { + dead = true; + break; + } + } + if (!dead) + continue; + } if (!is_gimple_debug (stmt)) something_changed = true; remove_dead_stmt (&gsi, bb); Index: gcc/testsuite/g++.dg/pr64191.C =================================================================== --- gcc/testsuite/g++.dg/pr64191.C (revision 0) +++ gcc/testsuite/g++.dg/pr64191.C (working copy) @@ -0,0 +1,25 @@ +// { dg-do compile } +// { dg-options "-O2 -fdump-tree-cddce1" } + +struct Bar +{ + int i; + ~Bar() { } +}; +void bar_dtor_loop(Bar* p, unsigned int n) +{ + if (p) { + Bar* e = p + n; + while (e > p) { + --e; + e->~Bar(); + } + } +} + +// The clobber in ~Bar should persist but those inlined into +// bar_dtor_loop not, nor should the loop therein + +// { dg-final { scan-tree-dump-times "CLOBBER" 1 "cddce1" } } +// { dg-final { scan-tree-dump-times "if" 0 "cddce1" } } +// { dg-final { cleanup-tree-dump "cddce1" } }