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 >
