On Thu, Apr 17, 2025 at 7:51 PM Andrew Pinski <quic_apin...@quicinc.com> wrote:
>
> The case here is we have:
> ```
>     char buf[32] = {};
>     void* ret = aaa();
>     __builtin_memcpy(ret, buf, 32);
> ```
>
> And buf does not escape.  But we don't prop the zeroing from buf to the 
> memcpy statement
> because optimize_memcpy_to_memset only looks back one statement. This can be 
> fixed to look back
> until we get an statement that may clobber the reference.  If we get a phi 
> node, then we don't do
> anything.
>
> Bootstrapped and tested on x86_64-linux-gnu.
>
>         PR tree-optimization/118947
>
> gcc/ChangeLog:
>
>         * gimple-fold.cc (optimize_memcpy_to_memset): Walk back until we get a
>         statement that may clobber the read.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/pr118947-1.c: New test.
>
> Signed-off-by: Andrew Pinski <quic_apin...@quicinc.com>
> ---
>  gcc/gimple-fold.cc                | 39 ++++++++++++++++++++++---------
>  gcc/testsuite/gcc.dg/pr118947-1.c | 15 ++++++++++++
>  2 files changed, 43 insertions(+), 11 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/pr118947-1.c
>
> diff --git a/gcc/gimple-fold.cc b/gcc/gimple-fold.cc
> index 3e6b53d6a0f..94d5a1ebbd7 100644
> --- a/gcc/gimple-fold.cc
> +++ b/gcc/gimple-fold.cc
> @@ -906,18 +906,41 @@ size_must_be_zero_p (tree size)
>  static bool
>  optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, tree dest, tree src, 
> tree len)
>  {
> +  ao_ref read;
>    gimple *stmt = gsi_stmt (*gsip);
>    if (gimple_has_volatile_ops (stmt))
>      return false;
>
> -  tree vuse = gimple_vuse (stmt);
> -  if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME)
> -    return false;
>
> -  gimple *defstmt = SSA_NAME_DEF_STMT (vuse);
>    tree src2 = NULL_TREE, len2 = NULL_TREE;
>    poly_int64 offset, offset2;
>    tree val = integer_zero_node;
> +  bool len_was_null = len == NULL_TREE;
> +  if (len == NULL_TREE)
> +    len = (TREE_CODE (src) == COMPONENT_REF
> +          ? DECL_SIZE_UNIT (TREE_OPERAND (src, 1))
> +          : TYPE_SIZE_UNIT (TREE_TYPE (src)));
> +  if (len == NULL_TREE
> +      || !poly_int_tree_p (len))
> +    return false;
> +
> +  ao_ref_init (&read, src);
> +  tree vuse = gimple_vuse (stmt);
> +  gimple *defstmt;
> +  do {
> +    if (vuse == NULL || TREE_CODE (vuse) != SSA_NAME)
> +      return false;
> +    defstmt = SSA_NAME_DEF_STMT (vuse);
> +    if (is_a <gphi*>(defstmt))
> +      return false;
> +
> +    /* If the len was null, then we can use TBBA. */
> +    if (stmt_may_clobber_ref_p_1 (defstmt, &read,
> +                                 /* tbaa_p = */ len_was_null))
> +      break;
> +    vuse = gimple_vuse (defstmt);
> +  } while (true);

I don't think this kind of unbound walk is OK, definitely not from
fold_stmt ().  This kind
of walking belongs to a optimization pass.

So, NAK.

Richard.

> +
>    if (gimple_store_p (defstmt)
>        && gimple_assign_single_p (defstmt)
>        && TREE_CODE (gimple_assign_rhs1 (defstmt)) == STRING_CST
> @@ -956,17 +979,11 @@ optimize_memcpy_to_memset (gimple_stmt_iterator *gsip, 
> tree dest, tree src, tree
>    if (src2 == NULL_TREE)
>      return false;
>
> -  if (len == NULL_TREE)
> -    len = (TREE_CODE (src) == COMPONENT_REF
> -          ? DECL_SIZE_UNIT (TREE_OPERAND (src, 1))
> -          : TYPE_SIZE_UNIT (TREE_TYPE (src)));
>    if (len2 == NULL_TREE)
>      len2 = (TREE_CODE (src2) == COMPONENT_REF
>             ? DECL_SIZE_UNIT (TREE_OPERAND (src2, 1))
>             : TYPE_SIZE_UNIT (TREE_TYPE (src2)));
> -  if (len == NULL_TREE
> -      || !poly_int_tree_p (len)
> -      || len2 == NULL_TREE
> +  if (len2 == NULL_TREE
>        || !poly_int_tree_p (len2))
>      return false;
>
> diff --git a/gcc/testsuite/gcc.dg/pr118947-1.c 
> b/gcc/testsuite/gcc.dg/pr118947-1.c
> new file mode 100644
> index 00000000000..70b7f800065
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr118947-1.c
> @@ -0,0 +1,15 @@
> +/* PR tree-optimization/118947 */
> +/* { dg-do compile { target size32plus } } */
> +/* { dg-options "-O2 -fdump-tree-forwprop1-details" } */
> +/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */
> +
> +void* aaa();
> +void* bbb()
> +{
> +    char buf[32] = {};
> +    /*  Tha call to aaa should not matter and clobber buf. */
> +    void* ret = aaa();
> +    __builtin_memcpy(ret, buf, 32);
> +    return ret;
> +}
> +
> --
> 2.43.0
>

Reply via email to