https://gcc.gnu.org/g:5294840e3c7bf9bd98016dec07f54ee8dc71714a

commit r16-3156-g5294840e3c7bf9bd98016dec07f54ee8dc71714a
Author: Richard Biener <rguent...@suse.de>
Date:   Mon Aug 11 10:42:47 2025 +0200

    tree-optimization/121493 - another missed VN with aggregate copy
    
    This is another case where opportunistically handling a first
    aggregate copy where we failed to match up the refs exactly
    (as we don't insert missing handling components) yields to a
    failure in the second aggregate copy that we visit.  Add another
    fixup to deal with such situations, in-line with that present
    opportunistic handling.
    
            PR tree-optimization/121493
            * tree-ssa-sccvn.cc (vn_reference_lookup_3): Opportunistically
            strip components with known offset.
    
            * gcc.dg/tree-ssa/ssa-fre-109.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-109.c | 23 +++++++++++++++++++++++
 gcc/tree-ssa-sccvn.cc                       | 11 +++++++++++
 2 files changed, 34 insertions(+)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-109.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-109.c
new file mode 100644
index 000000000000..f04e033c05b3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-109.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1" } */
+
+struct s1
+{
+  int t;
+};
+
+struct s2
+{
+  struct s1 t;
+};
+
+int f1(int a)
+{
+  struct s1 t = (struct s1){a};
+  struct s2 tt = (struct s2){t};
+  struct s2 ttt = tt;
+  struct s1 *t0 = &ttt.t;
+  return t0->t;
+}
+
+/* { dg-final { scan-tree-dump "return a" "fre1" } } */
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index cdd7c0542add..0f6760de4d42 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -3650,6 +3650,17 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void 
*data_,
          j--;
        }
 
+      /* When we still didn't manage to strip off all components from
+        lhs_op, opportunistically continue for those we can handle
+        via extra_off.  Note this is an attempt to fixup secondary
+        copies after we hit the !found && j == 0 case above.  */
+      while (j != -1
+            && known_ne (lhs_ops[j].off, -1U))
+       {
+         extra_off += -lhs_ops[j].off;
+         j--;
+       }
+
       /* i now points to the first additional op.
         ???  LHS may not be completely contained in VR, one or more
         VIEW_CONVERT_EXPRs could be in its way.  We could at least

Reply via email to