https://gcc.gnu.org/g:53f491ccd1e59fad77fb2cb30d1a58b9e5e5f63c

commit r16-3066-g53f491ccd1e59fad77fb2cb30d1a58b9e5e5f63c
Author: Richard Biener <rguent...@suse.de>
Date:   Wed Aug 6 12:31:13 2025 +0200

    tree-optimization/121405 - missed VN with aggregate copy
    
    The following handles value-numbering of a BIT_FIELD_REF of
    a register that's defined by a load by looking up a subset
    load similar to how we handle bit-and masked loads.  This
    allows the testcase to be simplified by two FRE passes,
    the first one will create the BIT_FIELD_REF.
    
            PR tree-optimization/121405
            * tree-ssa-sccvn.cc (visit_nary_op): Handle BIT_FIELD_REF
            with reference def by looking up a combination of both.
    
            * gcc.dg/tree-ssa/ssa-fre-107.c: New testcase.
            * gcc.target/i386/pr90579.c: Adjust.

Diff:
---
 gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c | 29 +++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/i386/pr90579.c     |  7 ++-----
 gcc/tree-ssa-sccvn.cc                       | 22 ++++++++++++++++++++++
 3 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c 
b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c
new file mode 100644
index 000000000000..f80baf3ca8d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-107.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+struct vec_char_16
+{
+  unsigned char raw[2];
+};
+
+static inline struct vec_char_16
+Dup128VecFromValues(unsigned char t0, unsigned char t1)
+{
+  struct vec_char_16 result;
+  result.raw[0] = t0;
+  result.raw[1] = t1;
+  return result;
+}
+
+int f(unsigned char t0, unsigned char t1)
+{
+  struct vec_char_16 a = Dup128VecFromValues(t0, t1);
+  struct vec_char_16 b;
+  __builtin_memcpy(&b, &a, sizeof(a));
+  return b.raw[0] + b.raw[1];
+}
+
+/* Ideally we'd optimize this at FRE1 time but we only replace
+   the loads from b.raw[] with BIT_FIELD_REFs which get optimized
+   only later in the next FRE.  */
+/* { dg-final { scan-tree-dump-not "MEM" "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90579.c 
b/gcc/testsuite/gcc.target/i386/pr90579.c
index ab48a44063c3..bd2fd3378e13 100644
--- a/gcc/testsuite/gcc.target/i386/pr90579.c
+++ b/gcc/testsuite/gcc.target/i386/pr90579.c
@@ -16,8 +16,5 @@ loop (int k, double x)
   return t;
 }
 
-/* Verify we end up with scalar loads from r for the final sum.  */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+40" } } */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+32" } } */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+24" } } */
-/* { dg-final { scan-assembler "vaddsd\tr\\\+16" } } */
+/* Verify we end up with no loads from r.  */
+/* { dg-final { scan-assembler-not "v\[ma\]\[^\t \]+\tr" } } */
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 00315d154e4e..1c113f848ebb 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -5633,6 +5633,28 @@ visit_nary_op (tree lhs, gassign *stmt)
            }
        }
       break;
+    case BIT_FIELD_REF:
+      if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == SSA_NAME)
+       {
+         tree op0 = TREE_OPERAND (rhs1, 0);
+         gassign *ass = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op0));
+         if (ass
+             && !gimple_has_volatile_ops (ass)
+             && vn_get_stmt_kind (ass) == VN_REFERENCE)
+           {
+             tree last_vuse = gimple_vuse (ass);
+             tree op = build3 (BIT_FIELD_REF, TREE_TYPE (rhs1),
+                               gimple_assign_rhs1 (ass),
+                               TREE_OPERAND (rhs1, 1), TREE_OPERAND (rhs1, 2));
+             tree result = vn_reference_lookup (op, gimple_vuse (ass),
+                                                default_vn_walk_kind,
+                                                NULL, true, &last_vuse);
+             if (result
+                 && useless_type_conversion_p (type, TREE_TYPE (result)))
+               return set_ssa_val_to (lhs, result);
+           }
+       }
+      break;
     case TRUNC_DIV_EXPR:
       if (TYPE_UNSIGNED (type))
        break;

Reply via email to