https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107569

--- Comment #48 from Richard Biener <rguenth at gcc dot gnu.org> ---
So instead of an extra DCE pass one could try harder to not leave around dead
code after folding, for example with the following (doesn't fix the testcase
yet, all the custom folding code would need adjustments as well).  But it's
not 100% reliable and it comes at a cost even when folding isn't successful
(while we don't update stmt operands immediately, what they point to is
changed by the actual folding already).

diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
index e34f0888954..133619899cd 100644
--- a/gcc/tree-ssa-forwprop.cc
+++ b/gcc/tree-ssa-forwprop.cc
@@ -53,6 +53,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "tree-ssa.h"
 #include "gimple-range.h"
+#include "tree-ssa-dce.h"

 /* This pass propagates the RHS of assignment statements into use
    sites of the LHS of the assignment.  It's basically a specialized
@@ -3466,6 +3467,7 @@ pass_forwprop::execute (function *fun)
   auto_vec<gimple *, 32> to_remove;
   to_purge = BITMAP_ALLOC (NULL);
   bitmap need_ab_cleanup = BITMAP_ALLOC (NULL);
+  auto_bitmap simple_dce_seed;
   for (int i = 0; i < postorder_num; ++i)
     {
       gimple_stmt_iterator gsi;
@@ -3846,8 +3848,16 @@ pass_forwprop::execute (function *fun)
                                   && gimple_call_noreturn_p (stmt));
              changed = false;

+             auto_vec<int, 4> seeds;
+             use_operand_p use_p;
+             ssa_op_iter iter;
+             FOR_EACH_SSA_USE_OPERAND (use_p, orig_stmt, iter, SSA_OP_USE)
+               seeds.safe_push (SSA_NAME_VERSION (USE_FROM_PTR (use_p)));
+
              if (fold_stmt (&gsi, fwprop_ssa_val))
                {
+                 for (int seed : seeds)
+                   bitmap_set_bit (simple_dce_seed, seed);
                  changed = true;
                  stmt = gsi_stmt (gsi);
                  /* Cleanup the CFG if we simplified a condition to
@@ -4037,6 +4047,8 @@ pass_forwprop::execute (function *fun)
       cfg_changed |= fixup_noreturn_call (stmt);
     }

+  simple_dce_from_worklist (simple_dce_seed);
+
   cfg_changed |= gimple_purge_all_dead_eh_edges (to_purge);
   cfg_changed |= gimple_purge_all_dead_abnormal_call_edges (need_ab_cleanup);
   BITMAP_FREE (to_purge);


Another possibility is preventing FRE/PRE from picking up dead stmts, as
suggested this does fix the testcase.  The extra stmt removal is not
strictly necessary.  I'm going to test sth like this.

diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index d5b081a309f..9f77b7a5647 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -6683,6 +6683,12 @@ eliminate_dom_walker::eliminate_stmt (basic_block b,
gimple_stmt_iterator *gsi)
               && DECL_HARD_REGISTER (gimple_assign_rhs1 (stmt))
               && is_global_var (gimple_assign_rhs1 (stmt)))))
     {
+      if (has_zero_uses (lhs))
+       {
+         to_remove.safe_push (stmt);
+         return;
+       }
+
       sprime = eliminate_avail (b, lhs);
       if (!sprime)
        {
@@ -7200,7 +7206,8 @@ eliminate_dom_walker::eliminate_stmt (basic_block b,
gimple_stmt_iterator *gsi)
      continue with the next stmt above and skip this.  */
   def_operand_p defp;
   FOR_EACH_SSA_DEF_OPERAND (defp, stmt, iter, SSA_OP_DEF)
-    eliminate_push_avail (b, DEF_FROM_PTR (defp));
+    if (! has_zero_uses (DEF_FROM_PTR (defp)))
+      eliminate_push_avail (b, DEF_FROM_PTR (defp));
 }

 /* Perform elimination for the basic-block B during the domwalk.  */
@@ -8048,7 +8055,8 @@ process_bb (rpo_elim &avail, basic_block bb,
        /* If not eliminating, make all not already available defs
           available.  */
        FOR_EACH_SSA_TREE_OPERAND (op, gsi_stmt (gsi), i, SSA_OP_DEF)
-         if (! avail.eliminate_avail (bb, op))
+         if (! has_zero_uses (op)
+             && ! avail.eliminate_avail (bb, op))
            avail.eliminate_push_avail (bb, op);
     }

Reply via email to