diff mbox series

[v2,MIPS] Fix handling of MSA SUBREG moves on big-endian targets

Message ID 1567498586-30858-1-git-send-email-mihailo.stojanovic@rt-rk.com
State New
Headers show
Series [v2,MIPS] Fix handling of MSA SUBREG moves on big-endian targets | expand

Commit Message

Mihailo Stojanovic Sept. 3, 2019, 8:16 a.m. UTC
From: Mihailo Stojanovic <mistojanovic@wavecomp.com>

Hi everybody,

This fixes the MSA implementation on big-endian targets which is
essentially broken for things like SUBREG handling and calling
convention for vector types. It borrows heavily from [1] as Aarch64 has
the same problem with SVE vectors.

Conceptually, register bitconverts should act as the data has been
stored to memory in one mode, and loaded from memory in the other.
This isn't what happens on big-endian as vector load/store instructions
are essentially mixed-endian with respect to the vector as a whole.
The in-register representation of data must be changed so that the
load/store round-trip becomes valid. This is done by inserting one or
two shuffle instructions for every SUBREG move, as previously
implemented in [2] for LLVM. Even if the shuffle instructions weren't
generated, constraint in mips_can_change_mode_class would force the
conceptual memory reload of SUBREG move operand, which would generate
correct, albeit very inefficient code.

New msa_reg_predicate was created in order to forbid SUBREG operands in
MSA patterns on big-endian targets. It weeds SUBREGs out of the
instruction patterns into SUBREG->REG moves which are caught by the new
msa_mov<mode>_subreg_be pattern and transformed into shuffle(s).

As for the MSA calling convention, ABI states that compiling for MSA
should not change the base ABIs vector calling convention, that is, MSA
vectors passed or returned by value do not use the MSA vector registers.
Instead, they are passed by general-purpose registers, as described by
the ABI. Passing the vector argument requires splitting it into 2 (or 4)
general-purpose registers and bitconverting it into V2DImode (or
V4SImode). The solution boils down to the one presented for SUBREG
moves: force every vector argument to the appropriate mode (V2DI or
V4SI) so that the shuffle instruction(s) might be generated in order to
conform to the calling convention. The same applies to vectors as return
values.

New testcases were added (thanks Dragan!) to check calling convention
compliance for all possible combinations of MSA and non-MSA
interlinking.

This fixes the following vectorization test failures:

    vect/pr66251.c
    vect/vect-alias-check-10.c
    vect/vect-alias-check-11.c
    vect/vect-alias-check-12.c
    vect/vect-bswap32.c
    vect/vect-bswap64.c
    vect/vect-nop-move.c
    vect/slp-41.c
    vect/slp-43.c
    vect/slp-45.c
    vect/slp-perm-11.c

Tested on mips32-mti-linux-gnu and mips64-mti-linux-gnu.

Regards,
Mihailo

[1] https://gcc.gnu.org/ml/gcc-patches/2018-01/msg02176.html
[2] https://reviews.llvm.org/rL189330

gcc/ChangeLog:

2019-08-08  Mihailo Stojanovic  <mihailo.stojanovic@rt-rk.com>

    * config/mips/mips-msa.md: Replace register_operand predicate with
    msa_reg_operand in every pattern.
    (msa_change_mode): New pattern.
    (*msa_change_mode_<mode>): New unspec.
    (*msa_mov<mode>_subreg_be): New unspec.
    * config/mips/mips-protos.h (mips_split_msa_subreg_move): Declare.
    * config/mips/mips.c (mips_maybe_expand_msa_subreg_move): New
    function.
    (mips_replace_reg_mode): Ditto.
    (mips_split_msa_subreg_move): Ditto.
    (mips_legitimize_move): Modify machine modes of MSA vectors which
    reside in general-purpose registers. Check whether SUBREG move can
    be replaced with shuffle(s).
    (mips_split_128bit_move): Replace new SUBREGs with REGs.
    (mips_split_msa_copy_d): Ditto.
    (mips_split_msa_insert_d): Ditto.
    (mips_split_msa_fill_d): Ditto.
    (mips_can_change_mode_class): Disallow mode change which would
    result in lane width change.
    (mips_expand_vec_unpack): Replace new SUBREG with REG on big-endian
    targets.
    * config/mips/predicates.md (msa_reg_operand): New predicate.

gcc/testsuite/ChangeLog:

2019-08-08  Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>

    * gcc.target/mips/inter/msa-inter.exp: New file.
    * gcc.target/mips/inter/msa_1.h: New test.
    * gcc.target/mips/inter/msa_1_main.c: New test.
    * gcc.target/mips/inter/msa_1_x.c: New test.
    * gcc.target/mips/inter/msa_1_y.c: New test.
---
 gcc/config/mips/mips-msa.md                       | 1026 +++++++++++----------
 gcc/config/mips/mips-protos.h                     |    2 +
 gcc/config/mips/mips.c                            |  166 +++-
 gcc/config/mips/predicates.md                     |    5 +
 gcc/testsuite/gcc.target/mips/inter/msa-inter.exp |   67 ++
 gcc/testsuite/gcc.target/mips/inter/msa_1.h       |   23 +
 gcc/testsuite/gcc.target/mips/inter/msa_1_main.c  |    8 +
 gcc/testsuite/gcc.target/mips/inter/msa_1_x.c     |   35 +
 gcc/testsuite/gcc.target/mips/inter/msa_1_y.c     |   14 +
 9 files changed, 849 insertions(+), 497 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/inter/msa-inter.exp
 create mode 100644 gcc/testsuite/gcc.target/mips/inter/msa_1.h
 create mode 100644 gcc/testsuite/gcc.target/mips/inter/msa_1_main.c
 create mode 100644 gcc/testsuite/gcc.target/mips/inter/msa_1_x.c
 create mode 100644 gcc/testsuite/gcc.target/mips/inter/msa_1_y.c

Comments

Jeff Law Sept. 3, 2019, 7:16 p.m. UTC | #1
On 9/3/19 2:16 AM, Mihailo Stojanovic wrote:
> From: Mihailo Stojanovic <mistojanovic@wavecomp.com>
> 
> Hi everybody,
> 
> This fixes the MSA implementation on big-endian targets which is
> essentially broken for things like SUBREG handling and calling
> convention for vector types. It borrows heavily from [1] as Aarch64 has
> the same problem with SVE vectors.
> 
> Conceptually, register bitconverts should act as the data has been
> stored to memory in one mode, and loaded from memory in the other.
> This isn't what happens on big-endian as vector load/store instructions
> are essentially mixed-endian with respect to the vector as a whole.
> The in-register representation of data must be changed so that the
> load/store round-trip becomes valid. This is done by inserting one or
> two shuffle instructions for every SUBREG move, as previously
> implemented in [2] for LLVM. Even if the shuffle instructions weren't
> generated, constraint in mips_can_change_mode_class would force the
> conceptual memory reload of SUBREG move operand, which would generate
> correct, albeit very inefficient code.
> 
> New msa_reg_predicate was created in order to forbid SUBREG operands in
> MSA patterns on big-endian targets. It weeds SUBREGs out of the
> instruction patterns into SUBREG->REG moves which are caught by the new
> msa_mov<mode>_subreg_be pattern and transformed into shuffle(s).
> 
> As for the MSA calling convention, ABI states that compiling for MSA
> should not change the base ABIs vector calling convention, that is, MSA
> vectors passed or returned by value do not use the MSA vector registers.
> Instead, they are passed by general-purpose registers, as described by
> the ABI. Passing the vector argument requires splitting it into 2 (or 4)
> general-purpose registers and bitconverting it into V2DImode (or
> V4SImode). The solution boils down to the one presented for SUBREG
> moves: force every vector argument to the appropriate mode (V2DI or
> V4SI) so that the shuffle instruction(s) might be generated in order to
> conform to the calling convention. The same applies to vectors as return
> values.
> 
> New testcases were added (thanks Dragan!) to check calling convention
> compliance for all possible combinations of MSA and non-MSA
> interlinking.
> 
> This fixes the following vectorization test failures:
> 
>     vect/pr66251.c
>     vect/vect-alias-check-10.c
>     vect/vect-alias-check-11.c
>     vect/vect-alias-check-12.c
>     vect/vect-bswap32.c
>     vect/vect-bswap64.c
>     vect/vect-nop-move.c
>     vect/slp-41.c
>     vect/slp-43.c
>     vect/slp-45.c
>     vect/slp-perm-11.c
> 
> Tested on mips32-mti-linux-gnu and mips64-mti-linux-gnu.
> 
> Regards,
> Mihailo
> 
> [1] https://gcc.gnu.org/ml/gcc-patches/2018-01/msg02176.html
> [2] https://reviews.llvm.org/rL189330
> 
> gcc/ChangeLog:
> 
> 2019-08-08  Mihailo Stojanovic  <mihailo.stojanovic@rt-rk.com>
> 
>     * config/mips/mips-msa.md: Replace register_operand predicate with
>     msa_reg_operand in every pattern.
>     (msa_change_mode): New pattern.
>     (*msa_change_mode_<mode>): New unspec.
>     (*msa_mov<mode>_subreg_be): New unspec.
>     * config/mips/mips-protos.h (mips_split_msa_subreg_move): Declare.
>     * config/mips/mips.c (mips_maybe_expand_msa_subreg_move): New
>     function.
>     (mips_replace_reg_mode): Ditto.
>     (mips_split_msa_subreg_move): Ditto.
>     (mips_legitimize_move): Modify machine modes of MSA vectors which
>     reside in general-purpose registers. Check whether SUBREG move can
>     be replaced with shuffle(s).
>     (mips_split_128bit_move): Replace new SUBREGs with REGs.
>     (mips_split_msa_copy_d): Ditto.
>     (mips_split_msa_insert_d): Ditto.
>     (mips_split_msa_fill_d): Ditto.
>     (mips_can_change_mode_class): Disallow mode change which would
>     result in lane width change.
>     (mips_expand_vec_unpack): Replace new SUBREG with REG on big-endian
>     targets.
>     * config/mips/predicates.md (msa_reg_operand): New predicate.
> 
> gcc/testsuite/ChangeLog:
> 
> 2019-08-08  Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
> 
>     * gcc.target/mips/inter/msa-inter.exp: New file.
>     * gcc.target/mips/inter/msa_1.h: New test.
>     * gcc.target/mips/inter/msa_1_main.c: New test.
>     * gcc.target/mips/inter/msa_1_x.c: New test.
>     * gcc.target/mips/inter/msa_1_y.c: New test.
I don't guess Richard S's proposed cleanups to the generic handling of
SUBREGs to address issues with SVE really help here.

I suspect you're going to need to define secondary reloads here much
like the aarch64 port does.  See aarch64_secondary_reload.

I suspect you also need to twiddle mips_can_change_mode_class.

Unrelated, we should probably get you authenticated access to the source
tree so that you can commit changes as they're approved.

https://sourceware.org/cgi-bin/pdw/ps_form.cgi




Presumably TARGET_CAN_CHANGE_MODE_CLASS is properly defined

Typically this would be handled via TARGET_CAN_CHANGE_MODE_CLASS and
Richard Sandiford Sept. 4, 2019, 9:35 a.m. UTC | #2
Jeff Law <law@redhat.com> writes:
> On 9/3/19 2:16 AM, Mihailo Stojanovic wrote:
>> From: Mihailo Stojanovic <mistojanovic@wavecomp.com>
>> 
>> Hi everybody,
>> 
>> This fixes the MSA implementation on big-endian targets which is
>> essentially broken for things like SUBREG handling and calling
>> convention for vector types. It borrows heavily from [1] as Aarch64 has
>> the same problem with SVE vectors.
>> 
>> Conceptually, register bitconverts should act as the data has been
>> stored to memory in one mode, and loaded from memory in the other.
>> This isn't what happens on big-endian as vector load/store instructions
>> are essentially mixed-endian with respect to the vector as a whole.
>> The in-register representation of data must be changed so that the
>> load/store round-trip becomes valid. This is done by inserting one or
>> two shuffle instructions for every SUBREG move, as previously
>> implemented in [2] for LLVM. Even if the shuffle instructions weren't
>> generated, constraint in mips_can_change_mode_class would force the
>> conceptual memory reload of SUBREG move operand, which would generate
>> correct, albeit very inefficient code.
>> 
>> New msa_reg_predicate was created in order to forbid SUBREG operands in
>> MSA patterns on big-endian targets. It weeds SUBREGs out of the
>> instruction patterns into SUBREG->REG moves which are caught by the new
>> msa_mov<mode>_subreg_be pattern and transformed into shuffle(s).
>> 
>> As for the MSA calling convention, ABI states that compiling for MSA
>> should not change the base ABIs vector calling convention, that is, MSA
>> vectors passed or returned by value do not use the MSA vector registers.
>> Instead, they are passed by general-purpose registers, as described by
>> the ABI. Passing the vector argument requires splitting it into 2 (or 4)
>> general-purpose registers and bitconverting it into V2DImode (or
>> V4SImode). The solution boils down to the one presented for SUBREG
>> moves: force every vector argument to the appropriate mode (V2DI or
>> V4SI) so that the shuffle instruction(s) might be generated in order to
>> conform to the calling convention. The same applies to vectors as return
>> values.
>> 
>> New testcases were added (thanks Dragan!) to check calling convention
>> compliance for all possible combinations of MSA and non-MSA
>> interlinking.
>> 
>> This fixes the following vectorization test failures:
>> 
>>     vect/pr66251.c
>>     vect/vect-alias-check-10.c
>>     vect/vect-alias-check-11.c
>>     vect/vect-alias-check-12.c
>>     vect/vect-bswap32.c
>>     vect/vect-bswap64.c
>>     vect/vect-nop-move.c
>>     vect/slp-41.c
>>     vect/slp-43.c
>>     vect/slp-45.c
>>     vect/slp-perm-11.c
>> 
>> Tested on mips32-mti-linux-gnu and mips64-mti-linux-gnu.
>> 
>> Regards,
>> Mihailo
>> 
>> [1] https://gcc.gnu.org/ml/gcc-patches/2018-01/msg02176.html
>> [2] https://reviews.llvm.org/rL189330
>> 
>> gcc/ChangeLog:
>> 
>> 2019-08-08  Mihailo Stojanovic  <mihailo.stojanovic@rt-rk.com>
>> 
>>     * config/mips/mips-msa.md: Replace register_operand predicate with
>>     msa_reg_operand in every pattern.
>>     (msa_change_mode): New pattern.
>>     (*msa_change_mode_<mode>): New unspec.
>>     (*msa_mov<mode>_subreg_be): New unspec.
>>     * config/mips/mips-protos.h (mips_split_msa_subreg_move): Declare.
>>     * config/mips/mips.c (mips_maybe_expand_msa_subreg_move): New
>>     function.
>>     (mips_replace_reg_mode): Ditto.
>>     (mips_split_msa_subreg_move): Ditto.
>>     (mips_legitimize_move): Modify machine modes of MSA vectors which
>>     reside in general-purpose registers. Check whether SUBREG move can
>>     be replaced with shuffle(s).
>>     (mips_split_128bit_move): Replace new SUBREGs with REGs.
>>     (mips_split_msa_copy_d): Ditto.
>>     (mips_split_msa_insert_d): Ditto.
>>     (mips_split_msa_fill_d): Ditto.
>>     (mips_can_change_mode_class): Disallow mode change which would
>>     result in lane width change.
>>     (mips_expand_vec_unpack): Replace new SUBREG with REG on big-endian
>>     targets.
>>     * config/mips/predicates.md (msa_reg_operand): New predicate.
>> 
>> gcc/testsuite/ChangeLog:
>> 
>> 2019-08-08  Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
>> 
>>     * gcc.target/mips/inter/msa-inter.exp: New file.
>>     * gcc.target/mips/inter/msa_1.h: New test.
>>     * gcc.target/mips/inter/msa_1_main.c: New test.
>>     * gcc.target/mips/inter/msa_1_x.c: New test.
>>     * gcc.target/mips/inter/msa_1_y.c: New test.
> I don't guess Richard S's proposed cleanups to the generic handling of
> SUBREGs to address issues with SVE really help here.

Sorry, haven't applied that patch yet -- need to find time to retest.

But yeah, I don't think my patch will help.  For something like this
I think we'd need target hooks to control the subreg layout in registers.
Sounds like it should be doable, but probably quite tricky.

Thanks,
Richard
Mihailo Stojanovic Sept. 4, 2019, 1:12 p.m. UTC | #3
Hello,

