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); } }