Hi, Complementing the recent change to enable FP MADD instructions on MIPS32r2 processors in the 32-bit FPR mode (CP0.Status.FR=0) here's one to enable FP reciprocal instructions (RECIP.fmt and RSQRT.fmt) in that case as well. Architecture documents have been amended to make it unambiguous that these instructions are supported in that FPU configuration[1][2].
My understanding also is only a single implementation of a strict 32-bit MIPS32r2 FPU (CP1.FIR.F64=0) has been ever made and that chip actually supports these instructions, and no future 32-bit FPUs are supposed to be made as the architecture no longer allows it[3][4]. Note that these instructions were allowed in either FPU mode in the MIPS IV ISA, but for forward ISA compatibility this change does not enable them for -march=mips4 in the 32-bit FPR mode because the original revision of the MIPS64 ISA did not support it. I have regression-tested this change with the mips-linux-gnu target and the mips32r2/o32 multilib. I have also verified that the instructions affected were absent across the binaries produced by the testsuite before applying this change and present afterwards -- although only RECIP.D and RECIP.S are produced and only once each, by gcc.dg/builtins-24.c and gcc.dg/pr41963.c respectively. Neither RSQRT.D nor RSQRT.S have coverage in our testsuite. OK to apply? References: [1] "MIPS Architecture For Programmers, Volume II-A: The MIPS32 Instruction Set", Document Number: MD00086, Revision 5.03, Sept. 9, 2013 [2] "MIPS Architecture for Programmers, Volume II-B: The microMIPS32 Instruction Set, Document Number: MD00582, Revision 5.03, Sept. 9, 2013 [3] "MIPS Architecture For Programmers, Volume I-A: Introduction to the MIPS32 Architecture", Document Number: MD00082, Revision 5.03, Sept. 9, 2013 [4] "MIPSR Architecture For Programmers, Volume I-B: Introduction to the microMIPS32 Architecture", Document Number: MD00741, Revision 5.03, Sept. 9, 2013 2013-11-14 Maciej W. Rozycki <ma...@codesourcery.com> gcc/ * config/mips/mips.h (ISA_HAS_FP_RECIP_RSQRT): New macro. * config/mips/mips.c (mips_rtx_costs) <DIV>: Check for ISA_HAS_FP_RECIP_RSQRT rather than ISA_HAS_FP4. * config/mips/mips.md (recip_condition): Remove mode attribute. (div<mode>3): Use ISA_HAS_FP_RECIP_RSQRT rather than <recip_condition>. (*recip<mode>3, *rsqrt<mode>a, *rsqrt<mode>b): Likewise. Maciej gcc-mips32r2-recip.patch Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.c =================================================================== --- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.c 2013-11-12 15:32:19.767952530 +0000 +++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.c 2013-11-12 15:33:22.277646941 +0000 @@ -3967,7 +3967,7 @@ mips_rtx_costs (rtx x, int code, int out case DIV: /* Check for a reciprocal. */ if (float_mode_p - && ISA_HAS_FP4 + && ISA_HAS_FP_RECIP_RSQRT (mode) && flag_unsafe_math_optimizations && XEXP (x, 0) == CONST1_RTX (mode)) { Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.h =================================================================== --- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.h 2013-11-12 15:31:46.758734464 +0000 +++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.h 2013-11-12 15:33:22.277646941 +0000 @@ -921,6 +921,21 @@ struct mips_cpu_info { 'c = -((a * b) [+-] c)'. */ #define ISA_HAS_NMADD3_NMSUB3 TARGET_LOONGSON_2EF +/* ISA has floating-point RECIP.fmt and RSQRT.fmt instructions. The + MIPS64 rev. 1 ISA says that RECIP.D and RSQRT.D are unpredictable when + doubles are stored in pairs of FPRs, so for safety's sake, we apply + this restriction to the MIPS IV ISA too. */ +#define ISA_HAS_FP_RECIP_RSQRT(MODE) \ + (((ISA_HAS_FP4 \ + || (ISA_MIPS32R2 && !TARGET_MIPS16)) \ + && ((MODE) == SFmode \ + || ((TARGET_FLOAT64 \ + || !(ISA_MIPS4 \ + || ISA_MIPS64)) \ + && (MODE) == DFmode))) \ + || ((TARGET_SB1 && !TARGET_MIPS16) \ + && (MODE) == V2SFmode)) + /* ISA has count leading zeroes/ones instruction (not implemented). */ #define ISA_HAS_CLZ_CLO ((ISA_MIPS32 \ || ISA_MIPS32R2 \ Index: gcc-fsf-trunk-quilt/gcc/config/mips/mips.md =================================================================== --- gcc-fsf-trunk-quilt.orig/gcc/config/mips/mips.md 2013-11-12 15:31:46.758734464 +0000 +++ gcc-fsf-trunk-quilt/gcc/config/mips/mips.md 2013-11-12 15:33:22.277646941 +0000 @@ -881,15 +881,6 @@ (define_mode_attr sqrt_condition [(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")]) -;; This attribute gives the conditions under which RECIP.fmt and RSQRT.fmt -;; instructions can be used. The MIPS32 and MIPS64 ISAs say that RECIP.D -;; and RSQRT.D are unpredictable when doubles are stored in pairs of FPRs, -;; so for safety's sake, we apply this restriction to all targets. -(define_mode_attr recip_condition - [(SF "ISA_HAS_FP4") - (DF "ISA_HAS_FP4 && TARGET_FLOAT64") - (V2SF "TARGET_SB1")]) - ;; This code iterator allows signed and unsigned widening multiplications ;; to use the same template. (define_code_iterator any_extend [sign_extend zero_extend]) @@ -2501,7 +2492,8 @@ "<divide_condition>" { if (const_1_operand (operands[1], <MODE>mode)) - if (!(<recip_condition> && flag_unsafe_math_optimizations)) + if (!(ISA_HAS_FP_RECIP_RSQRT (<MODE>mode) + && flag_unsafe_math_optimizations)) operands[1] = force_reg (<MODE>mode, operands[1]); }) @@ -2539,7 +2531,7 @@ [(set (match_operand:ANYF 0 "register_operand" "=f") (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") (match_operand:ANYF 2 "register_operand" "f")))] - "<recip_condition> && flag_unsafe_math_optimizations" + "ISA_HAS_FP_RECIP_RSQRT (<MODE>mode) && flag_unsafe_math_optimizations" { if (TARGET_FIX_SB1) return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; @@ -2674,7 +2666,7 @@ [(set (match_operand:ANYF 0 "register_operand" "=f") (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))] - "<recip_condition> && flag_unsafe_math_optimizations" + "ISA_HAS_FP_RECIP_RSQRT (<MODE>mode) && flag_unsafe_math_optimizations" { if (TARGET_FIX_SB1) return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; @@ -2692,7 +2684,7 @@ [(set (match_operand:ANYF 0 "register_operand" "=f") (sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") (match_operand:ANYF 2 "register_operand" "f"))))] - "<recip_condition> && flag_unsafe_math_optimizations" + "ISA_HAS_FP_RECIP_RSQRT (<MODE>mode) && flag_unsafe_math_optimizations" { if (TARGET_FIX_SB1) return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";