https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121405

--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> ---
Hmm, so it's FRE1 that replaces

  a_20 = MEM[(struct vec_char_16 *)&D.3024];
  _5 = a_20;
  MEM <unsigned short> [(char * {ref-all})&b] = _5;
  _1 = b.raw[0];

with

  a_20 = MEM[(struct vec_char_16 *)&D.3024];
  MEM <unsigned short> [(char * {ref-all})&b] = a_20;
  _15 = BIT_FIELD_REF <a_20, 8, 0>;

via

Value numbering stmt = _1 = b.raw[0];
Inserting name _12 for expression BIT_FIELD_REF <a_20, 8, 0>
Setting value number of _1 to _12 (changed)

so handling BIT_FIELD_REFs as proposed then only works in FRE2:

Value numbering stmt = _7 = BIT_FIELD_REF <a_11, 8, 8>;
Setting value number of _7 to t1_5(D) (changed)


That means in the

  /* 4) Assignment from an SSA name which definition we may be able
     to access pieces from or we can combine to a larger entity.  */

case where we end up creating the BIT_FIELD_REF we could try to see
to handle it like an aggregate copy.

Meanwhile the following handes it in FRE2 (or when there's a BIT_FIELD_REF
already):

diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 00315d154e4..6b859de6ba9 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -5633,6 +5633,27 @@ 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)
+               return set_ssa_val_to (lhs, result);
+           }
+       }
+      break;
     case TRUNC_DIV_EXPR:
       if (TYPE_UNSIGNED (type))
        break;

Reply via email to