diff mbox

[MIPS] Alter default number of single-precision registers

Message ID 6D39441BF12EF246A7ABCE6654B0235351A231@LEMAIL01.le.imgtec.org
State New
Headers show

Commit Message

Matthew Fortune April 29, 2014, 1:40 p.m. UTC
Hi Richard,

When MIPSr1 introduced the ability to use odd-numbered single-precision
registers some implementations continued to only support even-numbered
single-precision registers.  Notably, loongson3a in FR=0 mode only
permits the even-numbered registers to be used.  For this reason and
also to coincide with other FP ABI related changes we are reducing the
number of single precision floating-point registers available for
generic architectures: MIPS32, MIPS32r2, MIPS64, MIP64r1 when using
-mfp32.

Targeting or tuning for a specific MIPS implementation which is known to
have odd-numbered single-precision registers usable will continue to make
use of all 32 registers. The -modd-spreg option has no effect on the
availability of odd-numbered single precision registers for -mfp64.

This patch also implements REGISTER_PREFIX to simplify the use of command
line options like -ffixed-reg which take a register name as an argument
and the $ (dollar) in MIPS register names makes this more awkward than
necessary.

Suggestions for better option names are welcome, also better approaches
to the tests are welcome. I'm simply relying on an ICE when no registers
are available to check the implementation.

Tested with mips-mti-linux-gnu.

Regards,
Matthew

2014-04-29  Matthew Fortune <matthew.fortune@imgtec.com>

gcc/
        * config/mips/mips-cpus.def: Add PTF_AVOID_ODD_SPREG to generic
	   mips32, mips32r2, mips64, mips64r2 and loongson3a.
	   * config/mips/mips.c: (mips_option_override) Implement -modd-spreg 
	   and defaults.
        * config/mips/mips.h: (PTF_AVOID_ODD_SPREG) Define.
        (TARGET_CPU_CPP_BUILTINS) Add _MIPS_SPFPSET builtin define.
        (ISA_HAS_ODD_SPREG) Define.  (REGISTER_PREFIX) Define.
        (MIN_FPRS_PER_FMT) Redefine in terms of TARGET_ODD_SPREG.

gcc/testsuite/

        * gcc.target/mips/mips.exp: Add -ffixed-f* to the option groups,
        Add -m[no-]odd-spreg.  Use _MIPS_SPFPSET to determine default
        odd-spreg option.  Account for -modd-spreg in minimum arch code.
        * gcc.target/mips/oddspreg-1.c: New.
        * gcc.target/mips/oddspreg-2.c: New.
        * gcc.target/mips/oddspreg-3.c: New.
        * gcc.target/mips/oddspreg-4.c: New. 
        * gcc.target/mips/oddspreg-5.c: New. 
        * gcc.target/mips/oddspreg-6.c: New.
---
 gcc/config/mips/mips-cpus.def              |   15 ++++++++++-----
 gcc/config/mips/mips.c                     |   15 +++++++++++++++
 gcc/config/mips/mips.h                     |   25 ++++++++++++++++++++++---
 gcc/config/mips/mips.opt                   |    4 ++++
 gcc/testsuite/gcc.target/mips/mips.exp     |   25 ++++++++++++++++++++++++-
 gcc/testsuite/gcc.target/mips/oddspreg-1.c |   14 ++++++++++++++
 gcc/testsuite/gcc.target/mips/oddspreg-2.c |   13 +++++++++++++
 gcc/testsuite/gcc.target/mips/oddspreg-3.c |   13 +++++++++++++
 gcc/testsuite/gcc.target/mips/oddspreg-4.c |   13 +++++++++++++
 gcc/testsuite/gcc.target/mips/oddspreg-5.c |   15 +++++++++++++++
 10 files changed, 143 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/oddspreg-1.c
 create mode 100644 gcc/testsuite/gcc.target/mips/oddspreg-2.c
 create mode 100644 gcc/testsuite/gcc.target/mips/oddspreg-3.c
 create mode 100644 gcc/testsuite/gcc.target/mips/oddspreg-4.c
 create mode 100644 gcc/testsuite/gcc.target/mips/oddspreg-5.c
 create mode 100644 gcc/testsuite/gcc.target/mips/oddspreg-6.c

Comments

