public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
@ 2015-06-11 20:09 Steve Ellcey 
  2015-06-11 20:39 ` Joseph Myers
  0 siblings, 1 reply; 25+ messages in thread
From: Steve Ellcey  @ 2015-06-11 20:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: clm, matthew.fortune

This patch updates MIPS to handle fused multiply and add instructions using
the standard fp-contract infrastructure.  Currently MIPS handles -mfused-madd
as a target specific option and it is not affected by the -ffp-contract option.

This patch changes -mfused-madd to be an alias for -ffp-contract=fast by
using the standard config/fused-madd.opt option file.  It also adds
fma, fms, fnma, and fnms instructions to be used with convert_mult_to_fma
and updates the definitions of the non-fused multiply and add instructions
that some MIPS architectures support.

After this patch I found the following changes in behaviour:

mips1, mips2, mips3, and mips32[r1] had no change because they have no
fused (or unfused) madd instructions.

loongson and r8000 have the most changes,  they no longer generate msub
instructions with -mfused-madd because that instruction does not generate
the correct NAN in some cases (the sign may be wrong).  If HONOR_NANS
is not set then they will generate msub instructions.

mips4 (other than r8000), mips32r2, mips64[r1], and mips64r2 will
now generated [unfused] multiply and add instructions even if 
-mno-fused-madd (or -ffp-contract=on) are used because these instructions
are not fused and will round in between the two operations.  This means
they give the same result as the individual instructions.

mips32r6 and mips64r6 now obey -mno-fused-madd (or -ffp-contract=on)
whereas before they were generating fused madds even when one of these
options were used.

One thing I did not put in this patch was to add code to use the
mips32r6/mips64r6 msubf instruction.  This instruction implements
'c - (a * b)', not '(a * b) - c' and since it not currently used by
GCC I decided not to add it to this patch.

I did run-time testing with mips32 and mips64, versions 1, 2, and 6.
With other MIPS versions (mips[1234], r8000, loongson) I did
compilations to assembly language and did a visual inspection of the
code to compare the results before and after this patch was applied.

OK to checkin?

Steve Ellcey
sellcey@imgtec.com


2015-06-11  Steve Ellcey  <sellcey@imgtec.com>

	* config.gcc (mips*-*-*): Add fused-madd.opt.
	* config/mips/mips.opt (mfused-madd): Remove.
	* config/mips/mips.c (mips_rtx_costs): Update cost calculations.
	* config/mips/mips.h (TARGET_MIPS8000): New.
	(ISA_HAS_FP_MADD4_MSUB4): Remove.
	(ISA_HAS_FP_MADDF_MSUBF): Remove.
	(ISA_HAS_FP_MADD3_MSUB3): Remove.
	(ISA_HAS_NMADD4_NMSUB4): Remove.
	(ISA_HAS_NMADD3_NMSUB3): Remove.
	(ISA_HAS_FUSED_MADD4): New.
	(ISA_HAS_UNFUSED_MADD4): New.
	(ISA_HAS_FUSED_MADDF): New.
	(ISA_HAS_FUSED_MADD3): New.
	* config/mips/mips.md: (fma<mode>4) Change from insn to expand.
	(*fma<mode>4_madd3) New.
	(*fma<mode>4_madd4) New.
	(*fma<mode>4_maddf) New.
	(fms<mode>4) New.
	(*fms<mode>4_msub3) New.
	(*fms<mode>4_msub4) New.
	(fnma<mode>4) New.
	(*fnma<mode>4_nmadd3) New.
	(*fnma<mode>4_nmadd4) New.
	(fnms<mode>4) New.
	(*fnms<mode>4_nmsub3) New.
	(*fnms<mode>4_nmsub4) New.
	(*madd4<mode>) Modify to be unfused only.
	(*msub4<mode>) Modify to be unfused only.
	(*nmadd4<mode>) Modify to be unfused only.
	(*nmsub4<mode>) Modify to be unfused only.
	(*madd3<mode>) Remove.
	(*msub3<mode>) Remove.
	(*nmadd3<mode>) Remove.
	(*nmsub3<mode>) Remove.
	(*nmadd3<mode>_fastmath) Remove.
	(*nmsub3<mode>_fastmath) Remove.
	(*nmadd4<mode>_fastmath) Update condition.
	(*nmsub4<mode>_fastmath)  Update condition.


diff --git a/gcc/config.gcc b/gcc/config.gcc
index 13a567f..f8c6307 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -418,7 +418,7 @@ microblaze*-*-*)
 mips*-*-*)
 	cpu_type=mips
 	extra_headers="loongson.h"
-	extra_options="${extra_options} g.opt mips/mips-tables.opt"
+	extra_options="${extra_options} g.opt fused-madd.opt mips/mips-tables.opt"
 	;;
 nds32*)
 	cpu_type=nds32
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index e81134e..3ed9804 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -4068,14 +4068,12 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case MINUS:
-      if (float_mode_p
-	  && (ISA_HAS_NMADD4_NMSUB4 || ISA_HAS_NMADD3_NMSUB3)
-	  && TARGET_FUSED_MADD
-	  && !HONOR_NANS (mode)
-	  && !HONOR_SIGNED_ZEROS (mode))
+      if (float_mode_p && ISA_HAS_UNFUSED_MADD4
+	  && !HONOR_NANS (mode) && !HONOR_SIGNED_ZEROS (mode))
 	{
-	  /* See if we can use NMADD or NMSUB.  See mips.md for the
-	     associated patterns.  */
+	  /* See if we can use NMADD or NMSUB via the *nmadd4<mode>_fastmath
+	     or *nmsub4<mode>_fastmath patterns.  These patterns check for
+	     HONOR_NANS and HONOR_SIGNED_ZEROS so we check here too.  */
 	  rtx op0 = XEXP (x, 0);
 	  rtx op1 = XEXP (x, 1);
 	  if (GET_CODE (op0) == MULT && GET_CODE (XEXP (op0, 0)) == NEG)
@@ -4102,9 +4100,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
 	{
 	  /* If this is part of a MADD or MSUB, treat the PLUS as
 	     being free.  */
-	  if ((ISA_HAS_FP_MADD4_MSUB4 || ISA_HAS_FP_MADD3_MSUB3)
-	      && TARGET_FUSED_MADD
-	      && GET_CODE (XEXP (x, 0)) == MULT)
+	  if (ISA_HAS_UNFUSED_MADD4 && GET_CODE (XEXP (x, 0)) == MULT)
 	    *total = 0;
 	  else
 	    *total = mips_cost->fp_add;
@@ -4136,14 +4132,11 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return true;
 
     case NEG:
-      if (float_mode_p
-	  && (ISA_HAS_NMADD4_NMSUB4 || ISA_HAS_NMADD3_NMSUB3)
-	  && TARGET_FUSED_MADD
-	  && !HONOR_NANS (mode)
-	  && HONOR_SIGNED_ZEROS (mode))
+      if (float_mode_p && ISA_HAS_UNFUSED_MADD4 && !HONOR_NANS (mode))
 	{
-	  /* See if we can use NMADD or NMSUB.  See mips.md for the
-	     associated patterns.  */
+	  /* See if we can use NMADD or NMSUB via the *nmadd4<mode> or
+	     *nmsub4<mode> patterns.  These patterns do not check
+	     HONOR_NANS but not HONOR_SIGNED_ZEROS so we check the same.  */
 	  rtx op = XEXP (x, 0);
 	  if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
 	      && GET_CODE (XEXP (op, 0)) == MULT)
@@ -4163,8 +4156,7 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
       return false;
 
     case FMA:
-      if (ISA_HAS_FP_MADDF_MSUBF)
-	*total = mips_fp_mult_cost (mode);
+      *total = mips_fp_mult_cost (mode);
       return false;
 
     case MULT:
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index bceef31..7a6f917 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -236,6 +236,7 @@ struct mips_cpu_info {
 #define TARGET_MIPS5500             (mips_arch == PROCESSOR_R5500)
 #define TARGET_MIPS5900             (mips_arch == PROCESSOR_R5900)
 #define TARGET_MIPS7000             (mips_arch == PROCESSOR_R7000)
+#define TARGET_MIPS8000             (mips_arch == PROCESSOR_R8000)
 #define TARGET_MIPS9000             (mips_arch == PROCESSOR_R9000)
 #define TARGET_OCTEON		    (mips_arch == PROCESSOR_OCTEON	\
 				     || mips_arch == PROCESSOR_OCTEON2	\
@@ -998,22 +999,21 @@ struct mips_cpu_info {
 /* Integer multiply-accumulate instructions should be generated.  */
 #define GENERATE_MADD_MSUB	(TARGET_IMADD && !TARGET_MIPS16)
 
-/* ISA has floating-point madd and msub instructions 'd = a * b [+-] c'.  */
-#define ISA_HAS_FP_MADD4_MSUB4  ISA_HAS_FP4
+/* ISA has 4 operand fused madd instructions of the form
+   'd = [+-] (a * b [+-] c)'.  */
+#define ISA_HAS_FUSED_MADD4	TARGET_MIPS8000
 
-/* ISA has floating-point MADDF and MSUBF instructions 'd = d [+-] a * b'.  */
-#define ISA_HAS_FP_MADDF_MSUBF  (mips_isa_rev >= 6)
+/* ISA has 4 operand unfused madd instructions of the form
+   'd = [+-] (a * b [+-] c)'.  */
+#define ISA_HAS_UNFUSED_MADD4	(ISA_HAS_FP4 && !TARGET_MIPS8000)
 
-/* ISA has floating-point madd and msub instructions 'c = a * b [+-] c'.  */
-#define ISA_HAS_FP_MADD3_MSUB3  TARGET_LOONGSON_2EF
+/* ISA has 3 operand r6 fused madd instructions of the form
+   'c = c [+-] (a * b)'.  */
+#define ISA_HAS_FUSED_MADDF	(mips_isa_rev >= 6)
 
-/* ISA has floating-point nmadd and nmsub instructions
-   'd = -((a * b) [+-] c)'.  */
-#define ISA_HAS_NMADD4_NMSUB4	ISA_HAS_FP4
-
-/* ISA has floating-point nmadd and nmsub instructions
-   'c = -((a * b) [+-] c)'.  */
-#define ISA_HAS_NMADD3_NMSUB3	TARGET_LOONGSON_2EF
+/* ISA has 3 operand loongson fused madd instructions of the form
+   'c = [+-] (a * b [+-] c)'.  */
+#define ISA_HAS_FUSED_MADD3	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
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 0a23fa2..4b2a6ed 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2475,165 +2475,238 @@
 
 ;; Floating point multiply accumulate instructions.
 
-(define_insn "*madd4<mode>"
+(define_expand "fma<mode>4"
+  [(set (match_operand:ANYF 0 "register_operand")
+	(fma:ANYF (match_operand:ANYF 1 "register_operand")
+		  (match_operand:ANYF 2 "register_operand")
+		  (match_operand:ANYF 3 "register_operand")))]
+  "ISA_HAS_FUSED_MADDF || ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4")
+
+(define_insn "*fma<mode>4_madd3"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
-			      (match_operand:ANYF 2 "register_operand" "f"))
-		   (match_operand:ANYF 3 "register_operand" "f")))]
-  "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD"
+	(fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
+		  (match_operand:ANYF 2 "register_operand" "f")
+		  (match_operand:ANYF 3 "register_operand" "0")))]
+  "ISA_HAS_FUSED_MADD3"
+  "madd.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fmadd")
+   (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "*fma<mode>4_madd4"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+	(fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
+		  (match_operand:ANYF 2 "register_operand" "f")
+		  (match_operand:ANYF 3 "register_operand" "f")))]
+  "ISA_HAS_FUSED_MADD4"
   "madd.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "fma<mode>4"
+(define_insn "*fma<mode>4_maddf"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
 		  (match_operand:ANYF 2 "register_operand" "f")
 		  (match_operand:ANYF 3 "register_operand" "0")))]
-  "ISA_HAS_FP_MADDF_MSUBF"
+  "ISA_HAS_FUSED_MADDF"
   "maddf.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*madd3<mode>"
+;; The fms, fnma, and fnms instructions cannot be used when HONOR_NANS
+;; is true because they may return a +qNAN when a -qNAN is required by
+;; IEEE 754-2008.
+
+(define_expand "fms<mode>4"
+  [(set (match_operand:ANYF 0 "register_operand")
+	(fma:ANYF (match_operand:ANYF 1 "register_operand")
+		  (match_operand:ANYF 2 "register_operand")
+		  (neg:ANYF (match_operand:ANYF 3 "register_operand"))))]
+  "(ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4) && !HONOR_NANS (<MODE>mode)")
+
+(define_insn "*fms<mode>4_msub3"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
-			      (match_operand:ANYF 2 "register_operand" "f"))
-		   (match_operand:ANYF 3 "register_operand" "0")))]
-  "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD"
-  "madd.<fmt>\t%0,%1,%2"
+	(fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
+		  (match_operand:ANYF 2 "register_operand" "f")
+		  (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))]
+  "ISA_HAS_FUSED_MADD3 && !HONOR_NANS (<MODE>mode)"
+  "msub.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*msub4<mode>"
+(define_insn "*fms<mode>4_msub4"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
-			       (match_operand:ANYF 2 "register_operand" "f"))
-		    (match_operand:ANYF 3 "register_operand" "f")))]
-  "ISA_HAS_FP_MADD4_MSUB4 && TARGET_FUSED_MADD"
+	(fma:ANYF (match_operand:ANYF 1 "register_operand" "f")
+		  (match_operand:ANYF 2 "register_operand" "f")
+		  (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))]
+  "ISA_HAS_FUSED_MADD4 && !HONOR_NANS (<MODE>mode)"
   "msub.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*msub3<mode>"
+;; fnma is defined in GCC as (fma (neg op1) op2 op3)
+;; (-op1 * op2) + op3 ==> -(op1 * op2) + op3 ==> -((op1 * op2) - op3)
+;; The mips nmsub instructions implement -((op1 * op2) - op3)
+;; This transformation means we may return the wrong signed zero
+;; so we check HONOR_SIGNED_ZEROS.
+
+(define_expand "fnma<mode>4"
+  [(set (match_operand:ANYF 0 "register_operand")
+	(fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand"))
+		  (match_operand:ANYF 2 "register_operand")
+		  (match_operand:ANYF 3 "register_operand")))]
+  "(ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4)
+   && !HONOR_NANS (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)")
+
+(define_insn "*fnma<mode>4_nmsub3"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
-			       (match_operand:ANYF 2 "register_operand" "f"))
-		    (match_operand:ANYF 3 "register_operand" "0")))]
-  "ISA_HAS_FP_MADD3_MSUB3 && TARGET_FUSED_MADD"
-  "msub.<fmt>\t%0,%1,%2"
+	(fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
+		  (match_operand:ANYF 2 "register_operand" "f")
+		  (match_operand:ANYF 3 "register_operand" "0")))]
+  "ISA_HAS_FUSED_MADD3
+   && !HONOR_NANS (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+  "nmsub.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmadd4<mode>"
+(define_insn "*fnma<mode>4_nmsub4"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(neg:ANYF (plus:ANYF
-		   (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
-			      (match_operand:ANYF 2 "register_operand" "f"))
-		   (match_operand:ANYF 3 "register_operand" "f"))))]
-  "ISA_HAS_NMADD4_NMSUB4
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
-  "nmadd.<fmt>\t%0,%3,%1,%2"
+	(fma:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
+		  (match_operand:ANYF 2 "register_operand" "f")
+		  (match_operand:ANYF 3 "register_operand" "f")))]
+  "ISA_HAS_FUSED_MADD4
+   && !HONOR_NANS (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+  "nmsub.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmadd3<mode>"
+;; fnms is defined as: (fma (neg op1) op2 (neg op3))
+;; ((-op1) * op2) - op3 ==> -(op1 * op2) - op3 ==> -((op1 * op2) + op3)
+;; The mips nmadd instructions implement -((op1 * op2) + op3)
+;; This transformation means we may return the wrong signed zero
+;; so we check HONOR_SIGNED_ZEROS.
+
+(define_expand "fnms<mode>4"
+  [(set (match_operand:ANYF 0 "register_operand")
+	(fma:ANYF
+	  (neg:ANYF (match_operand:ANYF 1 "register_operand"))
+	  (match_operand:ANYF 2 "register_operand")
+	  (neg:ANYF (match_operand:ANYF 3 "register_operand"))))]
+  "(ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4)
+   && !HONOR_NANS (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)")
+
+(define_insn "*fnms<mode>4_nmadd3"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(neg:ANYF (plus:ANYF
-		   (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
-			      (match_operand:ANYF 2 "register_operand" "f"))
-		   (match_operand:ANYF 3 "register_operand" "0"))))]
-  "ISA_HAS_NMADD3_NMSUB3
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
+	(fma:ANYF
+	  (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
+	  (match_operand:ANYF 2 "register_operand" "f")
+	  (neg:ANYF (match_operand:ANYF 3 "register_operand" "0"))))]
+  "ISA_HAS_FUSED_MADD3
+   && !HONOR_NANS (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
   "nmadd.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmadd4<mode>_fastmath"
+(define_insn "*fnms<mode>4_nmadd4"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(minus:ANYF
-	 (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
-		    (match_operand:ANYF 2 "register_operand" "f"))
-	 (match_operand:ANYF 3 "register_operand" "f")))]
-  "ISA_HAS_NMADD4_NMSUB4
-   && TARGET_FUSED_MADD
-   && !HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
+	(fma:ANYF
+	  (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
+	  (match_operand:ANYF 2 "register_operand" "f")
+	  (neg:ANYF (match_operand:ANYF 3 "register_operand" "f"))))]
+  "ISA_HAS_FUSED_MADD4
+   && !HONOR_NANS (<MODE>mode) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
   "nmadd.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmadd3<mode>_fastmath"
+;; Non-fused Floating point multiply accumulate instructions.
+
+;; These instructions are not fused and round in between the multiply
+;; and the add (or subtract) so they are equivalent to the separate
+;; multiply and add/sub instructions.
+
+(define_insn "*madd4<mode>"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(minus:ANYF
-	 (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
-		    (match_operand:ANYF 2 "register_operand" "f"))
-	 (match_operand:ANYF 3 "register_operand" "0")))]
-  "ISA_HAS_NMADD3_NMSUB3
-   && TARGET_FUSED_MADD
-   && !HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
-  "nmadd.<fmt>\t%0,%1,%2"
+	(plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
+			      (match_operand:ANYF 2 "register_operand" "f"))
+		   (match_operand:ANYF 3 "register_operand" "f")))]
+  "ISA_HAS_UNFUSED_MADD4"
+  "madd.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub4<mode>"
+(define_insn "*msub4<mode>"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
-	(neg:ANYF (minus:ANYF
-		   (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
-			      (match_operand:ANYF 3 "register_operand" "f"))
-		   (match_operand:ANYF 1 "register_operand" "f"))))]
-  "ISA_HAS_NMADD4_NMSUB4
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
-  "nmsub.<fmt>\t%0,%1,%2,%3"
+	(minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
+			       (match_operand:ANYF 2 "register_operand" "f"))
+		    (match_operand:ANYF 3 "register_operand" "f")))]
+  "ISA_HAS_UNFUSED_MADD4"
+  "msub.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub3<mode>"
+;; We need to check for HONOR_NANS on nmadd4 and nmsub4 because the nmadd and
+;; nmsub instructions will not negate qNaN the way IEEE 754-2008 expects.
+;; i.e. (neg (qNAN)) would result in qNaN instead of -qNaN
+
+(define_insn "*nmadd4<mode>"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+	(neg:ANYF (plus:ANYF
+		   (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
+			      (match_operand:ANYF 2 "register_operand" "f"))
+		   (match_operand:ANYF 3 "register_operand" "f"))))]
+  "ISA_HAS_UNFUSED_MADD4 && !HONOR_NANS (<MODE>mode)"
+  "nmadd.<fmt>\t%0,%3,%1,%2"
+  [(set_attr "type" "fmadd")
+   (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "*nmsub4<mode>"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(neg:ANYF (minus:ANYF
-		   (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
-			      (match_operand:ANYF 3 "register_operand" "f"))
-		   (match_operand:ANYF 1 "register_operand" "0"))))]
-  "ISA_HAS_NMADD3_NMSUB3
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
-  "nmsub.<fmt>\t%0,%1,%2"
+		   (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
+			      (match_operand:ANYF 2 "register_operand" "f"))
+		   (match_operand:ANYF 3 "register_operand" "f"))))]
+  "ISA_HAS_UNFUSED_MADD4 && !HONOR_NANS (<MODE>mode)"
+  "nmsub.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub4<mode>_fastmath"
+;; Fast-math Non-fused Floating point multiply accumulate instructions.
+
+;; These instructions are not fused but the expressions they match are
+;; not exactly what the instruction implements in the sense that they
+;; may not generate the properly signed zeros or NaNs.
+
+;; This instruction recognizes  ((-op1) * op2) - op3 and generates an
+;; nmadd which is really -((op1 * op2) + op3).  They are equivalent
+;; except for the sign bit when the result is zero or NaN.
+
+(define_insn "*nmadd4<mode>_fastmath"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(minus:ANYF
-	 (match_operand:ANYF 1 "register_operand" "f")
-	 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
-		    (match_operand:ANYF 3 "register_operand" "f"))))]
-  "ISA_HAS_NMADD4_NMSUB4
-   && TARGET_FUSED_MADD
+	  (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
+		     (match_operand:ANYF 2 "register_operand" "f"))
+	  (match_operand:ANYF 3 "register_operand" "f")))]
+  "ISA_HAS_UNFUSED_MADD4
    && !HONOR_SIGNED_ZEROS (<MODE>mode)
    && !HONOR_NANS (<MODE>mode)"
-  "nmsub.<fmt>\t%0,%1,%2,%3"
+  "nmadd.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub3<mode>_fastmath"
+;; This instruction recognizes (op1 - (op2 * op3) and generates an
+;; nmsub which is really -((op2 * op3) - op1).  They are equivalent
+;; except for the sign bit when the result is zero or NaN.
+
+(define_insn "*nmsub4<mode>_fastmath"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
 	(minus:ANYF
-	 (match_operand:ANYF 1 "register_operand" "f")
-	 (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
-		    (match_operand:ANYF 3 "register_operand" "0"))))]
-  "ISA_HAS_NMADD3_NMSUB3
-   && TARGET_FUSED_MADD
+	  (match_operand:ANYF 1 "register_operand" "f")
+	  (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
+		     (match_operand:ANYF 3 "register_operand" "f"))))]
+  "ISA_HAS_UNFUSED_MADD4
    && !HONOR_SIGNED_ZEROS (<MODE>mode)
    && !HONOR_NANS (<MODE>mode)"
-  "nmsub.<fmt>\t%0,%1,%2"
+  "nmsub.<fmt>\t%0,%1,%2,%3"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
diff --git a/gcc/config/mips/mips.opt b/gcc/config/mips/mips.opt
index a9baebe..348c6e0 100644
--- a/gcc/config/mips/mips.opt
+++ b/gcc/config/mips/mips.opt
@@ -209,10 +209,6 @@ mflush-func=
 Target RejectNegative Joined Var(mips_cache_flush_func) Init(CACHE_FLUSH_FUNC)
 -mflush-func=FUNC	Use FUNC to flush the cache before calling stack trampolines
 
-mfused-madd
-Target Report Var(TARGET_FUSED_MADD) Init(1)
-Generate floating-point multiply-add instructions
-
 mabs=
 Target RejectNegative Joined Enum(mips_ieee_754_value) Var(mips_abs) Init(MIPS_IEEE_754_DEFAULT)
 -mabs=MODE	Select the IEEE 754 ABS/NEG instruction execution mode

^ permalink raw reply	[flat|nested] 25+ messages in thread

end of thread, other threads:[~2015-07-06 17:35 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-11 20:09 [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd Steve Ellcey 
2015-06-11 20:39 ` Joseph Myers
2015-06-15 20:52   ` Maciej W. Rozycki
2015-06-15 21:37     ` Joseph Myers
2015-06-15 22:00       ` Maciej W. Rozycki
2015-06-15 22:09         ` Joseph Myers
2015-06-16 12:19           ` Maciej W. Rozycki
2015-06-16 12:26             ` Joseph Myers
2015-06-16 13:28               ` Maciej W. Rozycki
2015-06-16 16:13                 ` Joseph Myers
2015-06-17 10:43                 ` Richard Sandiford
2015-06-17 17:45                   ` Steve Ellcey
2015-06-17 18:44                     ` Maciej W. Rozycki
2015-06-17 18:52                       ` Richard Sandiford
2015-06-17 21:09                         ` Steve Ellcey
2015-06-17 22:06                           ` Matthew Fortune
2015-06-18 12:32                             ` Maciej W. Rozycki
2015-06-18 16:02                               ` Steve Ellcey
2015-06-29 16:10                                 ` Maciej W. Rozycki
2015-06-29 19:07                                   ` Matthew Fortune
2015-06-29 19:46                                     ` Moore, Catherine
2015-07-06 17:35                                     ` Steve Ellcey
2015-06-30  7:35                                   ` Richard Biener
2015-06-18 12:04                         ` Maciej W. Rozycki
2015-06-17 19:51                       ` Steve Ellcey

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).