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

Reply via email to