On 3.9.19. 21:16, Jeff Law wrote:
> On 9/3/19 2:16 AM, Mihailo Stojanovic wrote:
>> From: Mihailo Stojanovic <mistojanovic@wavecomp.com>
>>
>> Hi everybody,
>>
>> This fixes the MSA implementation on big-endian targets which is
>> essentially broken for things like SUBREG handling and calling
>> convention for vector types. It borrows heavily from [1] as Aarch64 has
>> the same problem with SVE vectors.
>>
>> Conceptually, register bitconverts should act as the data has been
>> stored to memory in one mode, and loaded from memory in the other.
>> This isn't what happens on big-endian as vector load/store instructions
>> are essentially mixed-endian with respect to the vector as a whole.
>> The in-register representation of data must be changed so that the
>> load/store round-trip becomes valid. This is done by inserting one or
>> two shuffle instructions for every SUBREG move, as previously
>> implemented in [2] for LLVM. Even if the shuffle instructions weren't
>> generated, constraint in mips_can_change_mode_class would force the
>> conceptual memory reload of SUBREG move operand, which would generate
>> correct, albeit very inefficient code.
>>
>> New msa_reg_predicate was created in order to forbid SUBREG operands in
>> MSA patterns on big-endian targets. It weeds SUBREGs out of the
>> instruction patterns into SUBREG->REG moves which are caught by the new
>> msa_mov<mode>_subreg_be pattern and transformed into shuffle(s).
>>
>> As for the MSA calling convention, ABI states that compiling for MSA
>> should not change the base ABIs vector calling convention, that is, MSA
>> vectors passed or returned by value do not use the MSA vector registers.
>> Instead, they are passed by general-purpose registers, as described by
>> the ABI. Passing the vector argument requires splitting it into 2 (or 4)
>> general-purpose registers and bitconverting it into V2DImode (or
>> V4SImode). The solution boils down to the one presented for SUBREG
>> moves: force every vector argument to the appropriate mode (V2DI or
>> V4SI) so that the shuffle instruction(s) might be generated in order to
>> conform to the calling convention. The same applies to vectors as return
>> values.
>>
>> New testcases were added (thanks Dragan!) to check calling convention
>> compliance for all possible combinations of MSA and non-MSA
>> interlinking.
>>
>> This fixes the following vectorization test failures:
>>
>>      vect/pr66251.c
>>      vect/vect-alias-check-10.c
>>      vect/vect-alias-check-11.c
>>      vect/vect-alias-check-12.c
>>      vect/vect-bswap32.c
>>      vect/vect-bswap64.c
>>      vect/vect-nop-move.c
>>      vect/slp-41.c
>>      vect/slp-43.c
>>      vect/slp-45.c
>>      vect/slp-perm-11.c
>>
>> Tested on mips32-mti-linux-gnu and mips64-mti-linux-gnu.
>>
>> Regards,
>> Mihailo
>>
>> [1] https://gcc.gnu.org/ml/gcc-patches/2018-01/msg02176.html
>> [2] https://reviews.llvm.org/rL189330
>>
>> gcc/ChangeLog:
>>
>> 2019-08-08  Mihailo Stojanovic  <mihailo.stojanovic@rt-rk.com>
>>
>>      * config/mips/mips-msa.md: Replace register_operand predicate with
>>      msa_reg_operand in every pattern.
>>      (msa_change_mode): New pattern.
>>      (*msa_change_mode_<mode>): New unspec.
>>      (*msa_mov<mode>_subreg_be): New unspec.
>>      * config/mips/mips-protos.h (mips_split_msa_subreg_move): Declare.
>>      * config/mips/mips.c (mips_maybe_expand_msa_subreg_move): New
>>      function.
>>      (mips_replace_reg_mode): Ditto.
>>      (mips_split_msa_subreg_move): Ditto.
>>      (mips_legitimize_move): Modify machine modes of MSA vectors which
>>      reside in general-purpose registers. Check whether SUBREG move can
>>      be replaced with shuffle(s).
>>      (mips_split_128bit_move): Replace new SUBREGs with REGs.
>>      (mips_split_msa_copy_d): Ditto.
>>      (mips_split_msa_insert_d): Ditto.
>>      (mips_split_msa_fill_d): Ditto.
>>      (mips_can_change_mode_class): Disallow mode change which would
>>      result in lane width change.
>>      (mips_expand_vec_unpack): Replace new SUBREG with REG on big-endian
>>      targets.
>>      * config/mips/predicates.md (msa_reg_operand): New predicate.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 2019-08-08  Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
>>
>>      * gcc.target/mips/inter/msa-inter.exp: New file.
>>      * gcc.target/mips/inter/msa_1.h: New test.
>>      * gcc.target/mips/inter/msa_1_main.c: New test.
>>      * gcc.target/mips/inter/msa_1_x.c: New test.
>>      * gcc.target/mips/inter/msa_1_y.c: New test.
> I don't guess Richard S's proposed cleanups to the generic handling of
> SUBREGs to address issues with SVE really help here.
Could you send a link to the proposed patch?
I can't seem to find it on the mailing list.
> I suspect you're going to need to define secondary reloads here much
> like the aarch64 port does.  See aarch64_secondary_reload
I'm not sure that MSA memory accesses need secondary reloads, as MSA
doesn't have predicated moves. Instead, every memory load and store
is handled by LD.* and ST.* instructions.
> I suspect you also need to twiddle mips_can_change_mode_class.
I've already made changes to mips_can_change_mode_class, to disallow
MSA mode change which results in a lane width change. Maybe you had
something else in mind?

I'm not sure I really understood yours and Richard's suggestions, so I
don't have a clear idea how to proceed with this patch. If you could
elaborate a bit more I would be grateful.

Thanks,
Mihailo
Jeff Law Sept. 4, 2019, 2:54 p.m. UTC | #4
On 9/4/19 3:35 AM, Richard Sandiford wrote:
> Jeff Law <law@redhat.com> writes:
>> On 9/3/19 2:16 AM, Mihailo Stojanovic wrote:
>>> From: Mihailo Stojanovic <mistojanovic@wavecomp.com>
>>>
>>> Hi everybody,
>>>
>>> This fixes the MSA implementation on big-endian targets which is
>>> essentially broken for things like SUBREG handling and calling
>>> convention for vector types. It borrows heavily from [1] as Aarch64 has
>>> the same problem with SVE vectors.
>>>
>>> Conceptually, register bitconverts should act as the data has been
>>> stored to memory in one mode, and loaded from memory in the other.
>>> This isn't what happens on big-endian as vector load/store instructions
>>> are essentially mixed-endian with respect to the vector as a whole.
>>> The in-register representation of data must be changed so that the
>>> load/store round-trip becomes valid. This is done by inserting one or
>>> two shuffle instructions for every SUBREG move, as previously
>>> implemented in [2] for LLVM. Even if the shuffle instructions weren't
>>> generated, constraint in mips_can_change_mode_class would force the
>>> conceptual memory reload of SUBREG move operand, which would generate
>>> correct, albeit very inefficient code.
>>>
>>> New msa_reg_predicate was created in order to forbid SUBREG operands in
>>> MSA patterns on big-endian targets. It weeds SUBREGs out of the
>>> instruction patterns into SUBREG->REG moves which are caught by the new
>>> msa_mov<mode>_subreg_be pattern and transformed into shuffle(s).
>>>
>>> As for the MSA calling convention, ABI states that compiling for MSA
>>> should not change the base ABIs vector calling convention, that is, MSA
>>> vectors passed or returned by value do not use the MSA vector registers.
>>> Instead, they are passed by general-purpose registers, as described by
>>> the ABI. Passing the vector argument requires splitting it into 2 (or 4)
>>> general-purpose registers and bitconverting it into V2DImode (or
>>> V4SImode). The solution boils down to the one presented for SUBREG
>>> moves: force every vector argument to the appropriate mode (V2DI or
>>> V4SI) so that the shuffle instruction(s) might be generated in order to
>>> conform to the calling convention. The same applies to vectors as return
>>> values.
>>>
>>> New testcases were added (thanks Dragan!) to check calling convention
>>> compliance for all possible combinations of MSA and non-MSA
>>> interlinking.
>>>
>>> This fixes the following vectorization test failures:
>>>
>>>     vect/pr66251.c
>>>     vect/vect-alias-check-10.c
>>>     vect/vect-alias-check-11.c
>>>     vect/vect-alias-check-12.c
>>>     vect/vect-bswap32.c
>>>     vect/vect-bswap64.c
>>>     vect/vect-nop-move.c
>>>     vect/slp-41.c
>>>     vect/slp-43.c
>>>     vect/slp-45.c
>>>     vect/slp-perm-11.c
>>>
>>> Tested on mips32-mti-linux-gnu and mips64-mti-linux-gnu.
>>>
>>> Regards,
>>> Mihailo
>>>
>>> [1] https://gcc.gnu.org/ml/gcc-patches/2018-01/msg02176.html
>>> [2] https://reviews.llvm.org/rL189330
>>>
>>> gcc/ChangeLog:
>>>
>>> 2019-08-08  Mihailo Stojanovic  <mihailo.stojanovic@rt-rk.com>
>>>
>>>     * config/mips/mips-msa.md: Replace register_operand predicate with
>>>     msa_reg_operand in every pattern.
>>>     (msa_change_mode): New pattern.
>>>     (*msa_change_mode_<mode>): New unspec.
>>>     (*msa_mov<mode>_subreg_be): New unspec.
>>>     * config/mips/mips-protos.h (mips_split_msa_subreg_move): Declare.
>>>     * config/mips/mips.c (mips_maybe_expand_msa_subreg_move): New
>>>     function.
>>>     (mips_replace_reg_mode): Ditto.
>>>     (mips_split_msa_subreg_move): Ditto.
>>>     (mips_legitimize_move): Modify machine modes of MSA vectors which
>>>     reside in general-purpose registers. Check whether SUBREG move can
>>>     be replaced with shuffle(s).
>>>     (mips_split_128bit_move): Replace new SUBREGs with REGs.
>>>     (mips_split_msa_copy_d): Ditto.
>>>     (mips_split_msa_insert_d): Ditto.
>>>     (mips_split_msa_fill_d): Ditto.
>>>     (mips_can_change_mode_class): Disallow mode change which would
>>>     result in lane width change.
>>>     (mips_expand_vec_unpack): Replace new SUBREG with REG on big-endian
>>>     targets.
>>>     * config/mips/predicates.md (msa_reg_operand): New predicate.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> 2019-08-08  Dragan Mladjenovic  <dragan.mladjenovic@rt-rk.com>
>>>
>>>     * gcc.target/mips/inter/msa-inter.exp: New file.
>>>     * gcc.target/mips/inter/msa_1.h: New test.
>>>     * gcc.target/mips/inter/msa_1_main.c: New test.
>>>     * gcc.target/mips/inter/msa_1_x.c: New test.
>>>     * gcc.target/mips/inter/msa_1_y.c: New test.
>> I don't guess Richard S's proposed cleanups to the generic handling of
>> SUBREGs to address issues with SVE really help here.
> 
> Sorry, haven't applied that patch yet -- need to find time to retest.
ACK.  ISTM that getting it in this week or waiting until after Cauldron
would be best.   Obviously your call.  I'll pass along anything my
tester complains about post-installation.

> 
> But yeah, I don't think my patch will help.  For something like this
> I think we'd need target hooks to control the subreg layout in registers.
> Sounds like it should be doable, but probably quite tricky.
Yea, yours dealt mostly with the simplification side whereas Mihailo
MIPS patch is focused on preventing SUBREGs in many contexts.  I think
the big question is whether or not the historical knobs to prevent mode
changes and the like are sufficient to deal with the cases in question.

jeff
diff mbox series

Patch

diff --git a/gcc/config/mips/mips-msa.md b/gcc/config/mips/mips-msa.md
index 929646d..7dd8fdc 100644
--- a/gcc/config/mips/mips-msa.md
+++ b/gcc/config/mips/mips-msa.md
@@ -90,6 +90,8 @@ 
   UNSPEC_MSA_SUBSUU_S
   UNSPEC_MSA_SUBSUS_U
   UNSPEC_MSA_VSHF
+  UNSPEC_MSA_CHANGE_MODE
+  UNSPEC_MSA_SUBREG_BE
 ])
 
 ;; All vector modes with 128 bits.
@@ -232,7 +234,7 @@ 
    (V2DI  "uimm6")])
 
 (define_expand "vec_init<mode><unitmode>"
-  [(match_operand:MSA 0 "register_operand")
+  [(match_operand:MSA 0 "msa_reg_operand")
    (match_operand:MSA 1 "")]
   "ISA_HAS_MSA"
 {
@@ -242,22 +244,22 @@ 
 
 ;; pckev pattern with implicit type conversion.
 (define_insn "vec_pack_trunc_<mode>"
-   [(set (match_operand:<VHMODE> 0 "register_operand" "=f")
+   [(set (match_operand:<VHMODE> 0 "msa_reg_operand" "=f")
 	 (vec_concat:<VHMODE>
 	   (truncate:<VTRUNCMODE>
-	     (match_operand:IMSA_DWH 1 "register_operand" "f"))
+	     (match_operand:IMSA_DWH 1 "msa_reg_operand" "f"))
 	   (truncate:<VTRUNCMODE>
-	     (match_operand:IMSA_DWH 2 "register_operand" "f"))))]
+	     (match_operand:IMSA_DWH 2 "msa_reg_operand" "f"))))]
   "ISA_HAS_MSA"
   "pckev.<hmsafmt>\t%w0,%w2,%w1"
   [(set_attr "type" "simd_permute")
    (set_attr "mode" "<MODE>")])
 
 (define_expand "vec_unpacks_hi_v4sf"
-  [(set (match_operand:V2DF 0 "register_operand" "=f")
+  [(set (match_operand:V2DF 0 "msa_reg_operand" "=f")
 	(float_extend:V2DF
 	  (vec_select:V2SF
-	    (match_operand:V4SF 1 "register_operand" "f")
+	    (match_operand:V4SF 1 "msa_reg_operand" "f")
 	    (match_dup 2))))]
   "ISA_HAS_MSA"
 {
@@ -265,10 +267,10 @@ 
 })
 
 (define_expand "vec_unpacks_lo_v4sf"
-  [(set (match_operand:V2DF 0 "register_operand" "=f")
+  [(set (match_operand:V2DF 0 "msa_reg_operand" "=f")
 	(float_extend:V2DF
 	  (vec_select:V2SF
-	    (match_operand:V4SF 1 "register_operand" "f")
+	    (match_operand:V4SF 1 "msa_reg_operand" "f")
 	    (match_dup 2))))]
   "ISA_HAS_MSA"
 {
@@ -276,8 +278,8 @@ 
 })
 
 (define_expand "vec_unpacks_hi_<mode>"
-  [(match_operand:<VDMODE> 0 "register_operand")
-   (match_operand:IMSA_WHB 1 "register_operand")]
+  [(match_operand:<VDMODE> 0 "msa_reg_operand")
+   (match_operand:IMSA_WHB 1 "msa_reg_operand")]
   "ISA_HAS_MSA"
 {
   mips_expand_vec_unpack (operands, false/*unsigned_p*/, true/*high_p*/);
@@ -285,8 +287,8 @@ 
 })
 
 (define_expand "vec_unpacks_lo_<mode>"
-  [(match_operand:<VDMODE> 0 "register_operand")
-   (match_operand:IMSA_WHB 1 "register_operand")]
+  [(match_operand:<VDMODE> 0 "msa_reg_operand")
+   (match_operand:IMSA_WHB 1 "msa_reg_operand")]
   "ISA_HAS_MSA"
 {
   mips_expand_vec_unpack (operands, false/*unsigned_p*/, false/*high_p*/);
@@ -294,8 +296,8 @@ 
 })
 
 (define_expand "vec_unpacku_hi_<mode>"
-  [(match_operand:<VDMODE> 0 "register_operand")
-   (match_operand:IMSA_WHB 1 "register_operand")]
+  [(match_operand:<VDMODE> 0 "msa_reg_operand")
+   (match_operand:IMSA_WHB 1 "msa_reg_operand")]
   "ISA_HAS_MSA"
 {
   mips_expand_vec_unpack (operands, true/*unsigned_p*/, true/*high_p*/);
@@ -303,8 +305,8 @@ 
 })
 
 (define_expand "vec_unpacku_lo_<mode>"
-  [(match_operand:<VDMODE> 0 "register_operand")
-   (match_operand:IMSA_WHB 1 "register_operand")]
+  [(match_operand:<VDMODE> 0 "msa_reg_operand")
+   (match_operand:IMSA_WHB 1 "msa_reg_operand")]
   "ISA_HAS_MSA"
 {
   mips_expand_vec_unpack (operands, true/*unsigned_p*/, false/*high_p*/);
@@ -312,8 +314,8 @@ 
 })
 
 (define_expand "vec_extract<mode><unitmode>"
-  [(match_operand:<UNITMODE> 0 "register_operand")
-   (match_operand:IMSA 1 "register_operand")
+  [(match_operand:<UNITMODE> 0 "msa_reg_operand")
+   (match_operand:IMSA 1 "msa_reg_operand")
    (match_operand 2 "const_<indeximm>_operand")]
   "ISA_HAS_MSA"
 {
@@ -330,8 +332,8 @@ 
 })
 
 (define_expand "vec_extract<mode><unitmode>"
-  [(match_operand:<UNITMODE> 0 "register_operand")
-   (match_operand:FMSA 1 "register_operand")
+  [(match_operand:<UNITMODE> 0 "msa_reg_operand")
+   (match_operand:FMSA 1 "msa_reg_operand")
    (match_operand 2 "const_<indeximm>_operand")]
   "ISA_HAS_MSA"
 {
@@ -358,9 +360,9 @@ 
 })
 
 (define_insn_and_split "msa_vec_extract_<msafmt_f>"
-  [(set (match_operand:<UNITMODE> 0 "register_operand" "=f")
+  [(set (match_operand:<UNITMODE> 0 "msa_reg_operand" "=f")
 	(vec_select:<UNITMODE>
-	  (match_operand:FMSA 1 "register_operand" "f")
+	  (match_operand:FMSA 1 "msa_reg_operand" "f")
 	  (parallel [(const_int 0)])))]
   "ISA_HAS_MSA"
   "#"
@@ -384,7 +386,7 @@ 
    (set_attr "mode" "<UNITMODE>")])
 
 (define_expand "vec_set<mode>"
-  [(match_operand:IMSA 0 "register_operand")
+  [(match_operand:IMSA 0 "msa_reg_operand")
    (match_operand:<UNITMODE> 1 "reg_or_0_operand")
    (match_operand 2 "const_<indeximm>_operand")]
   "ISA_HAS_MSA"
@@ -396,8 +398,8 @@ 
 })
 
 (define_expand "vec_set<mode>"
-  [(match_operand:FMSA 0 "register_operand")
-   (match_operand:<UNITMODE> 1 "register_operand")
+  [(match_operand:FMSA 0 "msa_reg_operand")
+   (match_operand:<UNITMODE> 1 "msa_reg_operand")
    (match_operand 2 "const_<indeximm>_operand")]
   "ISA_HAS_MSA"
 {
@@ -408,12 +410,12 @@ 
 })
 
 (define_expand "vcondu<MSA:mode><IMSA:mode>"
-  [(match_operand:MSA 0 "register_operand")
+  [(match_operand:MSA 0 "msa_reg_operand")
    (match_operand:MSA 1 "reg_or_m1_operand")
    (match_operand:MSA 2 "reg_or_0_operand")
    (match_operator 3 ""
-     [(match_operand:IMSA 4 "register_operand")
-      (match_operand:IMSA 5 "register_operand")])]
+     [(match_operand:IMSA 4 "msa_reg_operand")
+      (match_operand:IMSA 5 "msa_reg_operand")])]
   "ISA_HAS_MSA
    && (GET_MODE_NUNITS (<MSA:MODE>mode) == GET_MODE_NUNITS (<IMSA:MODE>mode))"
 {
@@ -422,12 +424,12 @@ 
 })
 
 (define_expand "vcond<MSA:mode><MSA_2:mode>"
-  [(match_operand:MSA 0 "register_operand")
+  [(match_operand:MSA 0 "msa_reg_operand")
    (match_operand:MSA 1 "reg_or_m1_operand")
    (match_operand:MSA 2 "reg_or_0_operand")
    (match_operator 3 ""
-     [(match_operand:MSA_2 4 "register_operand")
-      (match_operand:MSA_2 5 "register_operand")])]
+     [(match_operand:MSA_2 4 "msa_reg_operand")
+      (match_operand:MSA_2 5 "msa_reg_operand")])]
   "ISA_HAS_MSA
    && (GET_MODE_NUNITS (<MSA:MODE>mode) == GET_MODE_NUNITS (<MSA_2:MODE>mode))"
 {
@@ -436,11 +438,11 @@ 
 })
 
 (define_insn "msa_insert_<msafmt_f>"
-  [(set (match_operand:MSA 0 "register_operand" "=f")
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
 	(vec_merge:MSA
 	  (vec_duplicate:MSA
 	    (match_operand:<UNITMODE> 1 "reg_or_0_operand" "dJ"))
-	  (match_operand:MSA 2 "register_operand" "0")
+	  (match_operand:MSA 2 "msa_reg_operand" "0")
 	  (match_operand 3 "const_<bitmask>_operand" "")))]
   "ISA_HAS_MSA"
 {
@@ -453,11 +455,11 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_split
-  [(set (match_operand:MSA_D 0 "register_operand")
+  [(set (match_operand:MSA_D 0 "msa_reg_operand")
 	(vec_merge:MSA_D
 	  (vec_duplicate:MSA_D
 	    (match_operand:<UNITMODE> 1 "<MSA_D:msa_d>_operand"))
-	  (match_operand:MSA_D 2 "register_operand")
+	  (match_operand:MSA_D 2 "msa_reg_operand")
 	  (match_operand 3 "const_<bitmask>_operand")))]
   "reload_completed && ISA_HAS_MSA && !TARGET_64BIT"
   [(const_int 0)]
@@ -467,13 +469,13 @@ 
 })
 
 (define_insn "msa_insve_<msafmt_f>"
-  [(set (match_operand:MSA 0 "register_operand" "=f")
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
 	(vec_merge:MSA
 	  (vec_duplicate:MSA
 	    (vec_select:<UNITMODE>
-	      (match_operand:MSA 1 "register_operand" "f")
+	      (match_operand:MSA 1 "msa_reg_operand" "f")
 	      (parallel [(const_int 0)])))
-	  (match_operand:MSA 2 "register_operand" "0")
+	  (match_operand:MSA 2 "msa_reg_operand" "0")
 	  (match_operand 3 "const_<bitmask>_operand" "")))]
   "ISA_HAS_MSA"
   "insve.<msafmt>\t%w0[%y3],%w1[0]"
@@ -482,11 +484,11 @@ 
 
 ;; Operand 3 is a scalar.
 (define_insn "msa_insve_<msafmt_f>_scalar"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
 	(vec_merge:FMSA
 	  (vec_duplicate:FMSA
-	    (match_operand:<UNITMODE> 1 "register_operand" "f"))
-	  (match_operand:FMSA 2 "register_operand" "0")
+	    (match_operand:<UNITMODE> 1 "msa_reg_operand" "f"))
+	  (match_operand:FMSA 2 "msa_reg_operand" "0")
 	  (match_operand 3 "const_<bitmask>_operand" "")))]
   "ISA_HAS_MSA"
   "insve.<msafmt>\t%w0[%y3],%w1[0]"
@@ -494,10 +496,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_copy_<su>_<msafmt>"
-  [(set (match_operand:<VRES> 0 "register_operand" "=d")
+  [(set (match_operand:<VRES> 0 "msa_reg_operand" "=d")
 	(any_extend:<VRES>
 	  (vec_select:<UNITMODE>
-	    (match_operand:IMSA_HB 1 "register_operand" "f")
+	    (match_operand:IMSA_HB 1 "msa_reg_operand" "f")
 	    (parallel [(match_operand 2 "const_<indeximm>_operand" "")]))))]
   "ISA_HAS_MSA"
   "copy_<su>.<msafmt>\t%0,%w1[%2]"
@@ -505,10 +507,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_copy_u_w"
-  [(set (match_operand:DI 0 "register_operand" "=d")
+  [(set (match_operand:DI 0 "msa_reg_operand" "=d")
 	(zero_extend:DI
 	  (vec_select:SI
-	    (match_operand:V4SI 1 "register_operand" "f")
+	    (match_operand:V4SI 1 "msa_reg_operand" "f")
 	    (parallel [(match_operand 2 "const_0_to_3_operand" "")]))))]
   "ISA_HAS_MSA && TARGET_64BIT"
   "copy_u.w\t%0,%w1[%2]"
@@ -516,10 +518,10 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_copy_s_<msafmt_f>_64bit"
-  [(set (match_operand:DI 0 "register_operand" "=d")
+  [(set (match_operand:DI 0 "msa_reg_operand" "=d")
 	(sign_extend:DI
 	  (vec_select:<UNITMODE>
-	    (match_operand:MSA_W 1 "register_operand" "f")
+	    (match_operand:MSA_W 1 "msa_reg_operand" "f")
 	    (parallel [(match_operand 2 "const_<indeximm>_operand" "")]))))]
   "ISA_HAS_MSA && TARGET_64BIT"
   "copy_s.<msafmt>\t%0,%w1[%2]"
@@ -527,9 +529,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_copy_s_<msafmt_f>"
-  [(set (match_operand:<UNITMODE> 0 "register_operand" "=d")
+  [(set (match_operand:<UNITMODE> 0 "msa_reg_operand" "=d")
 	(vec_select:<UNITMODE>
-	  (match_operand:MSA_W 1 "register_operand" "f")
+	  (match_operand:MSA_W 1 "msa_reg_operand" "f")
 	  (parallel [(match_operand 2 "const_<indeximm>_operand" "")])))]
   "ISA_HAS_MSA"
   "copy_s.<msafmt>\t%0,%w1[%2]"
@@ -537,9 +539,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn_and_split "msa_copy_s_<msafmt_f>"
-  [(set (match_operand:<UNITMODE> 0 "register_operand" "=d")
+  [(set (match_operand:<UNITMODE> 0 "msa_reg_operand" "=d")
 	(vec_select:<UNITMODE>
-	  (match_operand:MSA_D 1 "register_operand" "f")
+	  (match_operand:MSA_D 1 "msa_reg_operand" "f")
 	  (parallel [(match_operand 2 "const_<indeximm>_operand" "")])))]
   "ISA_HAS_MSA"
 {
@@ -559,8 +561,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_expand "abs<mode>2"
-  [(match_operand:IMSA 0 "register_operand" "=f")
-   (abs:IMSA (match_operand:IMSA 1 "register_operand" "f"))]
+  [(match_operand:IMSA 0 "msa_reg_operand" "=f")
+   (abs:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f"))]
   "ISA_HAS_MSA"
 {
   rtx reg = gen_reg_rtx (<MODE>mode);
@@ -570,9 +572,9 @@ 
 })
 
 (define_expand "neg<mode>2"
-  [(set (match_operand:MSA 0 "register_operand")
+  [(set (match_operand:MSA 0 "msa_reg_operand")
 	(minus:MSA (match_dup 2)
-		   (match_operand:MSA 1 "register_operand")))]
+		   (match_operand:MSA 1 "msa_reg_operand")))]
   "ISA_HAS_MSA"
 {
   rtx reg = gen_reg_rtx (<MODE>mode);
@@ -581,7 +583,7 @@ 
 })
 
 (define_expand "msa_ldi<mode>"
-  [(match_operand:IMSA 0 "register_operand")
+  [(match_operand:IMSA 0 "msa_reg_operand")
    (match_operand 1 "const_imm10_operand")]
   "ISA_HAS_MSA"
 {
@@ -594,10 +596,10 @@ 
 })
 
 (define_insn "vec_perm<mode>"
-  [(set (match_operand:MSA 0 "register_operand" "=f")
-	(unspec:MSA [(match_operand:MSA 1 "register_operand" "f")
-		     (match_operand:MSA 2 "register_operand" "f")
-		     (match_operand:<VIMODE> 3 "register_operand" "0")]
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
+	(unspec:MSA [(match_operand:MSA 1 "msa_reg_operand" "f")
+		     (match_operand:MSA 2 "msa_reg_operand" "f")
+		     (match_operand:<VIMODE> 3 "msa_reg_operand" "0")]
 		    UNSPEC_MSA_VSHF))]
   "ISA_HAS_MSA"
   "vshf.<msafmt>\t%w0,%w2,%w1"
@@ -645,7 +647,7 @@ 
 
 ;; Offset load
 (define_expand "msa_ld_<msafmt_f>"
-  [(match_operand:MSA 0 "register_operand")
+  [(match_operand:MSA 0 "msa_reg_operand")
    (match_operand 1 "pmode_register_operand")
    (match_operand 2 "aq10<msafmt>_operand")]
   "ISA_HAS_MSA"
@@ -658,7 +660,7 @@ 
 
 ;; Offset store
 (define_expand "msa_st_<msafmt_f>"
-  [(match_operand:MSA 0 "register_operand")
+  [(match_operand:MSA 0 "msa_reg_operand")
    (match_operand 1 "pmode_register_operand")
    (match_operand 2 "aq10<msafmt>_operand")]
   "ISA_HAS_MSA"
@@ -671,9 +673,9 @@ 
 
 ;; Integer operations
 (define_insn "add<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f,f")
 	(plus:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_ximm5_operand" "f,Unv5,Uuv5")))]
   "ISA_HAS_MSA"
 {
@@ -699,9 +701,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "sub<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
 	(minus:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_uimm5_operand" "f,Uuv5")))]
   "ISA_HAS_MSA"
   "@
@@ -712,74 +714,74 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "mul<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(mult:IMSA (match_operand:IMSA 1 "register_operand" "f")
-		   (match_operand:IMSA 2 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(mult:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+		   (match_operand:IMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "mulv.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_mul")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_maddv_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(plus:IMSA (mult:IMSA (match_operand:IMSA 1 "register_operand" "f")
-			      (match_operand:IMSA 2 "register_operand" "f"))
-		   (match_operand:IMSA 3 "register_operand" "0")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(plus:IMSA (mult:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+			      (match_operand:IMSA 2 "msa_reg_operand" "f"))
+		   (match_operand:IMSA 3 "msa_reg_operand" "0")))]
   "ISA_HAS_MSA"
   "maddv.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_mul")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_msubv_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(minus:IMSA (match_operand:IMSA 1 "register_operand" "0")
-		    (mult:IMSA (match_operand:IMSA 2 "register_operand" "f")
-			       (match_operand:IMSA 3 "register_operand" "f"))))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(minus:IMSA (match_operand:IMSA 1 "msa_reg_operand" "0")
+		    (mult:IMSA (match_operand:IMSA 2 "msa_reg_operand" "f")
+			       (match_operand:IMSA 3 "msa_reg_operand" "f"))))]
   "ISA_HAS_MSA"
   "msubv.<msafmt>\t%w0,%w2,%w3"
   [(set_attr "type" "simd_mul")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "div<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(div:IMSA (match_operand:IMSA 1 "register_operand" "f")
-		  (match_operand:IMSA 2 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(div:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+		  (match_operand:IMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   { return mips_msa_output_division ("div_s.<msafmt>\t%w0,%w1,%w2", operands); }
   [(set_attr "type" "simd_div")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "udiv<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(udiv:IMSA (match_operand:IMSA 1 "register_operand" "f")
-		   (match_operand:IMSA 2 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(udiv:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+		   (match_operand:IMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   { return mips_msa_output_division ("div_u.<msafmt>\t%w0,%w1,%w2", operands); }
   [(set_attr "type" "simd_div")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "mod<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(mod:IMSA (match_operand:IMSA 1 "register_operand" "f")
-		  (match_operand:IMSA 2 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(mod:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+		  (match_operand:IMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   { return mips_msa_output_division ("mod_s.<msafmt>\t%w0,%w1,%w2", operands); }
   [(set_attr "type" "simd_div")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "umod<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(umod:IMSA (match_operand:IMSA 1 "register_operand" "f")
-		   (match_operand:IMSA 2 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(umod:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+		   (match_operand:IMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   { return mips_msa_output_division ("mod_u.<msafmt>\t%w0,%w1,%w2", operands); }
   [(set_attr "type" "simd_div")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "xor<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f,f")
 	(xor:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
   "ISA_HAS_MSA"
   "@
@@ -790,9 +792,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "ior<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f,f")
 	(ior:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
   "ISA_HAS_MSA"
   "@
@@ -803,9 +805,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "and<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f,f")
 	(and:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_val_operand" "f,YZ,Urv8")))]
   "ISA_HAS_MSA"
 {
@@ -830,17 +832,17 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "one_cmpl<mode>2"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(not:IMSA (match_operand:IMSA 1 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(not:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "nor.v\t%w0,%w1,%w1"
   [(set_attr "type" "simd_logic")
    (set_attr "mode" "TI")])
 
 (define_insn "vlshr<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
 	(lshiftrt:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
   "ISA_HAS_MSA"
   "@
@@ -850,9 +852,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "vashr<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
 	(ashiftrt:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
   "ISA_HAS_MSA"
   "@
@@ -862,9 +864,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "vashl<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
 	(ashift:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_uimm6_operand" "f,Uuv6")))]
   "ISA_HAS_MSA"
   "@
@@ -875,64 +877,64 @@ 
 
 ;; Floating-point operations
 (define_insn "add<mode>3"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(plus:FMSA (match_operand:FMSA 1 "register_operand" "f")
-		   (match_operand:FMSA 2 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(plus:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+		   (match_operand:FMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "fadd.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fadd")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "sub<mode>3"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(minus:FMSA (match_operand:FMSA 1 "register_operand" "f")
-		    (match_operand:FMSA 2 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(minus:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+		    (match_operand:FMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "fsub.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fadd")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "mul<mode>3"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(mult:FMSA (match_operand:FMSA 1 "register_operand" "f")
-		   (match_operand:FMSA 2 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(mult:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+		   (match_operand:FMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "fmul.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fmul")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "div<mode>3"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(div:FMSA (match_operand:FMSA 1 "register_operand" "f")
-		  (match_operand:FMSA 2 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(div:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+		  (match_operand:FMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "fdiv.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fdiv")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "fma<mode>4"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(fma:FMSA (match_operand:FMSA 1 "register_operand" "f")
-		  (match_operand:FMSA 2 "register_operand" "f")
-		  (match_operand:FMSA 3 "register_operand" "0")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(fma:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+		  (match_operand:FMSA 2 "msa_reg_operand" "f")
+		  (match_operand:FMSA 3 "msa_reg_operand" "0")))]
   "ISA_HAS_MSA"
   "fmadd.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fmadd")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "fnma<mode>4"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(fma:FMSA (neg:FMSA (match_operand:FMSA 1 "register_operand" "f"))
-		  (match_operand:FMSA 2 "register_operand" "f")
-		  (match_operand:FMSA 3 "register_operand" "0")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(fma:FMSA (neg:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f"))
+		  (match_operand:FMSA 2 "msa_reg_operand" "f")
+		  (match_operand:FMSA 3 "msa_reg_operand" "0")))]
   "ISA_HAS_MSA"
   "fmsub.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fmadd")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "sqrt<mode>2"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(sqrt:FMSA (match_operand:FMSA 1 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(sqrt:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "fsqrt.<msafmt>\t%w0,%w1"
   [(set_attr "type" "simd_fdiv")
@@ -940,46 +942,46 @@ 
 
 ;; Built-in functions
 (define_insn "msa_add_a_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(plus:IMSA (abs:IMSA (match_operand:IMSA 1 "register_operand" "f"))
-		   (abs:IMSA (match_operand:IMSA 2 "register_operand" "f"))))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(plus:IMSA (abs:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f"))
+		   (abs:IMSA (match_operand:IMSA 2 "msa_reg_operand" "f"))))]
   "ISA_HAS_MSA"
   "add_a.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_int_arith")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_adds_a_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
 	(ss_plus:IMSA
-	  (abs:IMSA (match_operand:IMSA 1 "register_operand" "f"))
-	  (abs:IMSA (match_operand:IMSA 2 "register_operand" "f"))))]
+	  (abs:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f"))
+	  (abs:IMSA (match_operand:IMSA 2 "msa_reg_operand" "f"))))]
   "ISA_HAS_MSA"
   "adds_a.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_int_arith")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "ssadd<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(ss_plus:IMSA (match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(ss_plus:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "adds_s.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_int_arith")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "usadd<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(us_plus:IMSA (match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(us_plus:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "adds_u.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_int_arith")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_asub_s_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_ASUB_S))]
   "ISA_HAS_MSA"
   "asub_s.<msafmt>\t%w0,%w1,%w2"
@@ -987,9 +989,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_asub_u_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_ASUB_U))]
   "ISA_HAS_MSA"
   "asub_u.<msafmt>\t%w0,%w1,%w2"
@@ -997,9 +999,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_ave_s_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_AVE_S))]
   "ISA_HAS_MSA"
   "ave_s.<msafmt>\t%w0,%w1,%w2"
@@ -1007,9 +1009,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_ave_u_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_AVE_U))]
   "ISA_HAS_MSA"
   "ave_u.<msafmt>\t%w0,%w1,%w2"
@@ -1017,9 +1019,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_aver_s_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_AVER_S))]
   "ISA_HAS_MSA"
   "aver_s.<msafmt>\t%w0,%w1,%w2"
@@ -1027,9 +1029,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_aver_u_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_AVER_U))]
   "ISA_HAS_MSA"
   "aver_u.<msafmt>\t%w0,%w1,%w2"
@@ -1037,9 +1039,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bclr_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_BCLR))]
   "ISA_HAS_MSA"
   "bclr.<msafmt>\t%w0,%w1,%w2"
@@ -1047,8 +1049,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bclri_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
 		      (match_operand 2 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_BCLRI))]
   "ISA_HAS_MSA"
@@ -1057,10 +1059,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_binsl_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "0")
-		      (match_operand:IMSA 2 "register_operand" "f")
-		      (match_operand:IMSA 3 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "0")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")
+		      (match_operand:IMSA 3 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_BINSL))]
   "ISA_HAS_MSA"
   "binsl.<msafmt>\t%w0,%w2,%w3"
@@ -1068,9 +1070,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_binsli_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "0")
-		      (match_operand:IMSA 2 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "0")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")
 		      (match_operand 3 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_BINSLI))]
   "ISA_HAS_MSA"
@@ -1079,10 +1081,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_binsr_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "0")
-		      (match_operand:IMSA 2 "register_operand" "f")
-		      (match_operand:IMSA 3 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "0")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")
+		      (match_operand:IMSA 3 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_BINSR))]
   "ISA_HAS_MSA"
   "binsr.<msafmt>\t%w0,%w2,%w3"
@@ -1090,9 +1092,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_binsri_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "0")
-		      (match_operand:IMSA 2 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "0")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")
 		      (match_operand 3 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_BINSRI))]
   "ISA_HAS_MSA"
@@ -1101,11 +1103,11 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bmnz_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
-	(ior:IMSA (and:IMSA (match_operand:IMSA 2 "register_operand" "f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
+	(ior:IMSA (and:IMSA (match_operand:IMSA 2 "msa_reg_operand" "f,f")
 			    (match_operand:IMSA 3 "reg_or_vector_same_val_operand" "f,Urv8"))
 		  (and:IMSA (not:IMSA (match_dup 3))
-			    (match_operand:IMSA 1 "register_operand" "0,0"))))]
+			    (match_operand:IMSA 1 "msa_reg_operand" "0,0"))))]
   "ISA_HAS_MSA"
   "@
    bmnz.v\t%w0,%w2,%w3
@@ -1114,11 +1116,11 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bmz_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
 	(ior:IMSA (and:IMSA (not:IMSA
 			      (match_operand:IMSA 3 "reg_or_vector_same_val_operand" "f,Urv8"))
-			    (match_operand:IMSA 2 "register_operand" "f,f"))
-		  (and:IMSA (match_operand:IMSA 1 "register_operand" "0,0")
+			    (match_operand:IMSA 2 "msa_reg_operand" "f,f"))
+		  (and:IMSA (match_operand:IMSA 1 "msa_reg_operand" "0,0")
 			    (match_dup 3))))]
   "ISA_HAS_MSA"
   "@
@@ -1128,9 +1130,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bneg_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_BNEG))]
   "ISA_HAS_MSA"
   "bneg.<msafmt>\t%w0,%w1,%w2"
@@ -1138,8 +1140,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bnegi_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
 		       (match_operand 2 "const_msa_branch_operand" "")]
 		     UNSPEC_MSA_BNEGI))]
   "ISA_HAS_MSA"
@@ -1148,10 +1150,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bsel_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
 	(ior:IMSA (and:IMSA (not:IMSA
-			      (match_operand:IMSA 1 "register_operand" "0,0"))
-			    (match_operand:IMSA 2 "register_operand" "f,f"))
+			      (match_operand:IMSA 1 "msa_reg_operand" "0,0"))
+			    (match_operand:IMSA 2 "msa_reg_operand" "f,f"))
 		  (and:IMSA (match_dup 1)
 			    (match_operand:IMSA 3 "reg_or_vector_same_val_operand" "f,Urv8"))))]
   "ISA_HAS_MSA"
@@ -1162,9 +1164,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bset_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_BSET))]
   "ISA_HAS_MSA"
   "bset.<msafmt>\t%w0,%w1,%w2"
@@ -1172,8 +1174,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_bseti_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
 		      (match_operand 2 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_BSETI))]
   "ISA_HAS_MSA"
@@ -1205,9 +1207,9 @@ 
    (ltu  "u")])
 
 (define_insn "msa_c<ICC:icc>_<IMSA:msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
 	(ICC:IMSA
-	  (match_operand:IMSA 1 "register_operand" "f,f")
+	  (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 	  (match_operand:IMSA 2 "reg_or_vector_same_<ICC:cmpi>imm5_operand" "f,U<ICC:cmpi>v5")))]
   "ISA_HAS_MSA"
   "@
