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;