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.fort...@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 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; +} -- 1.7.1