@@ -1217,16 +1219,16 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_dotp_<su>_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
+  [(set (match_operand:V2DI 0 "msa_reg_operand" "=f")
 	(plus:V2DI
 	  (mult:V2DI
 	    (any_extend:V2DI
 	      (vec_select:V2SI
-		(match_operand:V4SI 1 "register_operand" "%f")
+		(match_operand:V4SI 1 "msa_reg_operand" "%f")
 		(parallel [(const_int 0) (const_int 2)])))
 	    (any_extend:V2DI
 	      (vec_select:V2SI
-		(match_operand:V4SI 2 "register_operand" "f")
+		(match_operand:V4SI 2 "msa_reg_operand" "f")
 		(parallel [(const_int 0) (const_int 2)]))))
 	  (mult:V2DI
 	    (any_extend:V2DI
@@ -1241,17 +1243,17 @@ 
    (set_attr "mode" "V2DI")])
 
 (define_insn "msa_dotp_<su>_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(plus:V4SI
 	  (mult:V4SI
 	    (any_extend:V4SI
 	      (vec_select:V4HI
-		(match_operand:V8HI 1 "register_operand" "%f")
+		(match_operand:V8HI 1 "msa_reg_operand" "%f")
 		(parallel [(const_int 0) (const_int 2)
 			   (const_int 4) (const_int 6)])))
 	    (any_extend:V4SI
 	      (vec_select:V4HI
-		(match_operand:V8HI 2 "register_operand" "f")
+		(match_operand:V8HI 2 "msa_reg_operand" "f")
 		(parallel [(const_int 0) (const_int 2)
 			   (const_int 4) (const_int 6)]))))
 	  (mult:V4SI
@@ -1269,19 +1271,19 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_dotp_<su>_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(plus:V8HI
 	  (mult:V8HI
 	    (any_extend:V8HI
 	      (vec_select:V8QI
-		(match_operand:V16QI 1 "register_operand" "%f")
+		(match_operand:V16QI 1 "msa_reg_operand" "%f")
 		(parallel [(const_int 0) (const_int 2)
 			   (const_int 4) (const_int 6)
 			   (const_int 8) (const_int 10)
 			   (const_int 12) (const_int 14)])))
 	    (any_extend:V8HI
 	      (vec_select:V8QI
-		(match_operand:V16QI 2 "register_operand" "f")
+		(match_operand:V16QI 2 "msa_reg_operand" "f")
 		(parallel [(const_int 0) (const_int 2)
 			   (const_int 4) (const_int 6)
 			   (const_int 8) (const_int 10)
@@ -1305,17 +1307,17 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_dpadd_<su>_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
+  [(set (match_operand:V2DI 0 "msa_reg_operand" "=f")
 	(plus:V2DI
 	  (plus:V2DI
 	    (mult:V2DI
 	      (any_extend:V2DI
 		(vec_select:V2SI
-		  (match_operand:V4SI 2 "register_operand" "%f")
+		  (match_operand:V4SI 2 "msa_reg_operand" "%f")
 		  (parallel [(const_int 0) (const_int 2)])))
 	      (any_extend:V2DI
 		(vec_select:V2SI
-		  (match_operand:V4SI 3 "register_operand" "f")
+		  (match_operand:V4SI 3 "msa_reg_operand" "f")
 		  (parallel [(const_int 0) (const_int 2)]))))
 	    (mult:V2DI
 	      (any_extend:V2DI
@@ -1324,25 +1326,25 @@ 
 	      (any_extend:V2DI
 		(vec_select:V2SI (match_dup 3)
 		  (parallel [(const_int 1) (const_int 3)])))))
-	  (match_operand:V2DI 1 "register_operand" "0")))]
+	  (match_operand:V2DI 1 "msa_reg_operand" "0")))]
   "ISA_HAS_MSA"
   "dpadd_<su>.d\t%w0,%w2,%w3"
   [(set_attr "type" "simd_mul")
    (set_attr "mode" "V2DI")])
 
 (define_insn "msa_dpadd_<su>_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(plus:V4SI
 	  (plus:V4SI
 	    (mult:V4SI
 	      (any_extend:V4SI
 		(vec_select:V4HI
-		  (match_operand:V8HI 2 "register_operand" "%f")
+		  (match_operand:V8HI 2 "msa_reg_operand" "%f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)])))
 	      (any_extend:V4SI
 		(vec_select:V4HI
-		  (match_operand:V8HI 3 "register_operand" "f")
+		  (match_operand:V8HI 3 "msa_reg_operand" "f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)]))))
 	    (mult:V4SI
@@ -1354,27 +1356,27 @@ 
 		(vec_select:V4HI (match_dup 3)
 		  (parallel [(const_int 1) (const_int 3)
 			     (const_int 5) (const_int 7)])))))
-	  (match_operand:V4SI 1 "register_operand" "0")))]
+	  (match_operand:V4SI 1 "msa_reg_operand" "0")))]
   "ISA_HAS_MSA"
   "dpadd_<su>.w\t%w0,%w2,%w3"
   [(set_attr "type" "simd_mul")
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_dpadd_<su>_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(plus:V8HI
 	  (plus:V8HI
 	    (mult:V8HI
 	      (any_extend:V8HI
 		(vec_select:V8QI
-		  (match_operand:V16QI 2 "register_operand" "%f")
+		  (match_operand:V16QI 2 "msa_reg_operand" "%f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)
 			     (const_int 8) (const_int 10)
 			     (const_int 12) (const_int 14)])))
 	      (any_extend:V8HI
 		(vec_select:V8QI
-		  (match_operand:V16QI 3 "register_operand" "f")
+		  (match_operand:V16QI 3 "msa_reg_operand" "f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)
 			     (const_int 8) (const_int 10)
@@ -1392,25 +1394,25 @@ 
 			     (const_int 5) (const_int 7)
 			     (const_int 9) (const_int 11)
 			     (const_int 13) (const_int 15)])))))
-	  (match_operand:V8HI 1 "register_operand" "0")))]
+	  (match_operand:V8HI 1 "msa_reg_operand" "0")))]
   "ISA_HAS_MSA"
   "dpadd_<su>.h\t%w0,%w2,%w3"
   [(set_attr "type" "simd_mul")
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_dpsub_<su>_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
+  [(set (match_operand:V2DI 0 "msa_reg_operand" "=f")
 	(minus:V2DI
-	  (match_operand:V2DI 1 "register_operand" "0")
+	  (match_operand:V2DI 1 "msa_reg_operand" "0")
 	  (plus:V2DI
 	    (mult:V2DI
 	      (any_extend:V2DI
 		(vec_select:V2SI
-		  (match_operand:V4SI 2 "register_operand" "%f")
+		  (match_operand:V4SI 2 "msa_reg_operand" "%f")
 		  (parallel [(const_int 0) (const_int 2)])))
 	      (any_extend:V2DI
 		(vec_select:V2SI
-		  (match_operand:V4SI 3 "register_operand" "f")
+		  (match_operand:V4SI 3 "msa_reg_operand" "f")
 		  (parallel [(const_int 0) (const_int 2)]))))
 	    (mult:V2DI
 	      (any_extend:V2DI
@@ -1425,19 +1427,19 @@ 
    (set_attr "mode" "V2DI")])
 
 (define_insn "msa_dpsub_<su>_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(minus:V4SI
-	  (match_operand:V4SI 1 "register_operand" "0")
+	  (match_operand:V4SI 1 "msa_reg_operand" "0")
 	  (plus:V4SI
 	    (mult:V4SI
 	      (any_extend:V4SI
 		(vec_select:V4HI
-		  (match_operand:V8HI 2 "register_operand" "%f")
+		  (match_operand:V8HI 2 "msa_reg_operand" "%f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)])))
 	      (any_extend:V4SI
 		(vec_select:V4HI
-		  (match_operand:V8HI 3 "register_operand" "f")
+		  (match_operand:V8HI 3 "msa_reg_operand" "f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)]))))
 	    (mult:V4SI
@@ -1455,21 +1457,21 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_dpsub_<su>_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(minus:V8HI
-	  (match_operand:V8HI 1 "register_operand" "0")
+	  (match_operand:V8HI 1 "msa_reg_operand" "0")
 	  (plus:V8HI
 	    (mult:V8HI
 	      (any_extend:V8HI
 		(vec_select:V8QI
-		  (match_operand:V16QI 2 "register_operand" "%f")
+		  (match_operand:V16QI 2 "msa_reg_operand" "%f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)
 			     (const_int 8) (const_int 10)
 			     (const_int 12) (const_int 14)])))
 	      (any_extend:V8HI
 		(vec_select:V8QI
-		  (match_operand:V16QI 3 "register_operand" "f")
+		  (match_operand:V16QI 3 "msa_reg_operand" "f")
 		  (parallel [(const_int 0) (const_int 2)
 			     (const_int 4) (const_int 6)
 			     (const_int 8) (const_int 10)
@@ -1493,8 +1495,8 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_fclass_<msafmt>"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(unspec:<VIMODE> [(match_operand:FMSA 1 "register_operand" "f")]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(unspec:<VIMODE> [(match_operand:FMSA 1 "msa_reg_operand" "f")]
 			 UNSPEC_MSA_FCLASS))]
   "ISA_HAS_MSA"
   "fclass.<msafmt>\t%w0,%w1"
@@ -1502,9 +1504,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_fcaf_<msafmt>"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(unspec:<VIMODE> [(match_operand:FMSA 1 "register_operand" "f")
-			  (match_operand:FMSA 2 "register_operand" "f")]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(unspec:<VIMODE> [(match_operand:FMSA 1 "msa_reg_operand" "f")
+			  (match_operand:FMSA 2 "msa_reg_operand" "f")]
 			 UNSPEC_MSA_FCAF))]
   "ISA_HAS_MSA"
   "fcaf.<msafmt>\t%w0,%w1,%w2"
@@ -1512,9 +1514,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_fcune_<FMSA:msafmt>"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(unspec:<VIMODE> [(match_operand:FMSA 1 "register_operand" "f")
-			  (match_operand:FMSA 2 "register_operand" "f")]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(unspec:<VIMODE> [(match_operand:FMSA 1 "msa_reg_operand" "f")
+			  (match_operand:FMSA 2 "msa_reg_operand" "f")]
 			 UNSPEC_MSA_FCUNE))]
   "ISA_HAS_MSA"
   "fcune.<FMSA:msafmt>\t%w0,%w1,%w2"
@@ -1553,18 +1555,18 @@ 
    (UNSPEC_MSA_FSLT  "fslt")])
 
 (define_insn "msa_<FCC:fcc>_<FMSA:msafmt>"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(FCC:<VIMODE> (match_operand:FMSA 1 "register_operand" "f")
-		      (match_operand:FMSA 2 "register_operand" "f")))]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(FCC:<VIMODE> (match_operand:FMSA 1 "msa_reg_operand" "f")
+		      (match_operand:FMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "<FCC:fcc>.<FMSA:msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fcmp")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_<fsc>_<FMSA:msafmt>"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(unspec:<VIMODE> [(match_operand:FMSA 1 "register_operand" "f")
-			   (match_operand:FMSA 2 "register_operand" "f")]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(unspec:<VIMODE> [(match_operand:FMSA 1 "msa_reg_operand" "f")
+			   (match_operand:FMSA 2 "msa_reg_operand" "f")]
 			 FSC_UNS))]
   "ISA_HAS_MSA"
   "<fsc>.<FMSA:msafmt>\t%w0,%w1,%w2"
@@ -1572,9 +1574,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_fexp2_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:FMSA 1 "register_operand" "f")
-		      (match_operand:<VIMODE> 2 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:FMSA 1 "msa_reg_operand" "f")
+		      (match_operand:<VIMODE> 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FEXP2))]
   "ISA_HAS_MSA"
   "fexp2.<msafmt>\t%w0,%w1,%w2"
@@ -1598,8 +1600,8 @@ 
    (V2DF "D2I")])
 
 (define_insn "float<fint><FMSA:mode>2"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(float:FMSA (match_operand:<VIMODE> 1 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(float:FMSA (match_operand:<VIMODE> 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "ffint_s.<msafmt>\t%w0,%w1"
   [(set_attr "type" "simd_fcvt")
@@ -1607,9 +1609,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "floatuns<fint><FMSA:mode>2"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
 	(unsigned_float:FMSA
-	  (match_operand:<VIMODE> 1 "register_operand" "f")))]
+	  (match_operand:<VIMODE> 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "ffint_u.<msafmt>\t%w0,%w1"
   [(set_attr "type" "simd_fcvt")
@@ -1621,8 +1623,8 @@ 
    (V2DF "V4SI")])
 
 (define_insn "msa_ffql_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:<FQ> 1 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:<FQ> 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FFQL))]
   "ISA_HAS_MSA"
   "ffql.<msafmt>\t%w0,%w1"
@@ -1631,8 +1633,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_ffqr_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:<FQ> 1 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:<FQ> 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FFQR))]
   "ISA_HAS_MSA"
   "ffqr.<msafmt>\t%w0,%w1"
@@ -1641,7 +1643,7 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_fill_<msafmt_f>"
-  [(set (match_operand:MSA 0 "register_operand" "=f,f")
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f,f")
 	(vec_duplicate:MSA
 	  (match_operand:<UNITMODE> 1 "reg_or_0_operand" "d,J")))]
   "ISA_HAS_MSA"
@@ -1658,9 +1660,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_split
-  [(set (match_operand:MSA_D 0 "register_operand")
+  [(set (match_operand:MSA_D 0 "msa_reg_operand")
 	(vec_duplicate:MSA_D
-	  (match_operand:<UNITMODE> 1 "register_operand")))]
+	  (match_operand:<UNITMODE> 1 "msa_reg_operand")))]
   "reload_completed && ISA_HAS_MSA && !TARGET_64BIT"
   [(const_int 0)]
 {
@@ -1669,8 +1671,8 @@ 
 })
 
 (define_insn "msa_flog2_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:FMSA 1 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:FMSA 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FLOG2))]
   "ISA_HAS_MSA"
   "flog2.<msafmt>\t%w0,%w1"
@@ -1678,19 +1680,19 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "smax<mode>3"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(smax:FMSA (match_operand:FMSA 1 "register_operand" "f")
-		   (match_operand:FMSA 2 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(smax:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+		   (match_operand:FMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "fmax.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fminmax")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_fmax_a_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
 	(if_then_else:FMSA
-	   (gt (abs:FMSA (match_operand:FMSA 1 "register_operand" "f"))
-	       (abs:FMSA (match_operand:FMSA 2 "register_operand" "f")))
+	   (gt (abs:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f"))
+	       (abs:FMSA (match_operand:FMSA 2 "msa_reg_operand" "f")))
 	   (match_dup 1)
 	   (match_dup 2)))]
   "ISA_HAS_MSA"
@@ -1699,19 +1701,19 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "smin<mode>3"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(smin:FMSA (match_operand:FMSA 1 "register_operand" "f")
-		   (match_operand:FMSA 2 "register_operand" "f")))]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(smin:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f")
+		   (match_operand:FMSA 2 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "fmin.<msafmt>\t%w0,%w1,%w2"
   [(set_attr "type" "simd_fminmax")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_fmin_a_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
 	(if_then_else:FMSA
-	   (lt (abs:FMSA (match_operand:FMSA 1 "register_operand" "f"))
-	       (abs:FMSA (match_operand:FMSA 2 "register_operand" "f")))
+	   (lt (abs:FMSA (match_operand:FMSA 1 "msa_reg_operand" "f"))
+	       (abs:FMSA (match_operand:FMSA 2 "msa_reg_operand" "f")))
 	   (match_dup 1)
 	   (match_dup 2)))]
   "ISA_HAS_MSA"
@@ -1720,8 +1722,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_frcp_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:FMSA 1 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:FMSA 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FRCP))]
   "ISA_HAS_MSA"
   "frcp.<msafmt>\t%w0,%w1"
@@ -1729,8 +1731,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_frint_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:FMSA 1 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:FMSA 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FRINT))]
   "ISA_HAS_MSA"
   "frint.<msafmt>\t%w0,%w1"
@@ -1738,8 +1740,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_frsqrt_<msafmt>"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:FMSA 1 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:FMSA 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FRSQRT))]
   "ISA_HAS_MSA"
   "frsqrt.<msafmt>\t%w0,%w1"
@@ -1747,8 +1749,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_ftint_s_<msafmt>"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(unspec:<VIMODE> [(match_operand:FMSA 1 "register_operand" "f")]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(unspec:<VIMODE> [(match_operand:FMSA 1 "msa_reg_operand" "f")]
 			 UNSPEC_MSA_FTINT_S))]
   "ISA_HAS_MSA"
   "ftint_s.<msafmt>\t%w0,%w1"
