https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89354
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Created attachment 45724 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=45724&action=edit gcc9-pr89354.patch Untested fix. I think the bug is in make_extraction, which for VOIDmode, (mem:DI ...), 0, NULL_RTX, 33, 1, 1, 0 arguments returns strangely (for 32-bit target) (zero_extract:SI (mem:DI ...) (const_int 33) (const_int 0)). That looks bogus to me, because those 33 bits can't fit into SImode. Then make_field_assignment does: assign = make_extraction (VOIDmode, dest, pos, NULL_RTX, len, 1, 1, 0); if (assign == 0) return x; machine_mode new_mode = (GET_CODE (assign) == STRICT_LOW_PART ? GET_MODE (XEXP (assign, 0)) : GET_MODE (assign)); which sets new_mode to SImode too, and src = canon_reg_for_combine (simplify_shift_const (NULL_RTX, LSHIFTRT, src_mode, other, pos), dest); src = force_to_mode (src, new_mode, len >= HOST_BITS_PER_WIDE_INT ? HOST_WIDE_INT_M1U : (HOST_WIDE_INT_1U << len) - 1, 0); other is (const_int 0x100000000) and as pos is 0, the first call just returns the same constant, but force_to_mode turns it into const0_rtx, which is where we lose the |= 0x100000000ULL.