Matthew Fortune writes: > > That's not what I hoped but is what I was concerned about as I believe it > means we have a change of behaviour. It boils down to simply ignoring the > argument type of unsigned char. My guess is that a zero extension is > created but then immediately eliminated because of the paradoxical subreg. > > I think you need to create a temporary and perform the zero extension to > ensure we honour the unsigned char operand: > > rtx new_dst = gen_reg_rtx (SImode); > emit_insn (gen_zero_extendqisi2 (new_dst, ops[2].value)); > ops[2].value = foo; > > This should mean that the testcase I sent always has a zero extension but if > you change the type of 'amount' to be unsigned char then there should not be > a zero extension as the argument will be assumed to be correctly zero extended > already and the explicitly introduced zero_extend will be eliminated. >
I have made it generate a zero_extend instead of a SUBREG. However, the pattern associated with gen_zero_extendqisi2 does not work with immediate operands, so I had to add an extra step in which the argument is put into a QImode register before being passed to gen_zero_extendqisi2. Is this OK ? Regards, Toma gcc/ * config/mips/mips.c (mips_expand_builtin_insn): Convert the QImode argument of the pshufh, psllh, psllw, psrah, psraw, psrlh, psrlw builtins to SImode and emit a zero-extend, if necessary. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index da7fa8f..bab5b93 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -16571,9 +16571,35 @@ mips_expand_builtin_insn (enum insn_code icode, unsigned int nops, { machine_mode imode; int rangelo = 0, rangehi = 0, error_opno = 0; + rtx qireg, sireg; switch (icode) { + /* The third operand of these instructions is in SImode, so we need to + bring the corresponding builtin argument from QImode into SImode. */ + case CODE_FOR_loongson_pshufh: + case CODE_FOR_loongson_psllh: + case CODE_FOR_loongson_psllw: + case CODE_FOR_loongson_psrah: + case CODE_FOR_loongson_psraw: + case CODE_FOR_loongson_psrlh: + case CODE_FOR_loongson_psrlw: + gcc_assert (has_target_p && nops == 3 && ops[2].mode == QImode); + sireg = gen_reg_rtx (SImode); + /* We need to put the immediate in a register because + gen_zero_extendqisi2 does not accept immediate operands. */ + if (CONST_INT_P (ops[2].value)) + { + qireg = gen_reg_rtx (QImode); + emit_insn (gen_rtx_SET (qireg, ops[2].value)); + emit_insn (gen_zero_extendqisi2 (sireg, qireg)); + } else { + emit_insn (gen_zero_extendqisi2 (sireg, ops[2].value)); + } + ops[2].value = sireg; + ops[2].mode = SImode; + break; + case CODE_FOR_msa_addvi_b: case CODE_FOR_msa_addvi_h: case CODE_FOR_msa_addvi_w: