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

--- Comment #3 from Konstantinos Eleftheriou <konstantinos.eleftheriou at vrull 
dot eu> ---
`store_bit_field_1` in `gcc/expmed.cc` may take the `gen_lowpart`
narrowing branch when its destination register's mode has no equal
integral mode (e.g. a multi-register vector tuple such as `V4x4BF`):

```
opt_scalar_int_mode op0_mode = int_mode_for_mode (GET_MODE (op0));
scalar_int_mode imode;
if (!op0_mode.exists (&imode) || imode != GET_MODE (op0))
  {
    if (MEM_P (op0))
      op0 = adjust_bitfield_address_size (op0, op0_mode.else_blk (),
                                          0, MEM_SIZE (op0));
    else if (!op0_mode.exists ())
      {
        ...

        /* Stack-temp branch: result is copied back into op0.  */
        rtx temp = assign_stack_temp (GET_MODE (op0),
                                      GET_MODE_SIZE (GET_MODE (op0)));
        emit_move_insn (temp, op0);
        store_bit_field_1 (temp, bitsize, bitnum, 0, 0, fieldmode, value,
                           reverse, fallback_p, undefined_p);
        emit_move_insn (op0, temp);          /* <-- copy back  */
        return true;
      }
    else
      op0 = gen_lowpart (op0_mode.require (), op0);   /* <-- no copy back  */
  }

return store_integral_bit_field (op0, op0_mode, ibitsize, ibitnum,
                                 bitregion_start, bitregion_end,
                                 fieldmode, value, reverse, fallback_p);
```

When `gen_lowpart` returns a fresh register (because the source mode
cannot be reinterpreted into the chosen integral mode via a valid
subreg), `store_integral_bit_field` writes the inserted value into
that fresh register.  The caller's `str_rtx` is never updated, so the
insertion is silently dropped.

The sibling `!op0_mode.exists()` branch already performs the
analogous copy-back via the stack-temp pattern (the final
`emit_move_insn (op0, temp)`).  The `gen_lowpart` branch is missing
that copy-back.

Suggested fix:

Mirror the stack-temp branch's copy-back at the end of
`store_bit_field_1`: after `store_integral_bit_field` returns, if the
register reached via `op0` differs from the one reached via
`str_rtx`, copy the value back into `str_rtx`.

Reply via email to