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

--- Comment #2 from Richard Biener <rguenth at gcc dot gnu.org> ---
I think the proper fix would be a larger rewrite of tree-tailcall to properly
isolate the path from call to return stmt.  This particular PR can be fixed
with sth like the following which lacks handling of dealing with copying
multiple stmts and updating the uses in those.  Path isolation would solve
that issue trivially and we could then even simply re-use the stmts computing
the accumulation ...

Not sth I can handle time-wise at this very moment so I'm going to paper over
this :/

Index: gcc/tree-ssa-loop-niter.c
===================================================================
--- gcc/tree-ssa-loop-niter.c   (revision 249638)
+++ gcc/tree-ssa-loop-niter.c   (working copy)
@@ -1792,7 +1792,7 @@ number_of_iterations_cond (struct loop *

 /* Substitute NEW for OLD in EXPR and fold the result.  */

-static tree
+tree
 simplify_replace_tree (tree expr, tree old, tree new_tree)
 {
   unsigned i, n;
Index: gcc/tree-tailcall.c
===================================================================
--- gcc/tree-tailcall.c (revision 249638)
+++ gcc/tree-tailcall.c (working copy)
@@ -392,6 +392,9 @@ propagate_through_phis (tree var, edge e
   return var;
 }

+tree
+simplify_replace_tree (tree expr, tree old, tree new_tree);
+
 /* Finds tailcalls falling into basic block BB. The list of found tailcalls is
    added to the start of RET.  */

@@ -532,8 +535,8 @@ find_tail_calls (basic_block bb, struct
      since we are running after dce.  */
   m = NULL_TREE;
   a = NULL_TREE;
-  auto_bitmap to_move_defs;
-  auto_vec<gimple *> to_move_stmts;
+  auto_bitmap to_copy_defs;
+  auto_vec<gimple *> to_copy_stmts;

   abb = bb;
   agsi = gsi;
@@ -566,7 +569,7 @@ find_tail_calls (basic_block bb, struct

       /* This is a gimple assign. */
       par ret = process_assignment (as_a <gassign *> (stmt), gsi,
-                                   &tmp_m, &tmp_a, &ass_var, to_move_defs);
+                                   &tmp_m, &tmp_a, &ass_var, to_copy_defs);
       if (ret == FAIL)
        return;
       else if (ret == TRY_MOVE)
@@ -576,12 +579,12 @@ find_tail_calls (basic_block bb, struct
          for (unsigned opno = 1; opno < gimple_num_ops (stmt); ++opno)
            {
              tree op = gimple_op (stmt, opno);
-             if (independent_of_stmt_p (op, stmt, gsi, to_move_defs) != op)
+             if (independent_of_stmt_p (op, stmt, gsi, to_copy_defs) != op)
                return;
            }
-         bitmap_set_bit (to_move_defs,
+         bitmap_set_bit (to_copy_defs,
                          SSA_NAME_VERSION (gimple_assign_lhs (stmt)));
-         to_move_stmts.safe_push (stmt);
+         to_copy_stmts.safe_push (stmt);
          continue;
        }

@@ -628,10 +631,19 @@ find_tail_calls (basic_block bb, struct
   if (tail_recursion)
     {
       unsigned i;
-      FOR_EACH_VEC_ELT (to_move_stmts, i, stmt)
+      FOR_EACH_VEC_ELT (to_copy_stmts, i, stmt)
        {
-         gimple_stmt_iterator mgsi = gsi_for_stmt (stmt);
-         gsi_move_before (&mgsi, &gsi);
+         gimple *copy = gimple_copy (stmt);
+         def_operand_p defp = SINGLE_SSA_DEF_OPERAND (copy, SSA_OP_DEF);
+         tree def = DEF_FROM_PTR (defp);
+         tree new_def = copy_ssa_name (def);
+         SET_DEF (defp, new_def);
+         SSA_NAME_DEF_STMT (new_def) = copy;
+         gsi_insert_before (&gsi, copy, GSI_SAME_STMT);
+         if (m)
+           m = simplify_replace_tree (m, def, new_def);
+         if (a)
+           a = simplify_replace_tree (a, def, new_def);
        }
     }

Reply via email to