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.

Reply via email to