MIPS: MIPS32r2 FP reciprocal instruction set support
diff mbox

Message ID alpine.DEB.1.10.1311141941370.21686@tp.orcam.me.uk
State Superseded
Headers show

Commit Message

Maciej W. Rozycki Nov. 14, 2013, 11:19 p.m. UTC
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  <macro@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

Comments

Richard Sandiford Nov. 16, 2013, 8:30 a.m. UTC | #1
"Maciej W. Rozycki" <macro@codesourcery.com> writes:
>  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.

Yeah, sounds good.

> 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))

I think the !(ISA_MIPS4 || ISA_MIPS64) part is really "r2 or later",
which elsewhere we test as "ISA_MIPS32R2 || ISA_MIPS64R2".  Obviously
that isn't as future-proof, but I think consistency wins here.
(E.g. the earlier ISA_MIPS32R2 seems like it's reallly "r2 or later" too).

Cleaning up these macros has been on my todo list for about ten years :-(

Please also test !TARGET_MIPS16 at the outermost level, so that there's
only one instance.  I think that gives something like:

#define ISA_HAS_FP_RECIP_RSQRT(MODE)					\
				((((ISA_HAS_FP4 || ISA_MIPS32R2)	\
				   && ((MODE) == SFmode			\
				       || ((TARGET_FLOAT64		\
					    || ISA_MIPS32R2		\
					    || ISA_MIPS64R2)		\
					   && (MODE) == DFmode)))	\
				  || (TARGET_SB1			\
				      && (MODE) == V2SFmode))		\
				 && !TARGET_MIPS16)

OK with those changes, thanks.

Richard

Patch
diff mbox

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";