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]>
---
.../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