Richard Sandiford April 30, 2014, 6:44 a.m. UTC | #1
Matthew Fortune <Matthew.Fortune@imgtec.com> writes:
> Hi Richard,
>
> When MIPSr1 introduced the ability to use odd-numbered single-precision
> registers some implementations continued to only support even-numbered
> single-precision registers.  Notably, loongson3a in FR=0 mode only
> permits the even-numbered registers to be used.  For this reason and
> also to coincide with other FP ABI related changes we are reducing the
> number of single precision floating-point registers available for
> generic architectures: MIPS32, MIPS32r2, MIPS64, MIP64r1 when using
> -mfp32.
>
> Targeting or tuning for a specific MIPS implementation which is known to
> have odd-numbered single-precision registers usable will continue to make
> use of all 32 registers. The -modd-spreg option has no effect on the
> availability of odd-numbered single precision registers for -mfp64.
>
> This patch also implements REGISTER_PREFIX to simplify the use of command
> line options like -ffixed-reg which take a register name as an argument
> and the $ (dollar) in MIPS register names makes this more awkward than
> necessary.
>
> Suggestions for better option names are welcome, also better approaches
> to the tests are welcome. I'm simply relying on an ICE when no registers
> are available to check the implementation.

One way would be something like:

  void
  foo (void)
  {
    register float foo asm ("$f1");
    asm volatile ("" : "=f" (foo));
  }

which gives:

  error: register specified for ‘foo’ isn’t suitable for data type

when odd FP regs are disallowed.

You need to document the new option in the texi file.

> diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
> index 45256e9..b012dfd 100644
> --- a/gcc/config/mips/mips.c
> +++ b/gcc/config/mips/mips.c
> @@ -17120,6 +17120,21 @@ mips_option_override (void)
>      warning (0, "the %qs architecture does not support madd or msub"
>  	     " instructions", mips_arch_info->name);
>  
> +  /* If neither -modd-spreg nor -mno-odd-spreg was given on the command
> +     line, set MASK_ODD_SPREG bsaed on the target architecture, ABI and
> +     tuning flags.  */
> +  if ((target_flags_explicit & MASK_ODD_SPREG) == 0)
> +    {
> +      if (ISA_HAS_ODD_SPREG
> +	  && ((mips_tune_info->tune_flags & PTF_AVOID_ODD_SPREG) == 0))
> +	target_flags |= MASK_ODD_SPREG;
> +      else
> +	target_flags &= ~MASK_ODD_SPREG;
> +    }
> +  else if (TARGET_ODD_SPREG && !ISA_HAS_ODD_SPREG)
> +    warning (0, "the %qs architecture does not support odd single-precision"
> +	     " registers", mips_arch_info->name);