@@ -1757,8 +1759,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_ftint_u_<msafmt>"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(unspec:<VIMODE> [(match_operand:FMSA 1 "register_operand" "f")]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(unspec:<VIMODE> [(match_operand:FMSA 1 "msa_reg_operand" "f")]
 			 UNSPEC_MSA_FTINT_U))]
   "ISA_HAS_MSA"
   "ftint_u.<msafmt>\t%w0,%w1"
@@ -1767,8 +1769,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "fix_trunc<FMSA:mode><mode_i>2"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(fix:<VIMODE> (match_operand:FMSA 1 "register_operand" "f")))]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(fix:<VIMODE> (match_operand:FMSA 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "ftrunc_s.<msafmt>\t%w0,%w1"
   [(set_attr "type" "simd_fcvt")
@@ -1776,8 +1778,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "fixuns_trunc<FMSA:mode><mode_i>2"
-  [(set (match_operand:<VIMODE> 0 "register_operand" "=f")
-	(unsigned_fix:<VIMODE> (match_operand:FMSA 1 "register_operand" "f")))]
+  [(set (match_operand:<VIMODE> 0 "msa_reg_operand" "=f")
+	(unsigned_fix:<VIMODE> (match_operand:FMSA 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "ftrunc_u.<msafmt>\t%w0,%w1"
   [(set_attr "type" "simd_fcvt")
@@ -1785,9 +1787,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_ftq_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
-	(unspec:V8HI [(match_operand:V4SF 1 "register_operand" "f")
-		      (match_operand:V4SF 2 "register_operand" "f")]
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
+	(unspec:V8HI [(match_operand:V4SF 1 "msa_reg_operand" "f")
+		      (match_operand:V4SF 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FTQ))]
   "ISA_HAS_MSA"
   "ftq.h\t%w0,%w1,%w2"
@@ -1796,9 +1798,9 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_ftq_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
-	(unspec:V4SI [(match_operand:V2DF 1 "register_operand" "f")
-		      (match_operand:V2DF 2 "register_operand" "f")]
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
+	(unspec:V4SI [(match_operand:V2DF 1 "msa_reg_operand" "f")
+		      (match_operand:V2DF 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FTQ))]
   "ISA_HAS_MSA"
   "ftq.w\t%w0,%w1,%w2"
@@ -1807,18 +1809,18 @@ 
    (set_attr "mode" "V2DF")])
 
 (define_insn "msa_h<optab>_<su>_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(addsub:V8HI
 	  (any_extend:V8HI
 	    (vec_select:V8QI
-	      (match_operand:V16QI 1 "register_operand" "f")
+	      (match_operand:V16QI 1 "msa_reg_operand" "f")
 	      (parallel [(const_int 1) (const_int 3)
 			 (const_int 5) (const_int 7)
 			 (const_int 9) (const_int 11)
 			 (const_int 13) (const_int 15)])))
 	  (any_extend:V8HI
 	    (vec_select:V8QI
-	      (match_operand:V16QI 2 "register_operand" "f")
+	      (match_operand:V16QI 2 "msa_reg_operand" "f")
 	      (parallel [(const_int 0) (const_int 2)
 			 (const_int 4) (const_int 6)
 			 (const_int 8) (const_int 10)
@@ -1829,16 +1831,16 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_h<optab>_<su>_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(addsub:V4SI
 	  (any_extend:V4SI
 	    (vec_select:V4HI
-	      (match_operand:V8HI 1 "register_operand" "f")
+	      (match_operand:V8HI 1 "msa_reg_operand" "f")
 	      (parallel [(const_int 1) (const_int 3)
 			 (const_int 5) (const_int 7)])))
 	  (any_extend:V4SI
 	    (vec_select:V4HI
-	      (match_operand:V8HI 2 "register_operand" "f")
+	      (match_operand:V8HI 2 "msa_reg_operand" "f")
 	      (parallel [(const_int 0) (const_int 2)
 			 (const_int 4) (const_int 6)])))))]
   "ISA_HAS_MSA"
@@ -1847,15 +1849,15 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_h<optab>_<su>_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
+  [(set (match_operand:V2DI 0 "msa_reg_operand" "=f")
 	(addsub:V2DI
 	  (any_extend:V2DI
 	    (vec_select:V2SI
-	      (match_operand:V4SI 1 "register_operand" "f")
+	      (match_operand:V4SI 1 "msa_reg_operand" "f")
 	      (parallel [(const_int 1) (const_int 3)])))
 	  (any_extend:V2DI
 	    (vec_select:V2SI
-	      (match_operand:V4SI 2 "register_operand" "f")
+	      (match_operand:V4SI 2 "msa_reg_operand" "f")
 	      (parallel [(const_int 0) (const_int 2)])))))]
   "ISA_HAS_MSA"
   "h<optab>_<su>.d\t%w0,%w1,%w2"
@@ -1863,11 +1865,11 @@ 
    (set_attr "mode" "V2DI")])
 
 (define_insn "msa_ilvev_b"
-  [(set (match_operand:V16QI 0 "register_operand" "=f")
+  [(set (match_operand:V16QI 0 "msa_reg_operand" "=f")
 	(vec_select:V16QI
 	  (vec_concat:V32QI
-	    (match_operand:V16QI 1 "register_operand" "f")
-	    (match_operand:V16QI 2 "register_operand" "f"))
+	    (match_operand:V16QI 1 "msa_reg_operand" "f")
+	    (match_operand:V16QI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0)  (const_int 16)
 		     (const_int 2)  (const_int 18)
 		     (const_int 4)  (const_int 20)
@@ -1882,11 +1884,11 @@ 
    (set_attr "mode" "V16QI")])
 
 (define_insn "msa_ilvev_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(vec_select:V8HI
 	  (vec_concat:V16HI
-	    (match_operand:V8HI 1 "register_operand" "f")
-	    (match_operand:V8HI 2 "register_operand" "f"))
+	    (match_operand:V8HI 1 "msa_reg_operand" "f")
+	    (match_operand:V8HI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 8)
 		     (const_int 2) (const_int 10)
 		     (const_int 4) (const_int 12)
@@ -1897,11 +1899,11 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_ilvev_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(vec_select:V4SI
 	  (vec_concat:V8SI
-	    (match_operand:V4SI 1 "register_operand" "f")
-	    (match_operand:V4SI 2 "register_operand" "f"))
+	    (match_operand:V4SI 1 "msa_reg_operand" "f")
+	    (match_operand:V4SI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 4)
 		     (const_int 2) (const_int 6)])))]
   "ISA_HAS_MSA"
@@ -1910,11 +1912,11 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_ilvev_w_f"
-  [(set (match_operand:V4SF 0 "register_operand" "=f")
+  [(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
 	(vec_select:V4SF
 	  (vec_concat:V8SF
-	    (match_operand:V4SF 1 "register_operand" "f")
-	    (match_operand:V4SF 2 "register_operand" "f"))
+	    (match_operand:V4SF 1 "msa_reg_operand" "f")
+	    (match_operand:V4SF 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 4)
 		     (const_int 2) (const_int 6)])))]
   "ISA_HAS_MSA"
@@ -1923,11 +1925,11 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_ilvl_b"
-  [(set (match_operand:V16QI 0 "register_operand" "=f")
+  [(set (match_operand:V16QI 0 "msa_reg_operand" "=f")
 	(vec_select:V16QI
 	  (vec_concat:V32QI
-	    (match_operand:V16QI 1 "register_operand" "f")
-	    (match_operand:V16QI 2 "register_operand" "f"))
+	    (match_operand:V16QI 1 "msa_reg_operand" "f")
+	    (match_operand:V16QI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 8)  (const_int 24)
 		     (const_int 9)  (const_int 25)
 		     (const_int 10) (const_int 26)
@@ -1942,11 +1944,11 @@ 
    (set_attr "mode" "V16QI")])
 
 (define_insn "msa_ilvl_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(vec_select:V8HI
 	  (vec_concat:V16HI
-	    (match_operand:V8HI 1 "register_operand" "f")
-	    (match_operand:V8HI 2 "register_operand" "f"))
+	    (match_operand:V8HI 1 "msa_reg_operand" "f")
+	    (match_operand:V8HI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 4) (const_int 12)
 		     (const_int 5) (const_int 13)
 		     (const_int 6) (const_int 14)
@@ -1957,11 +1959,11 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_ilvl_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(vec_select:V4SI
 	  (vec_concat:V8SI
-	    (match_operand:V4SI 1 "register_operand" "f")
-	    (match_operand:V4SI 2 "register_operand" "f"))
+	    (match_operand:V4SI 1 "msa_reg_operand" "f")
+	    (match_operand:V4SI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 2) (const_int 6)
 		     (const_int 3) (const_int 7)])))]
   "ISA_HAS_MSA"
@@ -1970,11 +1972,11 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_ilvl_w_f"
-  [(set (match_operand:V4SF 0 "register_operand" "=f")
+  [(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
 	(vec_select:V4SF
 	  (vec_concat:V8SF
-	    (match_operand:V4SF 1 "register_operand" "f")
-	    (match_operand:V4SF 2 "register_operand" "f"))
+	    (match_operand:V4SF 1 "msa_reg_operand" "f")
+	    (match_operand:V4SF 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 2) (const_int 6)
 		     (const_int 3) (const_int 7)])))]
   "ISA_HAS_MSA"
@@ -1983,11 +1985,11 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_ilvl_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
+  [(set (match_operand:V2DI 0 "msa_reg_operand" "=f")
 	(vec_select:V2DI
 	  (vec_concat:V4DI
-	    (match_operand:V2DI 1 "register_operand" "f")
-	    (match_operand:V2DI 2 "register_operand" "f"))
+	    (match_operand:V2DI 1 "msa_reg_operand" "f")
+	    (match_operand:V2DI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 1) (const_int 3)])))]
   "ISA_HAS_MSA"
   "ilvl.d\t%w0,%w2,%w1"
@@ -1995,11 +1997,11 @@ 
    (set_attr "mode" "V2DI")])
 
 (define_insn "msa_ilvl_d_f"
-  [(set (match_operand:V2DF 0 "register_operand" "=f")
+  [(set (match_operand:V2DF 0 "msa_reg_operand" "=f")
 	(vec_select:V2DF
 	  (vec_concat:V4DF
-	    (match_operand:V2DF 1 "register_operand" "f")
-	    (match_operand:V2DF 2 "register_operand" "f"))
+	    (match_operand:V2DF 1 "msa_reg_operand" "f")
+	    (match_operand:V2DF 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 1) (const_int 3)])))]
   "ISA_HAS_MSA"
   "ilvl.d\t%w0,%w2,%w1"
@@ -2007,11 +2009,11 @@ 
    (set_attr "mode" "V2DF")])
 
 (define_insn "msa_ilvod_b"
-  [(set (match_operand:V16QI 0 "register_operand" "=f")
+  [(set (match_operand:V16QI 0 "msa_reg_operand" "=f")
 	(vec_select:V16QI
 	  (vec_concat:V32QI
-	    (match_operand:V16QI 1 "register_operand" "f")
-	    (match_operand:V16QI 2 "register_operand" "f"))
+	    (match_operand:V16QI 1 "msa_reg_operand" "f")
+	    (match_operand:V16QI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 1)  (const_int 17)
 		     (const_int 3)  (const_int 19)
 		     (const_int 5)  (const_int 21)
@@ -2026,11 +2028,11 @@ 
    (set_attr "mode" "V16QI")])
 
 (define_insn "msa_ilvod_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(vec_select:V8HI
 	  (vec_concat:V16HI
-	    (match_operand:V8HI 1 "register_operand" "f")
-	    (match_operand:V8HI 2 "register_operand" "f"))
+	    (match_operand:V8HI 1 "msa_reg_operand" "f")
+	    (match_operand:V8HI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 1) (const_int 9)
 		     (const_int 3) (const_int 11)
 		     (const_int 5) (const_int 13)
@@ -2041,11 +2043,11 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_ilvod_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(vec_select:V4SI
 	  (vec_concat:V8SI
-	    (match_operand:V4SI 1 "register_operand" "f")
-	    (match_operand:V4SI 2 "register_operand" "f"))
+	    (match_operand:V4SI 1 "msa_reg_operand" "f")
+	    (match_operand:V4SI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 1) (const_int 5)
 		     (const_int 3) (const_int 7)])))]
   "ISA_HAS_MSA"
@@ -2054,11 +2056,11 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_ilvod_w_f"
-  [(set (match_operand:V4SF 0 "register_operand" "=f")
+  [(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
 	(vec_select:V4SF
 	  (vec_concat:V8SF
-	    (match_operand:V4SF 1 "register_operand" "f")
-	    (match_operand:V4SF 2 "register_operand" "f"))
+	    (match_operand:V4SF 1 "msa_reg_operand" "f")
+	    (match_operand:V4SF 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 1) (const_int 5)
 		     (const_int 3) (const_int 7)])))]
   "ISA_HAS_MSA"
@@ -2067,11 +2069,11 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_ilvr_b"
-  [(set (match_operand:V16QI 0 "register_operand" "=f")
+  [(set (match_operand:V16QI 0 "msa_reg_operand" "=f")
 	(vec_select:V16QI
 	  (vec_concat:V32QI
-	    (match_operand:V16QI 1 "register_operand" "f")
-	    (match_operand:V16QI 2 "register_operand" "f"))
+	    (match_operand:V16QI 1 "msa_reg_operand" "f")
+	    (match_operand:V16QI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 16)
 		     (const_int 1) (const_int 17)
 		     (const_int 2) (const_int 18)
@@ -2086,11 +2088,11 @@ 
    (set_attr "mode" "V16QI")])
 
 (define_insn "msa_ilvr_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
 	(vec_select:V8HI
 	  (vec_concat:V16HI
-	    (match_operand:V8HI 1 "register_operand" "f")
-	    (match_operand:V8HI 2 "register_operand" "f"))
+	    (match_operand:V8HI 1 "msa_reg_operand" "f")
+	    (match_operand:V8HI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 8)
 		     (const_int 1) (const_int 9)
 		     (const_int 2) (const_int 10)
@@ -2101,11 +2103,11 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_ilvr_w"
-  [(set (match_operand:V4SI 0 "register_operand" "=f")
+  [(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
 	(vec_select:V4SI
 	  (vec_concat:V8SI
-	    (match_operand:V4SI 1 "register_operand" "f")
-	    (match_operand:V4SI 2 "register_operand" "f"))
+	    (match_operand:V4SI 1 "msa_reg_operand" "f")
+	    (match_operand:V4SI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 4)
 		     (const_int 1) (const_int 5)])))]
   "ISA_HAS_MSA"
@@ -2114,11 +2116,11 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_ilvr_w_f"
-  [(set (match_operand:V4SF 0 "register_operand" "=f")
+  [(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
 	(vec_select:V4SF
 	  (vec_concat:V8SF
-	    (match_operand:V4SF 1 "register_operand" "f")
-	    (match_operand:V4SF 2 "register_operand" "f"))
+	    (match_operand:V4SF 1 "msa_reg_operand" "f")
+	    (match_operand:V4SF 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 4)
 		     (const_int 1) (const_int 5)])))]
   "ISA_HAS_MSA"
@@ -2127,11 +2129,11 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_ilvr_d"
-  [(set (match_operand:V2DI 0 "register_operand" "=f")
+  [(set (match_operand:V2DI 0 "msa_reg_operand" "=f")
 	(vec_select:V2DI
 	  (vec_concat:V4DI
-	    (match_operand:V2DI 1 "register_operand" "f")
-	    (match_operand:V2DI 2 "register_operand" "f"))
+	    (match_operand:V2DI 1 "msa_reg_operand" "f")
+	    (match_operand:V2DI 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 2)])))]
   "ISA_HAS_MSA"
   "ilvr.d\t%w0,%w2,%w1"
@@ -2139,11 +2141,11 @@ 
    (set_attr "mode" "V2DI")])
 
 (define_insn "msa_ilvr_d_f"
-  [(set (match_operand:V2DF 0 "register_operand" "=f")
+  [(set (match_operand:V2DF 0 "msa_reg_operand" "=f")
 	(vec_select:V2DF
 	  (vec_concat:V4DF
-	    (match_operand:V2DF 1 "register_operand" "f")
-	    (match_operand:V2DF 2 "register_operand" "f"))
+	    (match_operand:V2DF 1 "msa_reg_operand" "f")
+	    (match_operand:V2DF 2 "msa_reg_operand" "f"))
 	  (parallel [(const_int 0) (const_int 2)])))]
   "ISA_HAS_MSA"
   "ilvr.d\t%w0,%w2,%w1"
@@ -2151,10 +2153,10 @@ 
    (set_attr "mode" "V2DF")])
 
 (define_insn "msa_madd_q_<msafmt>"
-  [(set (match_operand:IMSA_WH 0 "register_operand" "=f")
-	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "register_operand" "0")
-			 (match_operand:IMSA_WH 2 "register_operand" "f")
-			 (match_operand:IMSA_WH 3 "register_operand" "f")]
+  [(set (match_operand:IMSA_WH 0 "msa_reg_operand" "=f")
+	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "msa_reg_operand" "0")
+			 (match_operand:IMSA_WH 2 "msa_reg_operand" "f")
+			 (match_operand:IMSA_WH 3 "msa_reg_operand" "f")]
 			UNSPEC_MSA_MADD_Q))]
   "ISA_HAS_MSA"
   "madd_q.<msafmt>\t%w0,%w2,%w3"
@@ -2162,10 +2164,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_maddr_q_<msafmt>"
-  [(set (match_operand:IMSA_WH 0 "register_operand" "=f")
-	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "register_operand" "0")
-			 (match_operand:IMSA_WH 2 "register_operand" "f")
-			 (match_operand:IMSA_WH 3 "register_operand" "f")]
+  [(set (match_operand:IMSA_WH 0 "msa_reg_operand" "=f")
+	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "msa_reg_operand" "0")
+			 (match_operand:IMSA_WH 2 "msa_reg_operand" "f")
+			 (match_operand:IMSA_WH 3 "msa_reg_operand" "f")]
 			UNSPEC_MSA_MADDR_Q))]
   "ISA_HAS_MSA"
   "maddr_q.<msafmt>\t%w0,%w2,%w3"
@@ -2173,10 +2175,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_max_a_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
 	(if_then_else:IMSA
-	   (gt (abs:IMSA (match_operand:IMSA 1 "register_operand" "f"))
-	       (abs:IMSA (match_operand:IMSA 2 "register_operand" "f")))
+	   (gt (abs:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f"))
+	       (abs:IMSA (match_operand:IMSA 2 "msa_reg_operand" "f")))
 	   (match_dup 1)
 	   (match_dup 2)))]
   "ISA_HAS_MSA"
@@ -2185,8 +2187,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "smax<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
-	(smax:IMSA (match_operand:IMSA 1 "register_operand" "f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
+	(smax:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 		   (match_operand:IMSA 2 "reg_or_vector_same_simm5_operand" "f,Usv5")))]
   "ISA_HAS_MSA"
   "@
@@ -2196,8 +2198,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "umax<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
-	(umax:IMSA (match_operand:IMSA 1 "register_operand" "f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
+	(umax:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 		   (match_operand:IMSA 2 "reg_or_vector_same_uimm5_operand" "f,Uuv5")))]
   "ISA_HAS_MSA"
   "@
@@ -2207,10 +2209,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_min_a_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
 	(if_then_else:IMSA
-	   (lt (abs:IMSA (match_operand:IMSA 1 "register_operand" "f"))
-	       (abs:IMSA (match_operand:IMSA 2 "register_operand" "f")))
+	   (lt (abs:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f"))
+	       (abs:IMSA (match_operand:IMSA 2 "msa_reg_operand" "f")))
 	   (match_dup 1)
 	   (match_dup 2)))]
   "ISA_HAS_MSA"
@@ -2219,8 +2221,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "smin<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
-	(smin:IMSA (match_operand:IMSA 1 "register_operand" "f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
+	(smin:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 		   (match_operand:IMSA 2 "reg_or_vector_same_simm5_operand" "f,Usv5")))]
   "ISA_HAS_MSA"
   "@
@@ -2230,8 +2232,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "umin<mode>3"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
-	(umin:IMSA (match_operand:IMSA 1 "register_operand" "f,f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
+	(umin:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f,f")
 		   (match_operand:IMSA 2 "reg_or_vector_same_uimm5_operand" "f,Uuv5")))]
   "ISA_HAS_MSA"
   "@
@@ -2241,10 +2243,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_msub_q_<msafmt>"
-  [(set (match_operand:IMSA_WH 0 "register_operand" "=f")
-	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "register_operand" "0")
-			 (match_operand:IMSA_WH 2 "register_operand" "f")
-			 (match_operand:IMSA_WH 3 "register_operand" "f")]
+  [(set (match_operand:IMSA_WH 0 "msa_reg_operand" "=f")
+	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "msa_reg_operand" "0")
+			 (match_operand:IMSA_WH 2 "msa_reg_operand" "f")
+			 (match_operand:IMSA_WH 3 "msa_reg_operand" "f")]
 			UNSPEC_MSA_MSUB_Q))]
   "ISA_HAS_MSA"
   "msub_q.<msafmt>\t%w0,%w2,%w3"
