diff --git a/gcc/config/mips/mips-msa.md b/gcc/config/mips/mips-msa.md index 3a67f25be56..d3b27d132ad 100644 --- a/gcc/config/mips/mips-msa.md +++ b/gcc/config/mips/mips-msa.md @@ -870,9 +870,12 @@ (match_operand:IMSA 1 "register_operand" "f,f") (match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))] "ISA_HAS_MSA" - "@ - srl.\t%w0,%w1,%w2 - srli.\t%w0,%w1,%E2" +{ + if (which_alternative == 0) + return "srl.\t%w0,%w1,%w2"; + + return mips_msa_output_shift_immediate("srli.\t%w0,%w1,%E2", operands); +} [(set_attr "type" "simd_shift") (set_attr "mode" "")]) @@ -882,9 +885,12 @@ (match_operand:IMSA 1 "register_operand" "f,f") (match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))] "ISA_HAS_MSA" - "@ - sra.\t%w0,%w1,%w2 - srai.\t%w0,%w1,%E2" +{ + if (which_alternative == 0) + return "sra.\t%w0,%w1,%w2"; + + return mips_msa_output_shift_immediate("srai.\t%w0,%w1,%E2", operands); +} [(set_attr "type" "simd_shift") (set_attr "mode" "")]) @@ -894,9 +900,12 @@ (match_operand:IMSA 1 "register_operand" "f,f") (match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))] "ISA_HAS_MSA" - "@ - sll.\t%w0,%w1,%w2 - slli.\t%w0,%w1,%E2" +{ + if (which_alternative == 0) + return "sll.\t%w0,%w1,%w2"; + + return mips_msa_output_shift_immediate("slli.\t%w0,%w1,%E2", operands); +} [(set_attr "type" "simd_shift") (set_attr "mode" "")]) diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index a5e4151b9e6..8d97eb36125 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -317,6 +317,7 @@ extern const char *mips_output_sync_loop (rtx_insn *, rtx *); extern unsigned int mips_sync_loop_insns (rtx_insn *, rtx *); extern const char *mips_output_division (const char *, rtx *); extern const char *mips_msa_output_division (const char *, rtx *); +extern const char *mips_msa_output_shift_immediate (const char *, rtx *); extern const char *mips_output_probe_stack_range (rtx, rtx); extern bool mips_hard_regno_rename_ok (unsigned int, unsigned int); extern bool mips_linked_madd_p (rtx_insn *, rtx_insn *); diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 39666d6973f..2f7ffe846d8 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -14459,6 +14459,27 @@ mips_msa_output_division (const char *division, rtx *operands) } return s; } + +/* Return the assembly code for MSA immediate shift instructions, + which has the operands given by OPERANDS. Truncate the shift amount + to make GAS happy. */ + +const char * +mips_msa_output_shift_immediate (const char *shift, rtx *operands) +{ + rtx amount = operands[2]; + machine_mode mode = amount->mode; + + unsigned val = UINTVAL (CONST_VECTOR_ELT (amount, 0)); + val &= GET_MODE_UNIT_BITSIZE (mode) - 1; + if (!val) + return ""; + + rtx c = gen_int_mode (val, GET_MODE_INNER (mode)); + operands[2] = gen_const_vec_duplicate (mode, c); + + return shift; +} /* Return true if destination of IN_INSN is used as add source in OUT_INSN. Both IN_INSN and OUT_INSN are of type fmadd. Example: diff --git a/gcc/testsuite/gcc.target/mips/pr101922.c b/gcc/testsuite/gcc.target/mips/pr101922.c new file mode 100644 index 00000000000..00a6e495ba2 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/pr101922.c @@ -0,0 +1,19 @@ +/* PR target/101922 + This was triggering an assembler error with -O3 -mmsa -mloongson-mmi. */ + +/* { dg-do assemble } */ +/* { dg-options "-mmsa -mloongson-mmi" } */ + +typedef __INT8_TYPE__ i8; +typedef __INT32_TYPE__ i32; + +i8 d[16]; + +i32 f(i32 x) { + int i; + for (i = 0; i < 16; i++) { + i32 t = (i32) d[i] >> 31; + x &= t; + } + return x; +}