I think this should be an -march decision rather than an -mtune decision.
The two existing PTF_s (which were supposed to be "processor tuning flags")
really are -mtune decisions, since the question isn't whether the features
are available (that's given accurately by ISA_HAS_*) but whether it's a good
idea to use them.

ISA_HAS_ODD_SPREG should probably be false for loongson !TARGET_FLOAT64.
Then the decision here is whether mips_arch_info is the generic ISA or not.
We could add a new flag for that (and rename "tune_flags" to simply "flags"
and update the commentary) but strncmp (mips_arch_info->name, "mips", 4)
should work too.

As you can tell, this whole what-ISA-has-what area is very old and
needs a rework.  It predates the current option machinery (and certainly
the use of the option machinery in the driver) by many years...

> @@ -1268,6 +1282,12 @@ struct mips_cpu_info {
>  /* By default, turn on GDB extensions.  */
>  #define DEFAULT_GDB_EXTENSIONS 1
>  
> +/* Registers may have a prefix which can be ignored when matching
> +   user asm and register definitions.  */
> +#ifndef REGISTER_PREFIX
> +#define REGISTER_PREFIX		"$"
> +#endif
> +
>  /* Local compiler-generated symbols must have a prefix that the assembler
>     understands.   By default, this is $, although some targets (e.g.,
>     NetBSD-ELF) need to override this.  */

This is OK to commit as an independent patch, thanks.

Thanks,
Richard
Matthew Fortune April 30, 2014, 7:50 a.m. UTC | #2
Richard Sandiford <rdsandiford@googlemail.com> writes:
> Matthew Fortune <Matthew.Fortune@imgtec.com> writes:

> > Hi Richard,

> >

> > When MIPSr1 introduced the ability to use odd-numbered

> > single-precision registers some implementations continued to only

> > support even-numbered single-precision registers.  Notably,

> loongson3a

> > in FR=0 mode only permits the even-numbered registers to be used.

> For

> > this reason and also to coincide with other FP ABI related changes we

> > are reducing the number of single precision floating-point registers

> > available for generic architectures: MIPS32, MIPS32r2, MIPS64,

> MIP64r1

> > when using -mfp32.

> >

> > Targeting or tuning for a specific MIPS implementation which is known

> > to have odd-numbered single-precision registers usable will continue

> > to make use of all 32 registers. The -modd-spreg option has no effect

> > on the availability of odd-numbered single precision registers for -

> mfp64.

> >

> > This patch also implements REGISTER_PREFIX to simplify the use of

> > command line options like -ffixed-reg which take a register name as

> an

> > argument and the $ (dollar) in MIPS register names makes this more

> > awkward than necessary.

> >

> > Suggestions for better option names are welcome, also better

> > approaches to the tests are welcome. I'm simply relying on an ICE

> when

> > no registers are available to check the implementation.

> 

> One way would be something like:

> 

>   void

>   foo (void)

>   {

>     register float foo asm ("$f1");

>     asm volatile ("" : "=f" (foo));

>   }

> 

> which gives:

> 

>   error: register specified for ‘foo’ isn’t suitable for data type

> 

> when odd FP regs are disallowed.


Yes that's blatantly obvious :-). I took these tests from my work on
the FPXX ABI which I can't find a way to test using inline asm and
constraints. (patch due soon).

> You need to document the new option in the texi file.


Will do.

> > diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index

> > 45256e9..b012dfd 100644

> > --- a/gcc/config/mips/mips.c

> > +++ b/gcc/config/mips/mips.c

> > @@ -17120,6 +17120,21 @@ mips_option_override (void)

> >      warning (0, "the %qs architecture does not support madd or msub"

> >  	     " instructions", mips_arch_info->name);

> >

> > +  /* If neither -modd-spreg nor -mno-odd-spreg was given on the

> command

> > +     line, set MASK_ODD_SPREG bsaed on the target architecture, ABI

> and

> > +     tuning flags.  */

> > +  if ((target_flags_explicit & MASK_ODD_SPREG) == 0)

> > +    {

> > +      if (ISA_HAS_ODD_SPREG

> > +	  && ((mips_tune_info->tune_flags & PTF_AVOID_ODD_SPREG) == 0))

> > +	target_flags |= MASK_ODD_SPREG;

> > +      else

> > +	target_flags &= ~MASK_ODD_SPREG;

> > +    }

> > +  else if (TARGET_ODD_SPREG && !ISA_HAS_ODD_SPREG)

> > +    warning (0, "the %qs architecture does not support odd single-

> precision"

> > +	     " registers", mips_arch_info->name);

> 

> I think this should be an -march decision rather than an -mtune

> decision.

> The two existing PTF_s (which were supposed to be "processor tuning

> flags") really are -mtune decisions, since the question isn't whether

> the features are available (that's given accurately by ISA_HAS_*) but

> whether it's a good idea to use them.

> 

> ISA_HAS_ODD_SPREG should probably be false for loongson

> !TARGET_FLOAT64.

> Then the decision here is whether mips_arch_info is the generic ISA or

> not.

> We could add a new flag for that (and rename "tune_flags" to simply

> "flags"

> and update the commentary) but strncmp (mips_arch_info->name, "mips",

> 4) should work too.


If we make ISA_HAS_ODD_SPREG return false for:
loongson3a && !TARGET_FLOAT64
Then the tuning option starts to make sense again as the generic mips
architectures do support the odd numbered registers but for
compatibility reasons they should be avoided. 

> As you can tell, this whole what-ISA-has-what area is very old and

> needs a rework.  It predates the current option machinery (and

> certainly the use of the option machinery in the driver) by many

> years...

> > @@ -1268,6 +1282,12 @@ struct mips_cpu_info {

> >  /* By default, turn on GDB extensions.  */  #define

> > DEFAULT_GDB_EXTENSIONS 1

> >

> > +/* Registers may have a prefix which can be ignored when matching

> > +   user asm and register definitions.  */ #ifndef REGISTER_PREFIX

> > +#define REGISTER_PREFIX		"$"

> > +#endif

> > +

> >  /* Local compiler-generated symbols must have a prefix that the

> assembler

> >     understands.   By default, this is $, although some targets

> (e.g.,

> >     NetBSD-ELF) need to override this.  */

> 

> This is OK to commit as an independent patch, thanks.


OK. We are waiting for our updated copyright assignment papers to be
completed but will prepare this separately. We are going to end up
with a few patches queued on assignment.

Regards,
Matthew
Richard Sandiford April 30, 2014, 8 a.m. UTC | #3
Matthew Fortune <Matthew.Fortune@imgtec.com> writes:
> Richard Sandiford <rdsandiford@googlemail.com> writes:
>> Matthew Fortune <Matthew.Fortune@imgtec.com> writes:
>> > Hi Richard,
>> >
>> > When MIPSr1 introduced the ability to use odd-numbered
>> > single-precision registers some implementations continued to only
>> > support even-numbered single-precision registers.  Notably,
>> loongson3a
>> > in FR=0 mode only permits the even-numbered registers to be used.
>> For
>> > this reason and also to coincide with other FP ABI related changes we
>> > are reducing the number of single precision floating-point registers
>> > available for generic architectures: MIPS32, MIPS32r2, MIPS64,
>> MIP64r1
>> > when using -mfp32.
>> >
>> > Targeting or tuning for a specific MIPS implementation which is known
>> > to have odd-numbered single-precision registers usable will continue
>> > to make use of all 32 registers. The -modd-spreg option has no effect
>> > on the availability of odd-numbered single precision registers for -
>> mfp64.
>> >
>> > This patch also implements REGISTER_PREFIX to simplify the use of
>> > command line options like -ffixed-reg which take a register name as
>> an
>> > argument and the $ (dollar) in MIPS register names makes this more
>> > awkward than necessary.
>> >
>> > Suggestions for better option names are welcome, also better
>> > approaches to the tests are welcome. I'm simply relying on an ICE
>> when
>> > no registers are available to check the implementation.
>> 
>> One way would be something like:
>> 
>>   void
>>   foo (void)
>>   {
>>     register float foo asm ("$f1");
>>     asm volatile ("" : "=f" (foo));
>>   }
>> 
>> which gives:
>> 
>>   error: register specified for ‘foo’ isn’t suitable for data type
>> 
>> when odd FP regs are disallowed.
>
> Yes that's blatantly obvious :-). I took these tests from my work on
> the FPXX ABI which I can't find a way to test using inline asm and
> constraints. (patch due soon).
>
>> You need to document the new option in the texi file.
>
> Will do.
>
>> > diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index
>> > 45256e9..b012dfd 100644
>> > --- a/gcc/config/mips/mips.c
>> > +++ b/gcc/config/mips/mips.c
>> > @@ -17120,6 +17120,21 @@ mips_option_override (void)
>> >      warning (0, "the %qs architecture does not support madd or msub"
>> >  	     " instructions", mips_arch_info->name);
>> >
>> > +  /* If neither -modd-spreg nor -mno-odd-spreg was given on the
>> command
>> > +     line, set MASK_ODD_SPREG bsaed on the target architecture, ABI
>> and
>> > +     tuning flags.  */
>> > +  if ((target_flags_explicit & MASK_ODD_SPREG) == 0)
>> > +    {
>> > +      if (ISA_HAS_ODD_SPREG
>> > +	  && ((mips_tune_info->tune_flags & PTF_AVOID_ODD_SPREG) == 0))
>> > +	target_flags |= MASK_ODD_SPREG;
>> > +      else
>> > +	target_flags &= ~MASK_ODD_SPREG;
>> > +    }
>> > +  else if (TARGET_ODD_SPREG && !ISA_HAS_ODD_SPREG)
>> > +    warning (0, "the %qs architecture does not support odd single-
>> precision"
>> > +	     " registers", mips_arch_info->name);
>> 
>> I think this should be an -march decision rather than an -mtune
>> decision.
>> The two existing PTF_s (which were supposed to be "processor tuning
>> flags") really are -mtune decisions, since the question isn't whether
>> the features are available (that's given accurately by ISA_HAS_*) but
>> whether it's a good idea to use them.
>> 
>> ISA_HAS_ODD_SPREG should probably be false for loongson
>> !TARGET_FLOAT64.
>> Then the decision here is whether mips_arch_info is the generic ISA or
>> not.
>> We could add a new flag for that (and rename "tune_flags" to simply
>> "flags"
>> and update the commentary) but strncmp (mips_arch_info->name, "mips",
>> 4) should work too.
>
> If we make ISA_HAS_ODD_SPREG return false for:
> loongson3a && !TARGET_FLOAT64
> Then the tuning option starts to make sense again as the generic mips
> architectures do support the odd numbered registers but for
> compatibility reasons they should be avoided. 

-march is "which instructions can I use?" and -mtune is "which instructions
give good performance?".  My understanding is that you wanted to disable
the instructions for mips32r2 etc. so that they can be safely linked
with loongson3a code, in which case it's an -march rather than an
-mtune decision.

Admittedly the branch-likely case is a bit of a grey area.  It can be
justified on tuning grounds because it's unlikely that deprecated
instructions will perform will in general, and the tuning for mips*
archs is supposed to be an all-round compromise.  But disabling half
the FPRs for single floats can't be justified on tuning grounds.
That's never going to help performance. :-)

Thanks,
Richard
diff mbox

Patch

diff --git a/gcc/config/mips/mips-cpus.def b/gcc/config/mips/mips-cpus.def
index 07fbf9c..49feb17 100644
--- a/gcc/config/mips/mips-cpus.def
+++ b/gcc/config/mips/mips-cpus.def
@@ -42,11 +42,15 @@  MIPS_CPU ("mips4", PROCESSOR_R8000, 4, 0)
    in revisions 2 and earlier, but revision 3 is likely to downgrade
    that to a recommendation to avoid the instructions in code that
    isn't tuned to a specific processor.  */
-MIPS_CPU ("mips32", PROCESSOR_4KC, 32, PTF_AVOID_BRANCHLIKELY)
-MIPS_CPU ("mips32r2", PROCESSOR_74KF2_1, 33, PTF_AVOID_BRANCHLIKELY)
-MIPS_CPU ("mips64", PROCESSOR_5KC, 64, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("mips32", PROCESSOR_4KC, 32, PTF_AVOID_BRANCHLIKELY
+				       | PTF_AVOID_ODD_SPREG)
+MIPS_CPU ("mips32r2", PROCESSOR_74KF2_1, 33, PTF_AVOID_BRANCHLIKELY
+					     | PTF_AVOID_ODD_SPREG)
+MIPS_CPU ("mips64", PROCESSOR_5KC, 64, PTF_AVOID_BRANCHLIKELY
+				       | PTF_AVOID_ODD_SPREG)
 /* ??? For now just tune the generic MIPS64r2 for 5KC as well.   */
-MIPS_CPU ("mips64r2", PROCESSOR_5KC, 65, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("mips64r2", PROCESSOR_5KC, 65, PTF_AVOID_BRANCHLIKELY
+					 | PTF_AVOID_ODD_SPREG)
 
 /* MIPS I processors.  */
 MIPS_CPU ("r3000", PROCESSOR_R3000, 1, 0)
@@ -147,7 +151,8 @@  MIPS_CPU ("sr71000", PROCESSOR_SR71000, 64, PTF_AVOID_BRANCHLIKELY)
 MIPS_CPU ("xlr", PROCESSOR_XLR, 64, PTF_AVOID_BRANCHLIKELY)
 
 /* MIPS64 Release 2 processors.  */
-MIPS_CPU ("loongson3a", PROCESSOR_LOONGSON_3A, 65, PTF_AVOID_BRANCHLIKELY)
+MIPS_CPU ("loongson3a", PROCESSOR_LOONGSON_3A, 65, PTF_AVOID_BRANCHLIKELY
+						   | PTF_AVOID_ODD_SPREG)
 MIPS_CPU ("octeon", PROCESSOR_OCTEON, 65, PTF_AVOID_BRANCHLIKELY)
 MIPS_CPU ("octeon+", PROCESSOR_OCTEON, 65, PTF_AVOID_BRANCHLIKELY)
 MIPS_CPU ("octeon2", PROCESSOR_OCTEON2, 65, PTF_AVOID_BRANCHLIKELY)
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 45256e9..b012dfd 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -17120,6 +17120,21 @@  mips_option_override (void)
     warning (0, "the %qs architecture does not support madd or msub"
 	     " instructions", mips_arch_info->name);
 
+  /* If neither -modd-spreg nor -mno-odd-spreg was given on the command
+     line, set MASK_ODD_SPREG bsaed on the target architecture, ABI and
+     tuning flags.  */
+  if ((target_flags_explicit & MASK_ODD_SPREG) == 0)
+    {
+      if (ISA_HAS_ODD_SPREG
+	  && ((mips_tune_info->tune_flags & PTF_AVOID_ODD_SPREG) == 0))
+	target_flags |= MASK_ODD_SPREG;
+      else
+	target_flags &= ~MASK_ODD_SPREG;
+    }
+  else if (TARGET_ODD_SPREG && !ISA_HAS_ODD_SPREG)
+    warning (0, "the %qs architecture does not support odd single-precision"
+	     " registers", mips_arch_info->name);
+
   /* The effect of -mabicalls isn't defined for the EABI.  */
   if (mips_abi == ABI_EABI && TARGET_ABICALLS)
     {
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index b25865b..5661d49 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -52,10 +52,15 @@  extern int target_flags_explicit;
    PTF_AVOID_IMADD
 	Set if it is usually not profitable to use the integer MADD or MSUB
 	instructions because of the overhead of getting the result out of
-	the HI/LO registers.  */
+	the HI/LO registers.
+
+   PTF_AVOID_ODD_SPREG
+	Set if the processor does not support using odd numbered
+	single-precision registers when the FP register width is 32-bit.  */
 
 #define PTF_AVOID_BRANCHLIKELY	0x1
 #define PTF_AVOID_IMADD		0x2
+#define PTF_AVOID_ODD_SPREG	0x4
 
 /* Information about one recognized processor.  Defined here for the
    benefit of TARGET_CPU_CPP_BUILTINS.  */
@@ -491,6 +496,8 @@  struct mips_cpu_info {
       builtin_define_with_int_value ("_MIPS_SZPTR", POINTER_SIZE);	\
       builtin_define_with_int_value ("_MIPS_FPSET",			\
 				     32 / MAX_FPRS_PER_FMT);		\
+      builtin_define_with_int_value ("_MIPS_SPFPSET",			\
+				     32 / MIN_FPRS_PER_FMT);		\
 									\
       /* These defines reflect the ABI in use, not whether the  	\
 	 FPU is directly accessible.  */				\
@@ -808,6 +815,13 @@  struct mips_cpu_info {
    been generated up to this point.  */
 #define ISA_HAS_BRANCHLIKELY	(!ISA_MIPS1)
 
+/* ISA has 32 single-precision registers.  */
+#define ISA_HAS_ODD_SPREG	(ISA_MIPS32				\
+				 || ISA_MIPS32R2			\
+				 || ISA_MIPS64				\
+				 || ISA_MIPS64R2			\
+				 || TARGET_FLOAT64)
+
 /* ISA has a three-operand multiplication instruction (usually spelt "mul").  */
 #define ISA_HAS_MUL3		((TARGET_MIPS3900                       \
 				  || TARGET_MIPS5400			\
@@ -1268,6 +1282,12 @@  struct mips_cpu_info {
 /* By default, turn on GDB extensions.  */
 #define DEFAULT_GDB_EXTENSIONS 1
 
+/* Registers may have a prefix which can be ignored when matching
+   user asm and register definitions.  */
+#ifndef REGISTER_PREFIX
+#define REGISTER_PREFIX		"$"
+#endif
+
 /* Local compiler-generated symbols must have a prefix that the assembler
    understands.   By default, this is $, although some targets (e.g.,
    NetBSD-ELF) need to override this.  */
@@ -1349,8 +1369,7 @@  struct mips_cpu_info {
 /* The number of consecutive floating-point registers needed to store the
    smallest format supported by the FPU.  */
 #define MIN_FPRS_PER_FMT \
-  (ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2 \
-   ? 1 : MAX_FPRS_PER_FMT)
+  (TARGET_ODD_SPREG ? 1 : MAX_FPRS_PER_FMT)
 
 /* The largest size of value that can be held in floating-point
    registers and moved with a single instruction.  */
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index 6ee5398..f91ca44 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -400,5 +400,9 @@  mxgot
 Target Report Var(TARGET_XGOT)
 Lift restrictions on GOT size
 
+modd-spreg
+Target Report Mask(ODD_SPREG)
+Enable use of odd-numbered single-precision registers
+
 noasmopt
 Driver
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 8c72cff..cd3090e 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -248,6 +248,15 @@  set mips_option_groups {
     dump "-fdump-.*"
 }
 
+foreach option {
+    0 1 2 3 4 5 6 7 8 9
+    10 11 12 13 14 15 16 17 18 19
+    20 21 22 23 24 25 26 27 28 29
+    30 31
+} {
+    lappend mips_option_groups "fixed-f$option" "-ffixed-f$option"
+}
+
 # Add -mfoo/-mno-foo options to mips_option_groups.
 foreach option {
     abicalls
@@ -270,6 +279,7 @@  foreach option {
     synci
     relax-pic-calls
     mcount-ra-address
+    odd-spreg
 } {
     lappend mips_option_groups $option "-m(no-|)$option"
 }
@@ -755,6 +765,12 @@  proc mips-dg-init {} {
 	    "-mno-paired-single",
 	    #endif
 
+	    #if _MIPS_SPFPSET == 32
+	    "-modd-spreg",
+	    #else
+	    "-mno-odd-spreg",
+	    #endif
+
 	    #if __mips_abicalls
 	    "-mabicalls",
 	    #else
@@ -840,6 +856,8 @@  proc mips-dg-finish {} {
 #            |                           |
 #         -mfp64                      -mfp32
 #            |                           |
+#         -modd-spreg                 -mno-odd-spreg
+#            |                           |
 #         -mabs=2008/-mabs=legacy     <no option>
 #            |                           |
 #         -mhard-float                -msoft-float
@@ -929,6 +947,7 @@  proc mips-dg-options { args } {
     mips_option_dependency options "-mips3d" "-mpaired-single"
     mips_option_dependency options "-mpaired-single" "-mfp64"
     mips_option_dependency options "-mfp64" "-mhard-float"
+    mips_option_dependency options "-mfp64" "-modd-spreg"
     mips_option_dependency options "-mabs=2008" "-mhard-float"
     mips_option_dependency options "-mabs=legacy" "-mhard-float"
     mips_option_dependency options "-mrelax-pic-calls" "-mno-plt"
@@ -1045,10 +1064,13 @@  proc mips-dg-options { args } {
         # We need a MIPS32 or MIPS64 ISA for:
 	#
         #   - paired-single instructions(*)
+        #   - odd numbered single precision registers
         #
 	# (*) Note that we don't support MIPS V at the moment.
 	} elseif { $isa_rev < 1
-		   && [mips_have_test_option_p options "-mpaired-single"] } {
+		   && ([mips_have_test_option_p options "-mpaired-single"]
+		       || ([mips_have_test_option_p options "-modd-spreg"]
+			   && ![mips_have_test_option_p options "-mfp64"]))} {
 	    if { $gp_size == 32 } {
 		mips_make_test_option options "-mips32"
 	    } else {
@@ -1192,6 +1214,7 @@  proc mips-dg-options { args } {
 	}
 	if { $isa_rev < 1 } {
 	    mips_make_test_option options "-mno-paired-single"
+	    mips_make_test_option options "-mno-odd-spreg"
 	}
 	if { $isa_rev < 2 } {
 	    if { $gp_size == 32 } {
diff --git a/gcc/testsuite/gcc.target/mips/oddspreg-1.c b/gcc/testsuite/gcc.target/mips/oddspreg-1.c
new file mode 100644
index 0000000..0c50372
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/oddspreg-1.c
@@ -0,0 +1,14 @@ 
+/* Check that we enable odd-numbered single precision registers.  */
+/* { dg-options "-mabi=32 -modd-spreg -mhard-float -ffixed-f0 -ffixed-f2 -ffixed-f4 -ffixed-f6 -ffixed-f8 -ffixed-f10 -ffixed-f12 -ffixed-f14 -ffixed-f16 -ffixed-f18 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
+
+#if _MIPS_SPFPSET != 32
+#error "Incorrect number of single-precision registers reported"
+#endif
+
+float a;
+float
+foo ()
+{
+  float b = a + 1.0f;
+  return b;
+}
diff --git a/gcc/testsuite/gcc.target/mips/oddspreg-2.c b/gcc/testsuite/gcc.target/mips/oddspreg-2.c
new file mode 100644
index 0000000..dfb64bd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/oddspreg-2.c
@@ -0,0 +1,13 @@ 
+/* Check that we disable odd-numbered single precision registers.  */
+/* { dg-xfail-if "register allocation test" { *-*-* } { "*" } { "" } } */
+/* { dg-options "-mabi=32 -mno-odd-spreg -mhard-float -ffixed-f0 -ffixed-f2 -ffixed-f4 -ffixed-f6 -ffixed-f8 -ffixed-f10 -ffixed-f12 -ffixed-f14 -ffixed-f16 -ffixed-f18 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
+
+float a;
+float
+foo ()
+{
+  float b = a + 1.0f;
+  return b;
+}
+/* { dg-final { scan-assembler "not scanning, forcing conventional output" } } */
+/* { dg-excess-errors "this test ICEs" { target *-*-* } } */
diff --git a/gcc/testsuite/gcc.target/mips/oddspreg-3.c b/gcc/testsuite/gcc.target/mips/oddspreg-3.c
new file mode 100644
index 0000000..0c02a43
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/oddspreg-3.c
@@ -0,0 +1,13 @@ 
+/* Check that we disable odd-numbered single precision registers.  */
+/* { dg-xfail-if "register allocation test" { *-*-* } { "*" } { "" } } */
+/* { dg-options "-mabi=32 -march=loongson3a -mhard-float -ffixed-f0 -ffixed-f2 -ffixed-f4 -ffixed-f6 -ffixed-f8 -ffixed-f10 -ffixed-f12 -ffixed-f14 -ffixed-f16 -ffixed-f18 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
+
+float a;
+float
+foo ()
+{
+  float b = a + 1.0f;
+  return b;
+}
+/* { dg-final { scan-assembler "not scanning, forcing conventional output" } } */
+/* { dg-excess-errors "this test ICEs" { target *-*-* } } */
diff --git a/gcc/testsuite/gcc.target/mips/oddspreg-4.c b/gcc/testsuite/gcc.target/mips/oddspreg-4.c
new file mode 100644
index 0000000..c8b6d82
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/oddspreg-4.c
@@ -0,0 +1,13 @@ 
+/* Check that we disable odd-numbered single precision registers.  */
+/* { dg-xfail-if "register allocation test" { *-*-* } { "*" } { "" } } */
+/* { dg-options "-mabi=32 -mips32r2 -mhard-float -ffixed-f0 -ffixed-f2 -ffixed-f4 -ffixed-f6 -ffixed-f8 -ffixed-f10 -ffixed-f12 -ffixed-f14 -ffixed-f16 -ffixed-f18 -ffixed-f20 -ffixed-f22 -ffixed-f24 -ffixed-f26 -ffixed-f28 -ffixed-f30" } */
+
+float a;
+float
+foo ()
+{
+  float b = a + 1.0f;
+  return b;
+}
+/* { dg-final { scan-assembler "not scanning, forcing conventional output" } } */
+/* { dg-excess-errors "this test ICEs" { target *-*-* } } */
diff --git a/gcc/testsuite/gcc.target/mips/oddspreg-5.c b/gcc/testsuite/gcc.target/mips/oddspreg-5.c
new file mode 100644
index 0000000..723424a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/oddspreg-5.c
@@ -0,0 +1,15 @@ 
+/* Check that we disable odd-numbered single precision registers and can
+   still generate code.  */
+/* { dg-options "-mabi=32 -mno-odd-spreg -mhard-float" } */
+
+#if _MIPS_SPFPSET != 16
+#error "Incorrect number of single-precision registers reported"
+#endif
+
+float a;
+float
+foo ()
+{
+  float b = a + 1.0f;
+  return b;
+}
diff --git a/gcc/testsuite/gcc.target/mips/oddspreg-6.c b/gcc/testsuite/gcc.target/mips/oddspreg-6.c
new file mode 100644
index 0000000..2d1b129
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/oddspreg-6.c
@@ -0,0 +1,15 @@ 
+/* Check that we disable odd-numbered single precision registers and can
+   still generate code.  */
+/* { dg-options "-mabi=64 -mno-odd-spreg -mhard-float" } */
+
+#if _MIPS_SPFPSET != 32
+#error "Incorrect number of single-precision registers reported"
+#endif
+
+float a;
+float
+foo ()
+{
+  float b = a + 1.0f;
+  return b;
+}