config.gcc: Add fused-madd.opt.
authorSteve Ellcey <sellcey@imgtec.com>
Mon, 6 Jul 2015 17:29:33 +0000 (17:29 +0000)
committerSteve Ellcey <sje@gcc.gnu.org>
Mon, 6 Jul 2015 17:29:33 +0000 (17:29 +0000)
2015-07-06  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.

From-SVN: r225468

gcc/ChangeLog
gcc/config.gcc
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/config/mips/mips.md
gcc/config/mips/mips.opt

index fe64509b9af70a47c17a4b0f93011c7043544e94..7c73d50d052497a0107e086e0815977711b06ea7 100644 (file)
@@ -1,3 +1,44 @@
+2015-07-06  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.
+
 2015-07-06  Alan Lawrence  <alan.lawrence@arm.com>
 
        PR target/65956
index f0405fe2bcd780402a38ab5e6a8f1ad656e30bc4..900aa18c95d3fed5b25bc4f44af9bc2e06dfa569 100644 (file)
@@ -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
index 95a0ae3f44c6e93f7538bdd029bac76ff221a6cb..ce21a0fd215108b04d5b8f84f950f6ccc7294300 100644 (file)
@@ -4054,13 +4054,11 @@ 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_SIGNED_ZEROS (mode))
+      if (float_mode_p && ISA_HAS_UNFUSED_MADD4 && !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_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)
@@ -4087,9 +4085,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;
@@ -4121,13 +4117,10 @@ 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_SIGNED_ZEROS (mode))
+      if (float_mode_p && ISA_HAS_UNFUSED_MADD4)
        {
-         /* 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.  */
          rtx op = XEXP (x, 0);
          if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
              && GET_CODE (XEXP (op, 0)) == MULT)
@@ -4147,8 +4140,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:
index bceef31b4a3b6cd99dfc08d5dead926ac5eb15b1..7a6f9171ac7e7fcfb764b4a965959dcee2c0de5f 100644 (file)
@@ -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
index f6912e11c2d33df82b459f1234eed0f936aff4ec..4f5692ce662e78a08147d9959785d4d1c4a0b426 100644 (file)
 
 ;; Floating point multiply accumulate instructions.
 
-;; The various multiply accumulate instructions can be used even when
-;; HONOR_NANS is true because while IEEE 754-2008 requires the negate
-;; operation to negate the sign of a NAN and the MIPS neg instruction does
-;; not do this, the multiply and add (or minus) parts of these instructions
-;; have no requirement on how the sign of a NAN is handled and so the final
-;; sign bit of the entire operation is undefined.
+(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 "*madd4<mode>"
+(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 can be used even when HONOR_NANS
+;; is true because while IEEE 754-2008 requires the negate operation to
+;; negate the sign of a NAN and the MIPS neg instruction does not do this,
+;; the fma part of the instruction has no requirement on how the sign of
+;; a NAN is handled and so the final sign bit of the entire operation is
+;; undefined.
+
+(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)")
+
+(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"
+  "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"
   "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_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_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)"
-  "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_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_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)"
+       (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_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)"
+       (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_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)"
-  "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)"
-  "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>"
+;; Like with the fused fms, fnma, and fnms instructions, these unfused
+;; instructions can be used even if HONOR_NANS is set because while
+;; IEEE 754-2008 requires the negate operation to negate the sign of a
+;; NAN and the MIPS neg instruction does not do this, the multiply and
+;; add (or subtract) part of the instruction has no requirement on how
+;; the sign of a NAN is handled and so the final sign bit of the entire
+;; operation is undefined.
+
+(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"
+  "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)"
-  "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"
+  "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.
+
+;; 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)"
-  "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)"
-  "nmsub.<fmt>\t%0,%1,%2"
+  "nmsub.<fmt>\t%0,%1,%2,%3"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
index a9baebe6a44d6e79064ba18a624c6e5b038d69cc..348c6e03f1ef5d571b70c0380c2ca7f3f4e9820a 100644 (file)
@@ -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