https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88739
--- Comment #8 from Richard Biener <rguenth at gcc dot gnu.org> --- So I think part of a fix would be the following. Not sure if REG_WORDS_BIG_ENDIAN or FLOAT_WORDS_BIG_ENDIAN come into play. With the fix we no longer simplify this for aarch64 since BITS_BIG_ENDIAN is 0 even in BE mode. Index: gcc/tree-ssa-sccvn.c =================================================================== --- gcc/tree-ssa-sccvn.c (revision 267553) +++ gcc/tree-ssa-sccvn.c (working copy) @@ -2229,13 +2229,18 @@ vn_reference_lookup_3 (ao_ref *ref, tree according to endianness. */ && (! INTEGRAL_TYPE_P (vr->type) || known_eq (ref->size, TYPE_PRECISION (vr->type))) - && multiple_p (ref->size, BITS_PER_UNIT)) + && multiple_p (ref->size, BITS_PER_UNIT) + && BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN + && BITS_BIG_ENDIAN == BYTES_BIG_ENDIAN) { gimple_match_op op (gimple_match_cond::UNCOND, BIT_FIELD_REF, vr->type, vn_valueize (gimple_assign_rhs1 (def_stmt)), bitsize_int (ref->size), - bitsize_int (offset - offset2)); + bitsize_int + (BYTES_BIG_ENDIAN + ? size2 - (offset - offset2) - ref->size + : offset - offset2)); tree val = vn_nary_build_or_lookup (&op); if (val && (TREE_CODE (val) != SSA_NAME In case both sizes/offsets are mutliples of BITS_PER_UNIT BITS_BIG_ENDIAN shouldn't matter though (likewise if size2 < WORD_SIZE). So a less conservative check might be && (known_le (size2, BITS_PER_WORD) || BYTES_BIG_ENDIAN == WORDS_BIG_ENDIAN) && (BITS_BIG_ENDIAN == BYTES_BIG_ENDIAN || (multiple_p (offset2, BITS_PER_UNIT) && multiple_p (offset, BITS_PER_UNIT) && (!BYTES_BIG_ENDIAN || multiple_p (size2, BITS_PER_UNIT))))) but I guess we lack exhaustive testing (and a list of targets that cover all combinations of endianesses). That is, not sure if BIT_FIELD_REF <_2, 16, 14> would be correct as suggested for aarch64_be because of that BITS_BIG_ENDIAN setting.