https://gcc.gnu.org/g:5558fa14d999c4d67a1efbba5ca1fe6d6f7ab3ae
commit r16-4740-g5558fa14d999c4d67a1efbba5ca1fe6d6f7ab3ae Author: Andrew Pinski <[email protected]> Date: Tue Oct 28 17:20:18 2025 -0700 forwprop: Improve simple dse for eh [PR122247] 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. 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]> Diff: --- .../g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C | 33 ++++++++++++++++++++++ gcc/tree-ssa-forwprop.cc | 7 +++++ 2 files changed, 40 insertions(+) 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 000000000000..52f1779bf519 --- /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 68e80baa46c0..4e273b9053a0 100644 --- a/gcc/tree-ssa-forwprop.cc +++ b/gcc/tree-ssa-forwprop.cc @@ -1793,6 +1793,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; @@ -1814,6 +1815,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))