@@ -2252,10 +2254,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_msubr_q_<msafmt>"
-  [(set (match_operand:IMSA_WH 0 "register_operand" "=f")
-	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "register_operand" "0")
-			 (match_operand:IMSA_WH 2 "register_operand" "f")
-			 (match_operand:IMSA_WH 3 "register_operand" "f")]
+  [(set (match_operand:IMSA_WH 0 "msa_reg_operand" "=f")
+	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "msa_reg_operand" "0")
+			 (match_operand:IMSA_WH 2 "msa_reg_operand" "f")
+			 (match_operand:IMSA_WH 3 "msa_reg_operand" "f")]
 			UNSPEC_MSA_MSUBR_Q))]
   "ISA_HAS_MSA"
   "msubr_q.<msafmt>\t%w0,%w2,%w3"
@@ -2263,9 +2265,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_mul_q_<msafmt>"
-  [(set (match_operand:IMSA_WH 0 "register_operand" "=f")
-	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "register_operand" "f")
-			 (match_operand:IMSA_WH 2 "register_operand" "f")]
+  [(set (match_operand:IMSA_WH 0 "msa_reg_operand" "=f")
+	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "msa_reg_operand" "f")
+			 (match_operand:IMSA_WH 2 "msa_reg_operand" "f")]
 			UNSPEC_MSA_MUL_Q))]
   "ISA_HAS_MSA"
   "mul_q.<msafmt>\t%w0,%w1,%w2"
@@ -2273,9 +2275,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_mulr_q_<msafmt>"
-  [(set (match_operand:IMSA_WH 0 "register_operand" "=f")
-	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "register_operand" "f")
-			 (match_operand:IMSA_WH 2 "register_operand" "f")]
+  [(set (match_operand:IMSA_WH 0 "msa_reg_operand" "=f")
+	(unspec:IMSA_WH [(match_operand:IMSA_WH 1 "msa_reg_operand" "f")
+			 (match_operand:IMSA_WH 2 "msa_reg_operand" "f")]
 			UNSPEC_MSA_MULR_Q))]
   "ISA_HAS_MSA"
   "mulr_q.<msafmt>\t%w0,%w1,%w2"
@@ -2283,8 +2285,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_nloc_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_NLOC))]
   "ISA_HAS_MSA"
   "nloc.<msafmt>\t%w0,%w1"
