On Wed, Oct 29, 2025 at 5:21 PM Andrew Pinski
<[email protected]> wrote:
>
> In the case with EH, we end up with the following IR:
> ```
>   # .MEM_5 = VDEF <.MEM_4(D)>
>   inner = outer;
>   # .MEM_6 = VDEF <.MEM_5>
>   p (outer);
>
>   <bb 3> :
>   # .MEM_7 = VDEF <.MEM_6>
>   inner ={v} {CLOBBER(eos)};
> ...
>
>   <bb 4> :
> <L0>:
>   # .MEM_9 = VDEF <.MEM_6>
>   inner ={v} {CLOBBER(eos)};
> ```
>
> So when the simple DSE looks at the clobber from `bb3`, we find the use of
> MEM_6 is in a non dominating BB of BB3 so it gets rejected. But since this 
> usage
> is also a clobber which isthe same as the original clobber; it can be safely 
> assumed
> to do the same thing as the first clobber. So it can be safely ignored.
>
> Bootstrapped and tested on x86_64-linux-gnu.

OK.

>         PR tree-optimization/122247
>
> gcc/ChangeLog:
>
>         * tree-ssa-forwprop.cc (do_simple_agr_dse): Allow
>         use to be a clobber of the same kind to the same lhs.
>
> gcc/testsuite/ChangeLog:
>
>         * g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C: New test.
>
> Signed-off-by: Andrew Pinski <[email protected]>
> ---
>  .../tree-ssa/copy-prop-aggregate-sra-1.C      | 33 +++++++++++++++++++
>  gcc/tree-ssa-forwprop.cc                      |  7 ++++
>  2 files changed, 40 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C
>
> diff --git a/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C 
> b/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C
> new file mode 100644
> index 00000000000..52f1779bf51
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C
> @@ -0,0 +1,33 @@
> +/* { dg-do compile } */
> +/* { dg-options "-O1 -fdump-tree-forwprop1-details  -fdump-tree-esra-details 
> -fexceptions" } */
> +
> +/* PR tree-optimization/122247 */
> +
> +struct s1
> +{
> +  int t[1024];
> +};
> +
> +struct s1 f(void);
> +
> +void g(int a, int b, int );
> +void p(struct s1);
> +void h(struct s1 outer)
> +{
> +  {
> +    struct s1 inner = outer;
> +    p(inner);
> +  }
> +  g(outer.t[0], outer.t[1], outer.t[2]);
> +}
> +/* Forwprop should be able to copy prop the copy of `inner = outer` to the 
> call of p.
> +   Also remove this copy. */
> +
> +/* { dg-final { scan-tree-dump-times "after previous" 1 "forwprop1" } } */
> +/* { dg-final { scan-tree-dump-times "Removing dead store stmt inner = 
> outer" 1 "forwprop1" } } */
> +
> +/* The extra copy that was done by inlining is removed so SRA should not 
> decide to cause
> +   inner nor outer to be scalarized even for the 3 elements accessed 
> afterwards.  */
> +/* { dg-final { scan-tree-dump-times "Disqualifying inner" 1 "esra" } } */
> +/* { dg-final { scan-tree-dump-times "Disqualifying outer" 1 "esra" } } */
> +
> diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc
> index 79ac25f7ed5..0de0621c00a 100644
> --- a/gcc/tree-ssa-forwprop.cc
> +++ b/gcc/tree-ssa-forwprop.cc
> @@ -1818,6 +1818,7 @@ do_simple_agr_dse (gassign *stmt, bool full_walk)
>    /* Only handle clobbers of a full decl.  */
>    if (!DECL_P (lhs))
>      return;
> +  clobber_kind kind = (clobber_kind)CLOBBER_KIND (gimple_assign_rhs1 (stmt));
>    ao_ref_init (&read, lhs);
>    tree vuse = gimple_vuse (stmt);
>    unsigned limit = full_walk ? param_sccvn_max_alias_queries_per_access : 4;
> @@ -1839,6 +1840,12 @@ do_simple_agr_dse (gassign *stmt, bool full_walk)
>           basic_block ubb = gimple_bb (use_stmt);
>           if (stmt == use_stmt)
>             continue;
> +         /* If the use is the same kind of clobber for lhs,
> +            then it can be safely skipped; this happens with eh
> +            and sometimes jump threading.  */
> +         if (gimple_clobber_p (use_stmt, kind)
> +             && lhs == gimple_assign_lhs (use_stmt))
> +           continue;
>           /* The use needs to be dominating the clobber. */
>           if ((ubb != bb && !dominated_by_p (CDI_DOMINATORS, bb, ubb))
>               || ref_maybe_used_by_stmt_p (use_stmt, &read, false))
> --
> 2.43.0
>

Reply via email to