]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
forwprop: Improve simple dse for eh [PR122247]
authorAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Wed, 29 Oct 2025 00:20:18 +0000 (17:20 -0700)
committerAndrew Pinski <andrew.pinski@oss.qualcomm.com>
Thu, 30 Oct 2025 15:10:12 +0000 (08:10 -0700)
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 <andrew.pinski@oss.qualcomm.com>
gcc/testsuite/g++.dg/tree-ssa/copy-prop-aggregate-sra-1.C [new file with mode: 0644]
gcc/tree-ssa-forwprop.cc

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 (file)
index 0000000..52f1779
--- /dev/null
@@ -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" } } */
+
index 68e80baa46c0e580527e2f6710abcfb0ee4807a3..4e273b9053a0ef2a840130a56b37f91fee99473a 100644 (file)
@@ -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))