@@ -2292,16 +2294,16 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "clz<mode>2"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(clz:IMSA (match_operand:IMSA 1 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(clz:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "nlzc.<msafmt>\t%w0,%w1"
   [(set_attr "type" "simd_bit")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_nor_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f,f")
-	(and:IMSA (not:IMSA (match_operand:IMSA 1 "register_operand" "f,f"))
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f,f")
+	(and:IMSA (not:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f,f"))
 		  (not:IMSA (match_operand:IMSA 2 "reg_or_vector_same_val_operand" "f,Urv8"))))]
   "ISA_HAS_MSA"
   "@
@@ -2311,11 +2313,11 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_pckev_b"
-[(set (match_operand:V16QI 0 "register_operand" "=f")
+[(set (match_operand:V16QI 0 "msa_reg_operand" "=f")
       (vec_select:V16QI
 	(vec_concat:V32QI
-	  (match_operand:V16QI 1 "register_operand" "f")
-	  (match_operand:V16QI 2 "register_operand" "f"))
+	  (match_operand:V16QI 1 "msa_reg_operand" "f")
+	  (match_operand:V16QI 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 0) (const_int 2)
 		   (const_int 4) (const_int 6)
 		   (const_int 8) (const_int 10)
@@ -2330,11 +2332,11 @@ 
    (set_attr "mode" "V16QI")])
 
 (define_insn "msa_pckev_h"
-[(set (match_operand:V8HI 0 "register_operand" "=f")
+[(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
       (vec_select:V8HI
 	(vec_concat:V16HI
-	  (match_operand:V8HI 1 "register_operand" "f")
-	  (match_operand:V8HI 2 "register_operand" "f"))
+	  (match_operand:V8HI 1 "msa_reg_operand" "f")
+	  (match_operand:V8HI 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 0) (const_int 2)
 		   (const_int 4) (const_int 6)
 		   (const_int 8) (const_int 10)
@@ -2345,11 +2347,11 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_pckev_w"
-[(set (match_operand:V4SI 0 "register_operand" "=f")
+[(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
       (vec_select:V4SI
 	(vec_concat:V8SI
-	  (match_operand:V4SI 1 "register_operand" "f")
-	  (match_operand:V4SI 2 "register_operand" "f"))
+	  (match_operand:V4SI 1 "msa_reg_operand" "f")
+	  (match_operand:V4SI 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 0) (const_int 2)
 		   (const_int 4) (const_int 6)])))]
   "ISA_HAS_MSA"
@@ -2358,11 +2360,11 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_pckev_w_f"
-[(set (match_operand:V4SF 0 "register_operand" "=f")
+[(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
       (vec_select:V4SF
 	(vec_concat:V8SF
-	  (match_operand:V4SF 1 "register_operand" "f")
-	  (match_operand:V4SF 2 "register_operand" "f"))
+	  (match_operand:V4SF 1 "msa_reg_operand" "f")
+	  (match_operand:V4SF 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 0) (const_int 2)
 		   (const_int 4) (const_int 6)])))]
   "ISA_HAS_MSA"
@@ -2371,11 +2373,11 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_pckod_b"
-[(set (match_operand:V16QI 0 "register_operand" "=f")
+[(set (match_operand:V16QI 0 "msa_reg_operand" "=f")
       (vec_select:V16QI
 	(vec_concat:V32QI
-	  (match_operand:V16QI 1 "register_operand" "f")
-	  (match_operand:V16QI 2 "register_operand" "f"))
+	  (match_operand:V16QI 1 "msa_reg_operand" "f")
+	  (match_operand:V16QI 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 1) (const_int 3)
 		   (const_int 5) (const_int 7)
 		   (const_int 9) (const_int 11)
@@ -2390,11 +2392,11 @@ 
    (set_attr "mode" "V16QI")])
 
 (define_insn "msa_pckod_h"
-[(set (match_operand:V8HI 0 "register_operand" "=f")
+[(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
       (vec_select:V8HI
 	(vec_concat:V16HI
-	  (match_operand:V8HI 1 "register_operand" "f")
-	  (match_operand:V8HI 2 "register_operand" "f"))
+	  (match_operand:V8HI 1 "msa_reg_operand" "f")
+	  (match_operand:V8HI 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 1) (const_int 3)
 		   (const_int 5) (const_int 7)
 		   (const_int 9) (const_int 11)
@@ -2405,11 +2407,11 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "msa_pckod_w"
-[(set (match_operand:V4SI 0 "register_operand" "=f")
+[(set (match_operand:V4SI 0 "msa_reg_operand" "=f")
       (vec_select:V4SI
 	(vec_concat:V8SI
-	  (match_operand:V4SI 1 "register_operand" "f")
-	  (match_operand:V4SI 2 "register_operand" "f"))
+	  (match_operand:V4SI 1 "msa_reg_operand" "f")
+	  (match_operand:V4SI 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 1) (const_int 3)
 		   (const_int 5) (const_int 7)])))]
   "ISA_HAS_MSA"
@@ -2418,11 +2420,11 @@ 
    (set_attr "mode" "V4SI")])
 
 (define_insn "msa_pckod_w_f"
-[(set (match_operand:V4SF 0 "register_operand" "=f")
+[(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
       (vec_select:V4SF
 	(vec_concat:V8SF
-	  (match_operand:V4SF 1 "register_operand" "f")
-	  (match_operand:V4SF 2 "register_operand" "f"))
+	  (match_operand:V4SF 1 "msa_reg_operand" "f")
+	  (match_operand:V4SF 2 "msa_reg_operand" "f"))
 	(parallel [(const_int 1) (const_int 3)
 		   (const_int 5) (const_int 7)])))]
   "ISA_HAS_MSA"
@@ -2431,16 +2433,16 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "popcount<mode>2"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(popcount:IMSA (match_operand:IMSA 1 "register_operand" "f")))]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(popcount:IMSA (match_operand:IMSA 1 "msa_reg_operand" "f")))]
   "ISA_HAS_MSA"
   "pcnt.<msafmt>\t%w0,%w1"
   [(set_attr "type" "simd_pcnt")
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_sat_s_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
 		      (match_operand 2 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_SAT_S))]
   "ISA_HAS_MSA"
@@ -2449,8 +2451,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_sat_u_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
 		      (match_operand 2 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_SAT_U))]
   "ISA_HAS_MSA"
@@ -2459,9 +2461,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_shf_<msafmt_f>"
-  [(set (match_operand:MSA_WHB_W 0 "register_operand" "=f")
+  [(set (match_operand:MSA_WHB_W 0 "msa_reg_operand" "=f")
 	(vec_select:MSA_WHB_W
-	  (match_operand:MSA_WHB_W 1 "register_operand" "f")
+	  (match_operand:MSA_WHB_W 1 "msa_reg_operand" "f")
 	  (match_operand 2 "par_const_vector_shf_set_operand" "")))]
   "ISA_HAS_MSA"
 {
@@ -2479,9 +2481,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_srar_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_SRAR))]
   "ISA_HAS_MSA"
   "srar.<msafmt>\t%w0,%w1,%w2"
@@ -2489,8 +2491,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_srari_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
 		      (match_operand 2 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_SRARI))]
   "ISA_HAS_MSA"
@@ -2499,9 +2501,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_srlr_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_SRLR))]
   "ISA_HAS_MSA"
   "srlr.<msafmt>\t%w0,%w1,%w2"
@@ -2509,8 +2511,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_srlri_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
 		      (match_operand 2 "const_<bitimm>_operand" "")]
 		     UNSPEC_MSA_SRLRI))]
   "ISA_HAS_MSA"
@@ -2519,9 +2521,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_subs_s_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_SUBS_S))]
   "ISA_HAS_MSA"
   "subs_s.<msafmt>\t%w0,%w1,%w2"
@@ -2529,9 +2531,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_subs_u_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_SUBS_U))]
   "ISA_HAS_MSA"
   "subs_u.<msafmt>\t%w0,%w1,%w2"
@@ -2539,9 +2541,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_subsuu_s_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_SUBSUU_S))]
   "ISA_HAS_MSA"
   "subsuu_s.<msafmt>\t%w0,%w1,%w2"
