> Am 13.08.2025 um 19:05 schrieb Andrew Pinski <andrew.pin...@oss.qualcomm.com>:
> 
> From: Andrew Pinski <quic_apin...@quicinc.com>
> 
> This implements the simple copy prop of aggregates into
> arguments of function calls. This can reduce the number of copies
> done. Just like removing of an extra copy in general, this can and
> will help out SRA; since we might not need to do a full scalarization
> of the aggregate now.
> 
> This is the simpliest form of this copy prop of aggregates into function 
> arguments.


Ok

Thanks,
Richard 

> Changes since v1:
> * v2: Merge in the changes of r16-3160-g2fe432175ef135.
>      Move the checks for assignment and call statement into 
> optimize_agr_copyprop
>      rather than having it in optimize_agr_copyprop_1 and 
> optimize_agr_copyprop_arg.
> 
> gcc/ChangeLog:
> 
>    * tree-ssa-forwprop.cc (optimize_agr_copyprop_1): New function split out 
> of ...
>    (optimize_agr_copyprop): Here. Also try calling optimize_agr_copyprop_arg.
>    (optimize_agr_copyprop_arg): New function.
> 
> gcc/testsuite/ChangeLog:
> 
>    * gcc.dg/tree-ssa/copy-prop-aggregate-arg-1.c: New test.
> 
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
> .../tree-ssa/copy-prop-aggregate-arg-1.c      |  21 +++
> gcc/tree-ssa-forwprop.cc                      | 171 ++++++++++++------
> 2 files changed, 137 insertions(+), 55 deletions(-)
> create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-arg-1.c
> 
> diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-arg-1.c 
> b/gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-arg-1.c
> new file mode 100644
> index 00000000000..2ce68918e57
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-prop-aggregate-arg-1.c
> @@ -0,0 +1,21 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-forwprop1-details" } 
> */
> +
> +struct s1
> +{
> +  int t[1024];
> +};
> +
> +void f(struct s1);
> +
> +void g(struct s1 a)
> +{
> +  struct s1 temp_struct0 = a;
> +  f(temp_struct0);
> +}
> +
> +/* There should be no references to any of "temp_struct*"
> +   temporaries.  */
> +/* { dg-final { scan-tree-dump-times "temp_struct" 0 "optimized" } } */
> +/* Also check that forwprop pass did the copy prop. */
> +/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */
> diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
> index 2878b45b60d..ec4fbeb9e54 100644
> --- a/gcc/tree-ssa-forwprop.cc
> +++ b/gcc/tree-ssa-forwprop.cc
> @@ -1416,6 +1416,106 @@ optimize_aggr_zeroprop (gimple_stmt_iterator *gsip)
> 
>   return changed;
> }
> +
> +/* Helper function for optimize_agr_copyprop.
> +   For aggregate copies in USE_STMT, see if DEST
> +   is on the lhs of USE_STMT and replace it with SRC. */
> +static bool
> +optimize_agr_copyprop_1 (gimple *stmt, gimple *use_stmt,
> +             tree dest, tree src)
> +{
> +  gcc_assert (gimple_assign_load_p (use_stmt)
> +          && gimple_store_p (use_stmt));
> +  if (gimple_has_volatile_ops (use_stmt))
> +    return false;
> +  tree dest2 = gimple_assign_lhs (use_stmt);
> +  tree src2 = gimple_assign_rhs1 (use_stmt);
> +  /* If the new store is `src2 = src2;` skip over it. */
> +  if (operand_equal_p (src2, dest2, 0))
> +    return false;
> +  if (!operand_equal_p (dest, src2, 0))
> +    return false;
> +  /* For 2 memory refences and using a temporary to do the copy,
> +     don't remove the temporary as the 2 memory references might overlap.
> +     Note t does not need to be decl as it could be field.
> +     See PR 22237 for full details.
> +     E.g.
> +     t = *a; #DEST = SRC;
> +     *b = t; #DEST2 = SRC2;
> +     Cannot be convert into
> +     t = *a;
> +     *b = *a;
> +     Though the following is allowed to be done:
> +     t = *a;
> +     *a = t;
> +     And convert it into:
> +     t = *a;
> +     *a = *a;
> +     */
> +  if (!operand_equal_p (dest2, src, 0)
> +      && !DECL_P (dest2) && !DECL_P (src))
> +    return false;
> +
> +  if (dump_file && (dump_flags & TDF_DETAILS))
> +    {
> +      fprintf (dump_file, "Simplified\n  ");
> +      print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
> +      fprintf (dump_file, "after previous\n  ");
> +      print_gimple_stmt (dump_file, stmt, 0, dump_flags);
> +    }
> +  gimple *orig_stmt = use_stmt;
> +  gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
> +  gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (src));
> +  update_stmt (use_stmt);
> +
> +  if (dump_file && (dump_flags & TDF_DETAILS))
> +    {
> +      fprintf (dump_file, "into\n  ");
> +      print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
> +    }
> +  if (maybe_clean_or_replace_eh_stmt (orig_stmt, use_stmt))
> +    bitmap_set_bit (to_purge, gimple_bb (stmt)->index);
> +  statistics_counter_event (cfun, "copy prop for aggregate", 1);
> +  return true;
> +}
> +
> +/* Helper function for optimize_agr_copyprop_1, propagate aggregates
> +   into the arguments of USE_STMT if the argument matches with DEST;
> +   replacing it with SRC.  */
> +static bool
> +optimize_agr_copyprop_arg (gimple *defstmt, gcall *call,
> +               tree dest, tree src)
> +{
> +  bool changed = false;
> +  for (unsigned arg = 0; arg < gimple_call_num_args (call); arg++)
> +    {
> +      tree *argptr = gimple_call_arg_ptr (call, arg);
> +      if (TREE_CODE (*argptr) == SSA_NAME
> +      || is_gimple_min_invariant (*argptr)
> +      || TYPE_VOLATILE (TREE_TYPE (*argptr)))
> +    continue;
> +      if (!operand_equal_p (*argptr, dest, 0))
> +    continue;
> +      if (dump_file && (dump_flags & TDF_DETAILS))
> +    {
> +      fprintf (dump_file, "Simplified\n  ");
> +      print_gimple_stmt (dump_file, call, 0, dump_flags);
> +      fprintf (dump_file, "after previous\n  ");
> +      print_gimple_stmt (dump_file, defstmt, 0, dump_flags);
> +    }
> +      *argptr = unshare_expr (src);
> +      changed = true;
> +      if (dump_file && (dump_flags & TDF_DETAILS))
> +    {
> +      fprintf (dump_file, "into\n  ");
> +      print_gimple_stmt (dump_file, call, 0, dump_flags);
> +    }
> +    }
> +  if (changed)
> +    update_stmt (call);
> +  return changed;
> +}
> +
> /* Optimizes
>    DEST = SRC;
>    DEST2 = DEST; # DEST2 = SRC2;
> @@ -1424,6 +1524,14 @@ optimize_aggr_zeroprop (gimple_stmt_iterator *gsip)
>    DEST2 = SRC;
>    GSIP is the first statement and SRC is the common
>    between the statements.
> +
> +   Also optimizes:
> +   DEST = SRC;
> +   call_func(..., DEST, ...);
> +   into:
> +   DEST = SRC;
> +   call_func(..., SRC, ...);
> +
> */
> static bool
> optimize_agr_copyprop (gimple_stmt_iterator *gsip)
> @@ -1448,61 +1556,14 @@ optimize_agr_copyprop (gimple_stmt_iterator *gsip)
>   bool changed = false;
>   FOR_EACH_IMM_USE_STMT (use_stmt, iter, vdef)
>     {
> -      if (!gimple_assign_load_p (use_stmt)
> -      || !gimple_store_p (use_stmt))
> -    continue;
> -      if (gimple_has_volatile_ops (use_stmt))
> -    continue;
> -      tree dest2 = gimple_assign_lhs (use_stmt);
> -      tree src2 = gimple_assign_rhs1 (use_stmt);
> -      /* If the new store is `src2 = src2;` skip over it. */
> -      if (operand_equal_p (src2, dest2, 0))
> -    continue;
> -      if (!operand_equal_p (dest, src2, 0))
> -    continue;
> -      /* For 2 memory refences and using a temporary to do the copy,
> -     don't remove the temporary as the 2 memory references might overlap.
> -     Note t does not need to be decl as it could be field.
> -     See PR 22237 for full details.
> -     E.g.
> -     t = *a; #DEST = SRC;
> -     *b = t; #DEST2 = SRC2;
> -     Cannot be convert into
> -     t = *a;
> -     *b = *a;
> -     Though the following is allowed to be done:
> -     t = *a;
> -     *a = t;
> -     And convert it into:
> -     t = *a;
> -     *a = *a;
> -       */
> -      if (!operand_equal_p (dest2, src, 0)
> -      && !DECL_P (dest2) && !DECL_P (src))
> -    continue;
> -      if (dump_file && (dump_flags & TDF_DETAILS))
> -    {
> -      fprintf (dump_file, "Simplified\n  ");
> -      print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
> -      fprintf (dump_file, "after previous\n  ");
> -      print_gimple_stmt (dump_file, stmt, 0, dump_flags);
> -    }
> -      gimple *orig_stmt = use_stmt;
> -      gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
> -      gimple_assign_set_rhs_from_tree (&gsi, unshare_expr (src));
> -      update_stmt (use_stmt);
> -
> -      if (dump_file && (dump_flags & TDF_DETAILS))
> -    {
> -      fprintf (dump_file, "into\n  ");
> -      print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
> -    }
> -
> -      /* Mark the bb for eh cleanup if needed.  */
> -      if (maybe_clean_or_replace_eh_stmt (orig_stmt, use_stmt))
> -    bitmap_set_bit (to_purge, gimple_bb (stmt)->index);
> -      statistics_counter_event (cfun, "copy prop for aggregate", 1);
> -      changed = true;
> +      if (gimple_assign_load_p (use_stmt)
> +      && gimple_store_p (use_stmt)
> +      && optimize_agr_copyprop_1 (stmt, use_stmt, dest, src))
> +    changed = true;
> +      else if (is_gimple_call (use_stmt)
> +           && optimize_agr_copyprop_arg (stmt, as_a<gcall*>(use_stmt),
> +                         dest, src))
> +    changed = true;
>     }
>   return changed;
> }
> --
> 2.43.0
> 

Reply via email to