On Thu, Aug 29, 2019 at 11:04 AM Martin Jambor <mjam...@suse.cz> wrote:
>
> Hi,
>
> when turning a tail-recursive call into a loop, the tail-call pass
> creates a phi node for each gimple_reg function parameter that has any
> use at all, even when the value passed to the original call is the same
> as the received one, when it is the parameter's default definition.
> This results in a redundant phi node in which one argument is the
> default definition and all others are the LHS of the same phi node.  See
> the Bugzilla entry for an example.  These phi nodes in turn confuses
> ipa-prop.c which cannot skip them and may not create a pass-through jump
> function when it should.
>
> Fixed by the following patch which just adds a bitmap to remember where
> there are non-default-defs passed to a tail-recursive call and then
> creates phi nodes only for such parameters.  It has passed bootstrap and
> testing on x86_64-linux.
>
> OK for trunk?

OK.  Eventually arg_needs_copy_p can be elided completely
and pre-computed into the bitmap so we can just check
the positional?  And rename the bitmap to arg_need_copy itself.

Thanks,
Richard.

>
> Martin
>
>
> 2019-08-28  Martin Jambor  <mjam...@suse.cz>
>
>         tree-optimization/91579
>         * tree-tailcall.c (tailr_non_ddef_args): New variable.
>         (find_tail_calls): Allocate tailr_non_ddef_args and set its bits as
>         appropriate.
>         (arg_needs_copy_p): New parameter idx.  Also check
>         tailr_non_ddef_args.
>         (tree_optimize_tail_calls_1): Free tailr_non_ddef_args.
>
>         testsuite/
>         * gcc.dg/tree-ssa/pr91579.c: New test.
> ---
>  gcc/testsuite/gcc.dg/tree-ssa/pr91579.c | 22 ++++++++++++++
>  gcc/tree-tailcall.c                     | 38 +++++++++++++++++++------
>  2 files changed, 52 insertions(+), 8 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr91579.c
>
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91579.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/pr91579.c
> new file mode 100644
> index 00000000000..ee752be1a85
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr91579.c
> @@ -0,0 +1,22 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -fdump-tree-tailr1" } */
> +
> +typedef long unsigned int size_t;
> +typedef int (*compare_t)(const void *, const void *);
> +
> +int partition (void *base, size_t nmemb, size_t size, compare_t cmp);
> +
> +void
> +my_qsort (void *base, size_t nmemb, size_t size, compare_t cmp)
> +{
> +  int pt;
> +  if (nmemb > 1)
> +    {
> +      pt = partition (base, nmemb, size, cmp);
> +      my_qsort (base, pt + 1, size, cmp);
> +      my_qsort ((void*)((char*) base + (pt + 1) * size),
> +               nmemb - pt - 1, size, cmp);
> +    }
> +}
> +
> +/* { dg-final { scan-tree-dump-not "cmp\[^\r\n\]*PHI" "tailr1" } } */
> diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
> index a4b563efd73..23d60f492da 100644
> --- a/gcc/tree-tailcall.c
> +++ b/gcc/tree-tailcall.c
> @@ -126,6 +126,13 @@ struct tailcall
>     accumulator.  */
>  static tree m_acc, a_acc;
>
> +/* Bitmap with a bit for each function parameter which is set to true if in a
> +   tail-recursion we pass to the actual argument something else than the
> +   default definition of the corresponding formal parameter.  It has no 
> meaning
> +   for non-gimple-register parameters.  */
> +
> +static bitmap tailr_non_ddef_args;
> +
>  static bool optimize_tail_call (struct tailcall *, bool);
>  static void eliminate_tail_call (struct tailcall *);
>
> @@ -727,6 +734,17 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
>           gimple_stmt_iterator mgsi = gsi_for_stmt (stmt);
>           gsi_move_before (&mgsi, &gsi);
>         }
> +      if (!tailr_non_ddef_args)
> +       tailr_non_ddef_args = BITMAP_ALLOC (NULL);
> +      for (param = DECL_ARGUMENTS (current_function_decl), idx = 0;
> +          param;
> +          param = DECL_CHAIN (param), idx++)
> +       {
> +         tree arg = gimple_call_arg (call, idx);
> +         if (is_gimple_reg (param)
> +             && (arg != ssa_default_def (cfun, param)))
> +           bitmap_set_bit (tailr_non_ddef_args, idx);
> +       }
>      }
>
>    nw = XNEW (struct tailcall);
> @@ -905,11 +923,11 @@ decrease_profile (basic_block bb, profile_count count)
>      }
>  }
>
> -/* Returns true if argument PARAM of the tail recursive call needs to be 
> copied
> -   when the call is eliminated.  */
> +/* Returns true if PARAM, which is the IDX-th argument of the tail 
> recursively
> +   called function, needs to be copied when the call is eliminated.  */
>
>  static bool
> -arg_needs_copy_p (tree param)
> +arg_needs_copy_p (tree param, unsigned idx)
>  {
>    tree def;
>
> @@ -918,7 +936,7 @@ arg_needs_copy_p (tree param)
>
>    /* Parameters that are only defined but never used need not be copied.  */
>    def = ssa_default_def (cfun, param);
> -  if (!def)
> +  if (!def || !bitmap_bit_p (tailr_non_ddef_args, idx))
>      return false;
>
>    return true;
> @@ -1005,7 +1023,7 @@ eliminate_tail_call (struct tailcall *t)
>         param;
>         param = DECL_CHAIN (param), idx++)
>      {
> -      if (!arg_needs_copy_p (param))
> +      if (!arg_needs_copy_p (param, idx))
>         continue;
>
>        arg = gimple_call_arg (stmt, idx);
> @@ -1139,10 +1157,11 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
>               split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
>
>           /* Copy the args if needed.  */
> -         for (param = DECL_ARGUMENTS (current_function_decl);
> +         unsigned idx;
> +         for (param = DECL_ARGUMENTS (current_function_decl), idx = 0;
>                param;
> -              param = DECL_CHAIN (param))
> -           if (arg_needs_copy_p (param))
> +              param = DECL_CHAIN (param), idx++)
> +           if (arg_needs_copy_p (param, idx))
>               {
>                 tree name = ssa_default_def (cfun, param);
>                 tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT 
> (name));
> @@ -1206,6 +1225,9 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
>    if (phis_constructed)
>      mark_virtual_operands_for_renaming (cfun);
>
> +  if (tailr_non_ddef_args)
> +    BITMAP_FREE (tailr_non_ddef_args);
> +
>    if (changed)
>      return TODO_cleanup_cfg | TODO_update_ssa_only_virtuals;
>    return 0;
> --
> 2.22.0
>

Reply via email to