@@ -2549,9 +2551,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_subsus_u_<msafmt>"
-  [(set (match_operand:IMSA 0 "register_operand" "=f")
-	(unspec:IMSA [(match_operand:IMSA 1 "register_operand" "f")
-		      (match_operand:IMSA 2 "register_operand" "f")]
+  [(set (match_operand:IMSA 0 "msa_reg_operand" "=f")
+	(unspec:IMSA [(match_operand:IMSA 1 "msa_reg_operand" "f")
+		      (match_operand:IMSA 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_SUBSUS_U))]
   "ISA_HAS_MSA"
   "subsus_u.<msafmt>\t%w0,%w1,%w2"
@@ -2559,9 +2561,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_sld_<msafmt_f>"
-  [(set (match_operand:MSA 0 "register_operand" "=f")
-	(unspec:MSA [(match_operand:MSA 1 "register_operand" "0")
-		     (match_operand:MSA 2 "register_operand" "f")
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
+	(unspec:MSA [(match_operand:MSA 1 "msa_reg_operand" "0")
+		     (match_operand:MSA 2 "msa_reg_operand" "f")
 		     (match_operand:SI 3 "reg_or_0_operand" "dJ")]
 		    UNSPEC_MSA_SLD))]
   "ISA_HAS_MSA"
@@ -2570,9 +2572,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_sldi_<msafmt_f>"
-  [(set (match_operand:MSA 0 "register_operand" "=f")
-	(unspec:MSA [(match_operand:MSA 1 "register_operand" "0")
-		     (match_operand:MSA 2 "register_operand" "f")
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
+	(unspec:MSA [(match_operand:MSA 1 "msa_reg_operand" "0")
+		     (match_operand:MSA 2 "msa_reg_operand" "f")
 		     (match_operand 3 "const_<indeximm>_operand" "")]
 		    UNSPEC_MSA_SLDI))]
   "ISA_HAS_MSA"
@@ -2581,9 +2583,9 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_splat_<msafmt_f>"
-  [(set (match_operand:MSA 0 "register_operand" "=f")
-	(unspec:MSA [(match_operand:MSA 1 "register_operand" "f")
-		     (match_operand:SI 2 "register_operand" "d")]
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
+	(unspec:MSA [(match_operand:MSA 1 "msa_reg_operand" "f")
+		     (match_operand:SI 2 "msa_reg_operand" "d")]
 		    UNSPEC_MSA_SPLAT))]
   "ISA_HAS_MSA"
   "splat.<msafmt>\t%w0,%w1[%z2]"
@@ -2591,10 +2593,10 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_splati_<msafmt_f>"
-  [(set (match_operand:MSA 0 "register_operand" "=f")
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
 	(vec_duplicate:MSA
 	  (vec_select:<UNITMODE>
-	    (match_operand:MSA 1 "register_operand" "f")
+	    (match_operand:MSA 1 "msa_reg_operand" "f")
 	    (parallel [(match_operand 2 "const_<indeximm>_operand" "")]))))]
   "ISA_HAS_MSA"
   "splati.<msafmt>\t%w0,%w1[%2]"
@@ -2602,8 +2604,8 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_splati_<msafmt_f>_scalar"
-  [(set (match_operand:FMSA 0 "register_operand" "=f")
-	(unspec:FMSA [(match_operand:<UNITMODE> 1 "register_operand" "f")]
+  [(set (match_operand:FMSA 0 "msa_reg_operand" "=f")
+	(unspec:FMSA [(match_operand:<UNITMODE> 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_SPLATI))]
   "ISA_HAS_MSA"
   "splati.<msafmt>\t%w0,%w1[0]"
@@ -2611,7 +2613,7 @@ 
    (set_attr "mode" "<MODE>")])
 
 (define_insn "msa_cfcmsa"
-  [(set (match_operand:SI 0 "register_operand" "=d")
+  [(set (match_operand:SI 0 "msa_reg_operand" "=d")
 	(unspec_volatile:SI [(match_operand 1 "const_uimm5_operand" "")]
 			    UNSPEC_MSA_CFCMSA))]
   "ISA_HAS_MSA"
@@ -2621,7 +2623,7 @@ 
 
 (define_insn "msa_ctcmsa"
   [(unspec_volatile [(match_operand 0 "const_uimm5_operand" "")
-		     (match_operand:SI 1 "register_operand" "d")]
+		     (match_operand:SI 1 "msa_reg_operand" "d")]
 		    UNSPEC_MSA_CTCMSA)]
   "ISA_HAS_MSA"
   "ctcmsa\t$%0,%1"
@@ -2629,9 +2631,9 @@ 
    (set_attr "mode" "SI")])
 
 (define_insn "msa_fexdo_h"
-  [(set (match_operand:V8HI 0 "register_operand" "=f")
-	(unspec:V8HI [(match_operand:V4SF 1 "register_operand" "f")
-		      (match_operand:V4SF 2 "register_operand" "f")]
+  [(set (match_operand:V8HI 0 "msa_reg_operand" "=f")
+	(unspec:V8HI [(match_operand:V4SF 1 "msa_reg_operand" "f")
+		      (match_operand:V4SF 2 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FEXDO))]
   "ISA_HAS_MSA"
   "fexdo.h\t%w0,%w1,%w2"
@@ -2639,18 +2641,18 @@ 
    (set_attr "mode" "V8HI")])
 
 (define_insn "vec_pack_trunc_v2df"
-  [(set (match_operand:V4SF 0 "register_operand" "=f")
+  [(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
 	(vec_concat:V4SF
-	  (float_truncate:V2SF (match_operand:V2DF 1 "register_operand" "f"))
-	  (float_truncate:V2SF (match_operand:V2DF 2 "register_operand" "f"))))]
+	  (float_truncate:V2SF (match_operand:V2DF 1 "msa_reg_operand" "f"))
+	  (float_truncate:V2SF (match_operand:V2DF 2 "msa_reg_operand" "f"))))]
   "ISA_HAS_MSA"
   "fexdo.w\t%w0,%w2,%w1"
   [(set_attr "type" "simd_fcvt")
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_fexupl_w"
-  [(set (match_operand:V4SF 0 "register_operand" "=f")
-	(unspec:V4SF [(match_operand:V8HI 1 "register_operand" "f")]
+  [(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
+	(unspec:V4SF [(match_operand:V8HI 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FEXUPL))]
   "ISA_HAS_MSA"
   "fexupl.w\t%w0,%w1"
@@ -2658,10 +2660,10 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_fexupl_d"
-  [(set (match_operand:V2DF 0 "register_operand" "=f")
+  [(set (match_operand:V2DF 0 "msa_reg_operand" "=f")
 	(float_extend:V2DF
 	(vec_select:V2SF
-	  (match_operand:V4SF 1 "register_operand" "f")
+	  (match_operand:V4SF 1 "msa_reg_operand" "f")
 	  (parallel [(const_int 2) (const_int 3)]))))]
   "ISA_HAS_MSA"
   "fexupl.d\t%w0,%w1"
@@ -2669,8 +2671,8 @@ 
    (set_attr "mode" "V2DF")])
 
 (define_insn "msa_fexupr_w"
-  [(set (match_operand:V4SF 0 "register_operand" "=f")
-	(unspec:V4SF [(match_operand:V8HI 1 "register_operand" "f")]
+  [(set (match_operand:V4SF 0 "msa_reg_operand" "=f")
+	(unspec:V4SF [(match_operand:V8HI 1 "msa_reg_operand" "f")]
 		     UNSPEC_MSA_FEXUPR))]
   "ISA_HAS_MSA"
   "fexupr.w\t%w0,%w1"
@@ -2678,10 +2680,10 @@ 
    (set_attr "mode" "V4SF")])
 
 (define_insn "msa_fexupr_d"
-  [(set (match_operand:V2DF 0 "register_operand" "=f")
+  [(set (match_operand:V2DF 0 "msa_reg_operand" "=f")
 	(float_extend:V2DF
 	(vec_select:V2SF
-	  (match_operand:V4SF 1 "register_operand" "f")
+	  (match_operand:V4SF 1 "msa_reg_operand" "f")
 	  (parallel [(const_int 0) (const_int 1)]))))]
   "ISA_HAS_MSA"
   "fexupr.d\t%w0,%w1"
@@ -2699,7 +2701,7 @@ 
 (define_insn "msa_<msabr>_<msafmt_f>"
  [(set (pc) (if_then_else
 	      (equality_op
-		(unspec:SI [(match_operand:MSA 1 "register_operand" "f")]
+		(unspec:SI [(match_operand:MSA 1 "msa_reg_operand" "f")]
 			    UNSPEC_MSA_BRANCH)
 		  (match_operand:SI 2 "const_0_operand"))
 		  (label_ref (match_operand 0))
@@ -2719,7 +2721,7 @@ 
 (define_insn "msa_<msabr>_v_<msafmt_f>"
  [(set (pc) (if_then_else
 	      (equality_op
-		(unspec:SI [(match_operand:MSA 1 "register_operand" "f")]
+		(unspec:SI [(match_operand:MSA 1 "msa_reg_operand" "f")]
 			    UNSPEC_MSA_BRANCH_V)
 		  (match_operand:SI 2 "const_0_operand"))
 		  (label_ref (match_operand 0))
@@ -2734,3 +2736,55 @@ 
  [(set_attr "type" "simd_branch")
   (set_attr "mode" "TI")
   (set_attr "compact_form" "never")])
+
+;; On big-endian targets we cannot use SUBREGs to refer to MSA register
+;; in different mode (see mips_can_change_mode_class).  This is used
+;; specifically during expansion of vec_unpack operations, which requires
+;; MSA register mode changes.
+(define_expand "msa_change_mode"
+  [(match_operand 0 "msa_reg_operand")
+   (match_operand 1 "msa_reg_operand")]
+  "ISA_HAS_MSA"
+{
+  gcc_assert (MSA_SUPPORTED_MODE_P (GET_MODE (operands[0]))
+              && MSA_SUPPORTED_MODE_P (GET_MODE (operands[1])));
+
+  if (!TARGET_BIG_ENDIAN)
+    emit_move_insn (operands[0],
+                    gen_lowpart (GET_MODE (operands[0]), operands[1]));
+  else
+    emit_move_insn (operands[0],
+                    gen_rtx_UNSPEC (GET_MODE (operands[0]),
+                                    gen_rtvec (1, operands[1]),
+                                    UNSPEC_MSA_CHANGE_MODE));
+
+  DONE;
+})
+
+(define_insn_and_split "*msa_change_mode_<mode>"
+  [(set (match_operand:MSA 0 "msa_reg_operand" "=f")
+    (unspec:MSA [(match_operand 1 "msa_reg_operand" "f")]
+      UNSPEC_MSA_CHANGE_MODE))]
+  "ISA_HAS_MSA && TARGET_BIG_ENDIAN
+   && MSA_SUPPORTED_MODE_P (GET_MODE (operands[1]))"
+  "#"
+  "&& reload_completed"
+  [(set (match_dup 0) (match_dup 1))]
+{
+  operands[1] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
+})
+
+;; A pattern for optimizing SUBREGs that have a reinterpreting effect
+;; on big-endian targets.
+(define_insn_and_split "*msa_mov<mode>_subreg_be"
+  [(set (match_operand:MSA 0 "nonimmediate_operand" "=f")
+    (unspec:MSA [(match_operand 1 "move_operand" "f")]
+      UNSPEC_MSA_SUBREG_BE))]
+  "ISA_HAS_MSA && TARGET_BIG_ENDIAN"
+  "#"
+  "&& reload_completed"
+  [(const_int 0)]
+{
+  mips_split_msa_subreg_move (operands[0], operands[1]);
+  DONE;
+})
diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h
index 32070fd..8b9d4bb 100644
--- a/gcc/config/mips/mips-protos.h
+++ b/gcc/config/mips/mips-protos.h
@@ -389,4 +389,6 @@  extern void mips_expand_vec_cond_expr (machine_mode, machine_mode, rtx *);
 /* Routines implemented in mips-d.c  */
 extern void mips_d_target_versions (void);
 
+extern void mips_split_msa_subreg_move (rtx, rtx);
+
 #endif /* ! GCC_MIPS_PROTOS_H */
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index c24dc71..b539f1f 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3715,6 +3715,119 @@  mips_legitimize_const_move (machine_mode mode, rtx dest, rtx src)
   mips_emit_move (dest, src);
 }
 
+/* Called only on big-endian targets.  See wether an MSA vector move from
+   SRC to DEST is effectively a (pair of) SHF instruction(s), because at least
+   one operand is a SUBREG of an MSA vector that has wider or narrower
+   elements.  Return true and emit the instruction if so.
+
+   VIEW_CONVERT (bitconvert) between the two vectors should change only the
+   compiler's interpretation of data, not the data itself, which is what
+   happens on big-endian targets.  Therefore, we insert one or two shuffle
+   instructions to keep the data in registers in a valid state.
+
+   Without this optimization, we would spill the SUBREG operand to stack in
+   one mode and reload it in the other, which is also valid, but obviously
+   a lot slower.  */
+
+static bool
+mips_maybe_expand_msa_subreg_move (rtx dest, rtx src)
+{
+  gcc_assert(TARGET_BIG_ENDIAN);
+
+  if (SUBREG_P (dest))
+    dest = SUBREG_REG (dest);
+  if (SUBREG_P (src))
+    src = SUBREG_REG (src);
+
+  /* The optimization handles two MSA REGs with different element size.  */
+  if (!REG_P (dest)
+      || !REG_P (src)
+      || (GET_MODE_UNIT_SIZE (GET_MODE (dest))
+	  == GET_MODE_UNIT_SIZE (GET_MODE (src))))
+    return false;
+
+  /* Generate *msa_mov<mode>_subreg_be.  */
+  rtx unspec = gen_rtx_UNSPEC (GET_MODE (dest),
+			       gen_rtvec (1, src),
+			       UNSPEC_MSA_SUBREG_BE);
+  emit_insn (gen_rtx_SET (dest, unspec));
+  return true;
+}
+
+/* Return a copy of X with mode MODE, without changing its other
+   attributes.  Unlike gen_lowpart, this doesn't care whether the mode
+   change is valid.  */
+
+static rtx
+mips_replace_reg_mode (rtx x, machine_mode mode)
+{
+  if (GET_MODE (x) == mode)
+    return x;
+
+  x = shallow_copy_rtx (x);
+  set_mode_and_regno (x, mode, REGNO (x));
+  return x;
+}
+
+/* Split a *msa_mov<mode>_subreg_be pattern with the given operands.  */
+
+void
+mips_split_msa_subreg_move (rtx dest, rtx src)
+{
+  /* Decide how many and which SHF operations we need.  The size ratio of
+     machine modes defines the number of operations, while the mode with the
+     narrower elements determines the mode of the operands.  */
+  int shf_value_1, shf_value_2 = 0xb1;
+  machine_mode mode_with_wider_elts = GET_MODE (dest);
+  machine_mode mode_with_narrower_elts = GET_MODE (src);
+  unsigned char wider_mode_size, narrower_mode_size;
+  rtx x;
+
+  wider_mode_size = GET_MODE_UNIT_SIZE (mode_with_wider_elts);
+  narrower_mode_size = GET_MODE_UNIT_SIZE (mode_with_narrower_elts);
+
+  if (wider_mode_size < narrower_mode_size)
+    {
+      std::swap (mode_with_wider_elts, mode_with_narrower_elts);
+      std::swap (wider_mode_size, narrower_mode_size);
+    }
+
+  int size_ratio = wider_mode_size / narrower_mode_size;
+  switch (size_ratio)
+    {
+    case 8:
+    case 4:
+      shf_value_1 = 0x1b;
+      break;
+    case 2:
+      shf_value_1 = 0xb1;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Emit the first SHF instruction with appropriate modes.  */
+  dest = mips_replace_reg_mode (dest, mode_with_narrower_elts);
+  src = mips_replace_reg_mode (src, mode_with_narrower_elts);
+  x = mips_gen_const_int_vector_shuffle (mode_with_narrower_elts,
+					 shf_value_1);
+  x = gen_rtx_VEC_SELECT (mode_with_narrower_elts, src, x);
+  x = gen_rtx_SET (dest, x);
+  emit_insn (x);
+
+  /* Emit the second SHF instruction (if needed) with appropriate modes.  */
+  if (size_ratio == 8)
+    {
+      dest = mips_replace_reg_mode (dest, V4SImode);
+      src = mips_replace_reg_mode (dest, V4SImode);
+      x = mips_gen_const_int_vector_shuffle (V4SImode,
+					     shf_value_2);
+      x = gen_rtx_VEC_SELECT (V4SImode, dest, x);
+      x = gen_rtx_SET (dest, x);
+      emit_insn (x);
+    }
+}
+
 /* If (set DEST SRC) is not a valid move instruction, emit an equivalent
    sequence that is valid.  */
 
@@ -3742,6 +3855,33 @@  mips_legitimize_move (machine_mode mode, rtx dest, rtx src)
       set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
       return true;
     }
+
+  if (TARGET_BIG_ENDIAN
+      && MSA_SUPPORTED_MODE_P (GET_MODE (dest))
+      && MSA_SUPPORTED_MODE_P (GET_MODE (src)))
+    {
+      /* SRC or DEST with an MSA mode have an allocated hard register only if
+	 they are function call arguments or return values.  In that case,
+	 force their machine mode to V2DImode or V4SI mode, depending on the
+	 target size.  This will produce shuffle instruction(s) which will
+	 reorder the elements within a vector, so that they conform to the
+	 calling convention.  This fixes the discrepancy between calling
+	 conventions of MSA and non-MSA builds.  */
+      if (REG_P (dest)
+	  && HARD_REGISTER_P (dest)
+	  && GP_REG_P (REGNO (dest)))
+	dest = mips_replace_reg_mode (dest, TARGET_64BIT ? V2DImode : V4SImode);
+
+      if (REG_P (src)
+	  && HARD_REGISTER_P (src)
+	  && GP_REG_P (REGNO (src)))
+	src = mips_replace_reg_mode (src, TARGET_64BIT ? V2DImode : V4SImode);
+
+      /* See whether MSA SUBREG move can be replaced with shuffle(s).  */
+      if (mips_maybe_expand_msa_subreg_move (dest, src))
+	return true;
+    }
+
   return false;
 }
 
@@ -4934,12 +5074,12 @@  mips_split_128bit_move (rtx dest, rtx src)
       if (!TARGET_64BIT)
 	{
 	  if (GET_MODE (dest) != V4SImode)
-	    new_dest = simplify_gen_subreg (V4SImode, dest, GET_MODE (dest), 0);
+	    new_dest = mips_replace_reg_mode (dest, V4SImode);
 	}
       else
 	{
 	  if (GET_MODE (dest) != V2DImode)
-	    new_dest = simplify_gen_subreg (V2DImode, dest, GET_MODE (dest), 0);
+	    new_dest = mips_replace_reg_mode (dest, V2DImode);
 	}
 
       for (byte = 0, index = 0; byte < GET_MODE_SIZE (TImode);
@@ -4962,12 +5102,12 @@  mips_split_128bit_move (rtx dest, rtx src)
       if (!TARGET_64BIT)
 	{
 	  if (GET_MODE (src) != V4SImode)
-	    new_src = simplify_gen_subreg (V4SImode, src, GET_MODE (src), 0);
+	    new_src = mips_replace_reg_mode (src, V4SImode);
 	}
       else
 	{
 	  if (GET_MODE (src) != V2DImode)
-	    new_src = simplify_gen_subreg (V2DImode, src, GET_MODE (src), 0);
+	    new_src = mips_replace_reg_mode (src, V2DImode);
 	}
 
       for (byte = 0, index = 0; byte < GET_MODE_SIZE (TImode);
@@ -5023,7 +5163,7 @@  mips_split_msa_copy_d (rtx dest, rtx src, rtx index,
      from the higher index.  */
   rtx low = mips_subword (dest, false);
   rtx high = mips_subword (dest, true);
-  rtx new_src = simplify_gen_subreg (V4SImode, src, GET_MODE (src), 0);
+  rtx new_src = mips_replace_reg_mode (src, V4SImode);
 
   emit_insn (gen_fn (low, new_src, GEN_INT (INTVAL (index) * 2)));
   emit_insn (gen_fn (high, new_src, GEN_INT (INTVAL (index) * 2 + 1)));
@@ -5044,8 +5184,8 @@  mips_split_msa_insert_d (rtx dest, rtx src1, rtx index, rtx src2)
      from the higher index.  */
   rtx low = mips_subword (src2, false);
   rtx high = mips_subword (src2, true);
-  rtx new_dest = simplify_gen_subreg (V4SImode, dest, GET_MODE (dest), 0);
-  rtx new_src1 = simplify_gen_subreg (V4SImode, src1, GET_MODE (src1), 0);
+  rtx new_dest = mips_replace_reg_mode (dest, V4SImode);
+  rtx new_src1 = mips_replace_reg_mode (src1, V4SImode);
   i = exact_log2 (INTVAL (index));
   gcc_assert (i != -1);
 
@@ -5077,7 +5217,7 @@  mips_split_msa_fill_d (rtx dest, rtx src)
       low = mips_subword (src, false);
       high = mips_subword (src, true);
     }
-  rtx new_dest = simplify_gen_subreg (V4SImode, dest, GET_MODE (dest), 0);
+  rtx new_dest = mips_replace_reg_mode (dest, V4SImode);
   emit_insn (gen_msa_fill_w (new_dest, low));
   emit_insn (gen_msa_insert_w (new_dest, high, new_dest, GEN_INT (1 << 1)));
   emit_insn (gen_msa_insert_w (new_dest, high, new_dest, GEN_INT (1 << 3)));
@@ -13012,9 +13152,13 @@  mips_can_change_mode_class (machine_mode from,
       && INTEGRAL_MODE_P (from) && INTEGRAL_MODE_P (to))
     return true;
 
-  /* Allow conversions between different MSA vector modes.  */
+  /* Allow conversions between different MSA vector modes.
+     On big-endian targets the MSA register layout doesn't match
+     its memory layout, so we disallow mode change that would
+     result in lane width change.  */
   if (MSA_SUPPORTED_MODE_P (from) && MSA_SUPPORTED_MODE_P (to))
-    return true;
+    return !TARGET_BIG_ENDIAN
+	    || (GET_MODE_UNIT_SIZE (from) == GET_MODE_UNIT_SIZE (to));
 
   /* Otherwise, there are several problems with changing the modes of
      values in floating-point registers:
@@ -21731,7 +21875,7 @@  mips_expand_vec_unpack (rtx operands[2], bool unsigned_p, bool high_p)
       dest = gen_reg_rtx (imode);
 
       emit_insn (unpack (dest, operands[1], tmp));
-      emit_move_insn (operands[0], gen_lowpart (GET_MODE (operands[0]), dest));
+      emit_insn (gen_msa_change_mode (operands[0], dest));
       return;
     }
 
diff --git a/gcc/config/mips/predicates.md b/gcc/config/mips/predicates.md
index 0b0b004..ec4d852 100644
--- a/gcc/config/mips/predicates.md
+++ b/gcc/config/mips/predicates.md
@@ -634,3 +634,8 @@ 
 (define_predicate "reg_or_vector_same_uimm6_operand"
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "const_vector_same_uimm6_operand")))
+
+(define_predicate "msa_reg_operand"
+  (if_then_else (match_test "TARGET_BIG_ENDIAN")
+       (match_code "reg")
+       (match_operand 0 "register_operand")))
diff --git a/gcc/testsuite/gcc.target/mips/inter/msa-inter.exp b/gcc/testsuite/gcc.target/mips/inter/msa-inter.exp
new file mode 100644
index 0000000..62aab64
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/inter/msa-inter.exp
@@ -0,0 +1,67 @@ 
+# Copyright (C) 2019 Free Software Foundation, Inc.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3.  If not see
+# <http://www.gnu.org/licenses/>.
+
+# Run calling convention compatibility tests for vector types in which the "alt"
+# compiler uses -mmsa.
+
+load_lib gcc-dg.exp
+
+# Check whether we can execute MSA code.
+if { ![check_mips_msa_hw_available] } {
+    return
+}
+
+# Save the old value of CFLAGS_FOR_TARGET, if any.
+global saved_CFLAGS_FOR_TARGET
+if { [info exists CFLAGS_FOR_TARGET] } {
+    set saved_CFLAGS_FOR_TARGET $CFLAGS_FOR_TARGET
+} else {
+    unset -nocomplain saved_CFLAGS_FOR_TARGET
+}
+
+# The "alt" compiler is the normal compiler with an extra "-mmsa" argument.
+proc compat-use-alt-compiler { } {
+    global saved_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET
+
+    if { [info exists saved_CFLAGS_FOR_TARGET] } {
+        set CFLAGS_FOR_TARGET [concat $saved_CFLAGS_FOR_TARGET "-mmsa"]
+    } else {
+        set CFLAGS_FOR_TARGET "-mmsa"
+    }
+}
+
+# Make the compiler under test the default.
+proc compat-use-tst-compiler { } {
+    global saved_CFLAGS_FOR_TARGET CFLAGS_FOR_TARGET
+
+    if { [info exists saved_CFLAGS_FOR_TARGET] } {
+        set CFLAGS_FOR_TARGET $saved_CFLAGS_FOR_TARGET
+    } else {
+        unset -nocomplain CFLAGS_FOR_TARGET
+    }
+}
+
+load_lib compat.exp
+
+gcc_init
+foreach src [lsort [find $srcdir/$subdir msa_*_main.c]] {
+    if { [runtest_file_p $runtests $src] } {
+        compat-execute $src "msa_inter" 1
+    }
+}
+compat-use-tst-compiler
diff --git a/gcc/testsuite/gcc.target/mips/inter/msa_1.h b/gcc/testsuite/gcc.target/mips/inter/msa_1.h
new file mode 100644
index 0000000..12114a9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/inter/msa_1.h
@@ -0,0 +1,23 @@ 
+typedef signed char v16i8 __attribute__ ((vector_size(16)));
+typedef short v8i16 __attribute__ ((vector_size(16)));
+typedef int v4i32 __attribute__ ((vector_size(16)));
+typedef long long v2i64 __attribute__ ((vector_size(16)));
+typedef unsigned char v16u8 __attribute__ ((vector_size(16)));
+typedef unsigned short v8u16 __attribute__ ((vector_size(16)));
+typedef unsigned int v4u32 __attribute__ ((vector_size(16)));
+typedef unsigned long long v2u64 __attribute__ ((vector_size(16)));
+typedef float v4f32 __attribute__ ((vector_size(16)));
+typedef double v2f64 __attribute__ ((vector_size(16)));
+
+
+#define ITERATE_FOR_ALL_TYPES(FUNC) \
+  FUNC (v16i8, 16) \
+  FUNC (v8i16, 8) \
+  FUNC (v4i32, 4) \
+  FUNC (v2i64, 2) \
+  FUNC (v16u8, 16) \
+  FUNC (v8u16, 8) \
+  FUNC (v4u32, 4) \
+  FUNC (v2u64, 2) \
+  FUNC (v4f32, 4) \
+  FUNC (v2f64, 2)
diff --git a/gcc/testsuite/gcc.target/mips/inter/msa_1_main.c b/gcc/testsuite/gcc.target/mips/inter/msa_1_main.c
new file mode 100644
index 0000000..0d17c83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/inter/msa_1_main.c
@@ -0,0 +1,8 @@ 
+extern void test (void);
+
+int
+main (void)
+{
+  test ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/mips/inter/msa_1_x.c b/gcc/testsuite/gcc.target/mips/inter/msa_1_x.c
new file mode 100644
index 0000000..f3d43ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/inter/msa_1_x.c
@@ -0,0 +1,35 @@ 
+#include "msa_1.h"
+
+#define INIT_2  {1, 2}
+#define INIT_4  {1, 2, 3, 4}
+#define INIT_8  {1, 2, 3, 4, 5, 6, 7, 8}
+#define INIT_16 {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 ,14 ,15 ,16}
+
+#define TEST(TYPE, NUM)                                         \
+__attribute__ ((noinline)) static void                          \
+test_ ## TYPE ##_caller (void)                                  \
+{                                                               \
+  extern TYPE test_ ## TYPE ##_callee (TYPE, const TYPE*);      \
+  TYPE vect = (TYPE) INIT_ ## NUM;                              \
+  TYPE res = test_ ## TYPE ## _callee (vect, &vect);            \
+  if (__builtin_memcmp (&vect, &res, sizeof vect))              \
+    __builtin_abort();                                          \
+}
+
+ITERATE_FOR_ALL_TYPES(TEST)
+
+#undef TEST
+#undef INIT_2
+#undef INIT_4
+#undef INIT_8
+#undef INIT_16
+
+#define RUN_TEST(TYPE, NUM) test_ ## TYPE ##_caller ();
+
+void
+test (void)
+{
+  ITERATE_FOR_ALL_TYPES(RUN_TEST)
+}
+
+#undef RUN_TEST
diff --git a/gcc/testsuite/gcc.target/mips/inter/msa_1_y.c b/gcc/testsuite/gcc.target/mips/inter/msa_1_y.c
new file mode 100644
index 0000000..250df27
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/inter/msa_1_y.c
@@ -0,0 +1,14 @@ 
+#include "msa_1.h"
+
+#define TEST(TYPE, NUM)                                       \
+TYPE                                                          \
+test_ ## TYPE ##_callee (TYPE vect, const TYPE* pvect)        \
+{                                                             \
+  if (__builtin_memcmp (&vect, pvect, sizeof vect))           \
+    __builtin_abort();                                        \
+  return *pvect;                                              \
+}
+
+ITERATE_FOR_ALL_TYPES(TEST)
+
+#undef TEST