Hi Robin, > Hi Jin, > > > --- a/gcc/config/riscv/riscv-v.cc > > +++ b/gcc/config/riscv/riscv-v.cc > > @@ -1883,6 +1883,19 @@ legitimize_move (rtx dest, rtx *srcp) > > return true; > > } > > > > + /* A SUBREG of a constant is not a valid vector move operand. Force the > > + inner constant into a register and rebuild the SUBREG. */ > > If it's not a valid move operand, how do we get here? Is (subreg:V2SI > (symbol_ref ...)) even valid RTL? > > -- > Regards > Robin
Thank you for the review. This expression comes from store_bit_field_1. For the equal-sized mode pun here, store_bit_field_1 calls force_subreg (V2SImode, symbol_ref:DI, DImode, 0). force_subreg first tries simplify_gen_subreg. The latter allows SYMBOL_REF, CONST, and LABEL_REF inside a SUBREG. validate_subreg also accepts the equal-sized modes and zero offset in this case. Therefore, force_subreg returns the SUBREG directly instead of materializing the inner constant in a register. emit_move_insn then invokes the movV2SI expander directly through mov_optab. The operand is not checked against general_operand before the expander is called, so it reaches riscv_vector::legitimize_move. The same approach is used by ix86_expand_vector_move (see https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=6a20b538f2a02e01b311af1dade9cea6a58d815e , PR middle-end/71626): materialize SUBREG_REG first and then rebuild the SUBREG. More precisely, the expression can be constructed by the current validate_subreg and simplify_gen_subreg and used as a temporary input to a move expander. However, it is not a general_operand and cannot remain in a final move insn. legitimize_move legalizes it before emitting the final move. My comment might not have made this clear. A more precise comment would be the following, and I can update it later if needed: /* store_bit_field can pass an unfoldable SUBREG of a constant to a move expander. Materialize the inner constant in a register and rebuild the SUBREG. */ Thanks, Jin
