]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
mips.c (mips_rtx_costs): Handle FMA.
authorRichard Sandiford <rdsandiford@googlemail.com>
Sun, 7 Nov 2010 08:31:21 +0000 (08:31 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sun, 7 Nov 2010 08:31:21 +0000 (08:31 +0000)
gcc/
* config/mips/mips.c (mips_rtx_costs): Handle FMA.
* config/mips/mips.md (*madd4<mode>, *madd3<mode>, *msub4<mode>)
(*msub3<mode>, *nmadd4<mode>_fastmath, *nmadd3<mode>_fastmath)
(*nmsub4<mode>_fastmath, *nmsub3<mode>_fastmath): Delete.
(*nmadd4<mode>, *nmadd3<mode>. *nmsub4<mode>, *nmsub3<mode>): Redefine
to use FMA.
(fma<mode>4, *fma<mode>4_madd3, *fma<mode>4_madd4): New patterns.
(fms<mode>4, *fms<mode>4_msub3, *fms<mode>4_msub4): Likewise.
(fnms<mode>4, *fnms<mode>4_nmadd3, *fnms<mode>4_nmadd4): Likewise.
(fnma<mode>4, *fnma<mode>4_nmsub3, *fnma<mode>4_nmsub4): Likewise.

gcc/testsuite/
* gcc.target/mips/mips.exp: Add support for -ffp-contract.
* gcc.target/mips/fma-1.c: New test.
* gcc.target/mips/fma-2.c: Likewise.
* gcc.target/mips/fma-3.c: Likewise.
* gcc.target/mips/fma-4.c: Likewise.
* gcc.target/mips/fma-5.c: Likewise.
* gcc.target/mips/fma-6.c: Likewise.
* gcc.target/mips/fma-7.c: Likewise.
* gcc.target/mips/fma-8.c: Likewise.
* gcc.target/mips/fma-9.c: Likewise.
* gcc.target/mips/fma-10.c: Likewise.
* gcc.target/mips/fma-11.c: Likewise.
* gcc.target/mips/fma-12.c: Likewise.
* gcc.target/mips/fma-13.c: Likewise.
* gcc.target/mips/fma-14.c: Likewise.
* gcc.target/mips/fma-15.c: Likewise.
* gcc.target/mips/fma-16.c: Likewise.
* gcc.target/mips/fma-17.c: Likewise.
* gcc.target/mips/fma-18.c: Likewise.
* gcc.target/mips/fma-19.c: Likewise.
* gcc.target/mips/fma-20.c: Likewise.

From-SVN: r166414

25 files changed:
gcc/ChangeLog
gcc/config/mips/mips.c
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/fma-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-11.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-12.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-14.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-15.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-16.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-17.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-18.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-19.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-20.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/fma-9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/mips.exp

index cb4c17a7ee88d7215426288fc4c646e1afb34bcb..8b590661467e014a4fcb58639f31f7ca81b42367 100644 (file)
@@ -1,3 +1,16 @@
+2010-11-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * config/mips/mips.c (mips_rtx_costs): Handle FMA.
+       * config/mips/mips.md (*madd4<mode>, *madd3<mode>, *msub4<mode>)
+       (*msub3<mode>, *nmadd4<mode>_fastmath, *nmadd3<mode>_fastmath)
+       (*nmsub4<mode>_fastmath, *nmsub3<mode>_fastmath): Delete.
+       (*nmadd4<mode>, *nmadd3<mode>. *nmsub4<mode>, *nmsub3<mode>): Redefine
+       to use FMA.
+       (fma<mode>4, *fma<mode>4_madd3, *fma<mode>4_madd4): New patterns.
+       (fms<mode>4, *fms<mode>4_msub3, *fms<mode>4_msub4): Likewise.
+       (fnms<mode>4, *fnms<mode>4_nmadd3, *fnms<mode>4_nmadd4): Likewise.
+       (fnma<mode>4, *fnma<mode>4_nmsub3, *fnma<mode>4_nmsub4): Likewise.
+
 2010-11-06  Simon Martin  <simartin@users.sourceforge.net>
 
        PR c/43384
index 76c0786713ecd82ad6ddb8cf04a587ce76649ec3..c10e9d1a7597c1064951e7ffe1d8627fbfb126ca 100644 (file)
@@ -3827,6 +3827,10 @@ mips_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
        *total = mips_cost->int_mult_si;
       return false;
 
+    case FMA:
+      *total = mips_fp_mult_cost (mode);
+      return false;
+
     case DIV:
       /* Check for a reciprocal.  */
       if (float_mode_p
index b7893941408b66106e404a9eda98c758b5084e38..a5f5d488b6b3c88bfac9b18a33db5521764cd5ae 100644 (file)
 
 ;; Floating point multiply accumulate instructions.
 
-(define_insn "*madd4<mode>"
-  [(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"
-  "madd.<fmt>\t%0,%3,%1,%2"
-  [(set_attr "type" "fmadd")
-   (set_attr "mode" "<UNITMODE>")])
+(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_FP_MADD3_MSUB3 || ISA_HAS_FP_MADD4_MSUB4")
 
-(define_insn "*madd3<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" "0")))]
-  "ISA_HAS_FP_MADD3_MSUB3 && 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_FP_MADD3_MSUB3"
   "madd.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*msub4<mode>"
+(define_insn "*fma<mode>4_madd4"
   [(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"
-  "msub.<fmt>\t%0,%3,%1,%2"
+       (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_FP_MADD4_MSUB4"
+  "madd.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*msub3<mode>"
+(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_FP_MADD3_MSUB3 || ISA_HAS_FP_MADD4_MSUB4")
+
+(define_insn "*fms<mode>4_msub3"
   [(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"
+       (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_FP_MADD3_MSUB3"
   "msub.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmadd4<mode>"
+(define_insn "*fms<mode>4_msub4"
   [(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 (<MODE>mode)
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
-  "nmadd.<fmt>\t%0,%3,%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" "f"))))]
+  "ISA_HAS_FP_MADD4_MSUB4"
+  "msub.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmadd3<mode>"
+;; If we're ignoring signed zeros, we can use NMADD (-(a * b + c)) to
+;; implement fnms (-a * b - c, which is unconditionally equivalent to
+;; -(a * b) - c).
+(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_NMADD3_NMSUB3 (<MODE>mode) || ISA_HAS_NMADD4_NMSUB4 (<MODE>mode))
+   && !HONOR_SIGNED_ZEROS (<MODE>mode)
+   && !HONOR_NANS (<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"))))]
+       (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_NMADD3_NMSUB3 (<MODE>mode)
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
+   && !HONOR_SIGNED_ZEROS (<MODE>mode)
    && !HONOR_NANS (<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")))]
+       (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_NMADD4_NMSUB4 (<MODE>mode)
-   && TARGET_FUSED_MADD
    && !HONOR_SIGNED_ZEROS (<MODE>mode)
    && !HONOR_NANS (<MODE>mode)"
   "nmadd.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmadd3<mode>_fastmath"
+(define_insn "*nmadd3"
   [(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 (<MODE>mode)
-   && TARGET_FUSED_MADD
-   && !HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
+       (neg:ANYF
+        (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_NMADD3_NMSUB3 (<MODE>mode) && !HONOR_NANS (<MODE>mode)"
   "nmadd.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub4<mode>"
+(define_insn "*nmadd4"
   [(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 (<MODE>mode)
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
-  "nmsub.<fmt>\t%0,%1,%2,%3"
+       (neg:ANYF
+        (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_NMADD4_NMSUB4 (<MODE>mode) && !HONOR_NANS (<MODE>mode)"
+  "nmadd.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub3<mode>"
+;; If we're ignoring signed zeros, we can use NMSUB (-(a * b - c)) to
+;; implement fnma (-a * b + c, which is unconditionally equivalent to
+;; -(a * b) + c).
+(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_NMADD3_NMSUB3 (<MODE>mode) || ISA_HAS_NMADD4_NMSUB4 (<MODE>mode))
+   && !HONOR_SIGNED_ZEROS (<MODE>mode)
+   && !HONOR_NANS (<MODE>mode)")
+
+(define_insn "*fnma<mode>4_nmsub3"
   [(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"))))]
+       (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_NMADD3_NMSUB3 (<MODE>mode)
-   && TARGET_FUSED_MADD
-   && HONOR_SIGNED_ZEROS (<MODE>mode)
+   && !HONOR_SIGNED_ZEROS (<MODE>mode)
    && !HONOR_NANS (<MODE>mode)"
   "nmsub.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub4<mode>_fastmath"
+(define_insn "*fnma<mode>4_nmsub4"
   [(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"))))]
+       (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_NMADD4_NMSUB4 (<MODE>mode)
-   && TARGET_FUSED_MADD
    && !HONOR_SIGNED_ZEROS (<MODE>mode)
    && !HONOR_NANS (<MODE>mode)"
-  "nmsub.<fmt>\t%0,%1,%2,%3"
+  "nmsub.<fmt>\t%0,%3,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
-(define_insn "*nmsub3<mode>_fastmath"
+(define_insn "*nmsub3"
   [(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 (<MODE>mode)
-   && TARGET_FUSED_MADD
-   && !HONOR_SIGNED_ZEROS (<MODE>mode)
-   && !HONOR_NANS (<MODE>mode)"
+       (neg:ANYF
+        (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_NMADD3_NMSUB3 (<MODE>mode) && !HONOR_NANS (<MODE>mode)"
   "nmsub.<fmt>\t%0,%1,%2"
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
+(define_insn "*nmsub4"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+       (neg:ANYF
+        (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_NMADD4_NMSUB4 (<MODE>mode) && !HONOR_NANS (<MODE>mode)"
+  "nmsub.<fmt>\t%0,%3,%1,%2"
+  [(set_attr "type" "fmadd")
+   (set_attr "mode" "<UNITMODE>")])
+
 ;;
 ;;  ....................
 ;;
index c5ccdb8000526f6d529eafbb2fa5bd6130509742..806b1d14a64791bd0b5b2748ee9b9b72d486d6ff 100644 (file)
@@ -1,3 +1,27 @@
+2010-11-07  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * gcc.target/mips/mips.exp: Add support for -ffp-contract.
+       * gcc.target/mips/fma-1.c: New test.
+       * gcc.target/mips/fma-2.c: Likewise.
+       * gcc.target/mips/fma-3.c: Likewise.
+       * gcc.target/mips/fma-4.c: Likewise.
+       * gcc.target/mips/fma-5.c: Likewise.
+       * gcc.target/mips/fma-6.c: Likewise.
+       * gcc.target/mips/fma-7.c: Likewise.
+       * gcc.target/mips/fma-8.c: Likewise.
+       * gcc.target/mips/fma-9.c: Likewise.
+       * gcc.target/mips/fma-10.c: Likewise.
+       * gcc.target/mips/fma-11.c: Likewise.
+       * gcc.target/mips/fma-12.c: Likewise.
+       * gcc.target/mips/fma-13.c: Likewise.
+       * gcc.target/mips/fma-14.c: Likewise.
+       * gcc.target/mips/fma-15.c: Likewise.
+       * gcc.target/mips/fma-16.c: Likewise.
+       * gcc.target/mips/fma-17.c: Likewise.
+       * gcc.target/mips/fma-18.c: Likewise.
+       * gcc.target/mips/fma-19.c: Likewise.
+       * gcc.target/mips/fma-20.c: Likewise.
+
 2010-11-06  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/cpp0x/constexpr-ctor3.C: New.
diff --git a/gcc/testsuite/gcc.target/mips/fma-1.c b/gcc/testsuite/gcc.target/mips/fma-1.c
new file mode 100644 (file)
index 0000000..d167473
--- /dev/null
@@ -0,0 +1,82 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -fno-fast-math -ffp-contract=off" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.s\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.s\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmadd\\.d\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.d\t" 3 } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* We should not use NMADD or NMSUB without -ffinite-math-only because
+   those instructions may perform arithmetic negation.  */
+
+NOMIPS16 float
+madd_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+msub_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+not_nmadd_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+not_nmsub_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+not_nmadd_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, -d);
+}
+
+NOMIPS16 float
+not_nmsub_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, d);
+}
+
+NOMIPS16 double
+madd_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+msub_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+not_nmadd_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+not_nmsub_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+not_nmadd_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, -d);
+}
+
+NOMIPS16 double
+not_nmsub_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-10.c b/gcc/testsuite/gcc.target/mips/fma-10.c
new file mode 100644 (file)
index 0000000..bb3f31b
--- /dev/null
@@ -0,0 +1,62 @@
+/* { dg-options "-mpaired-single -O -ffast-math -ftree-vectorize" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.ps\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.ps\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.ps\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.ps\t" 2 } } */
+
+#define N 512
+float a[N], b[N], c[N], d[N];
+
+NOMIPS16 void
+madd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (b[i], c[i], d[i]);
+}
+
+NOMIPS16 float
+msub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (b[i], c[i], -d[i]);
+}
+
+NOMIPS16 float
+nmadd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -__builtin_fmaf (b[i], c[i], d[i]);
+}
+
+NOMIPS16 float
+nmsub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -__builtin_fmaf (b[i], c[i], -d[i]);
+}
+
+NOMIPS16 float
+nmadd_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (-b[i], c[i], -d[i]);
+}
+
+NOMIPS16 float
+nmsub_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (-b[i], c[i], d[i]);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-11.c b/gcc/testsuite/gcc.target/mips/fma-11.c
new file mode 100644 (file)
index 0000000..17f124f
--- /dev/null
@@ -0,0 +1,79 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -fno-fast-math -ffp-contract=off" } */
+/* { dg-final { scan-assembler-not "\tmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tmsub\\." } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* No function should use fused operations, however high the -O level.  */
+
+NOMIPS16 float
+not_madd_s (float b, float c, float d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 float
+not_msub_s (float b, float c, float d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 float
+not_nmadd_s (float b, float c, float d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 float
+not_nmsub_s (float b, float c, float d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 float
+not_nmadd_s_2 (float b, float c, float d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 float
+not_nmsub_s_2 (float b, float c, float d)
+{
+  return -b * c + d;
+}
+
+NOMIPS16 double
+not_madd_d (double b, double c, double d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 double
+not_msub_d (double b, double c, double d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 double
+not_nmadd_d (double b, double c, double d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 double
+not_nmsub_d (double b, double c, double d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 double
+not_nmadd_d_2 (double b, double c, double d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 double
+not_nmsub_d_2 (double b, double c, double d)
+{
+  return -b * c + d;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-12.c b/gcc/testsuite/gcc.target/mips/fma-12.c
new file mode 100644 (file)
index 0000000..6a6303c
--- /dev/null
@@ -0,0 +1,82 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O2 -fno-fast-math -ffp-contract=fast" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.s\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.s\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmadd\\.d\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.d\t" 3 } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* We should not use NMADD or NMSUB without -ffinite-math-only because
+   those instructions may perform arithmetic negation.  */
+
+NOMIPS16 float
+madd_s (float b, float c, float d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 float
+msub_s (float b, float c, float d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 float
+not_nmadd_s (float b, float c, float d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 float
+not_nmsub_s (float b, float c, float d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 float
+not_nmadd_s_2 (float b, float c, float d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 float
+not_nmsub_s_2 (float b, float c, float d)
+{
+  return -b * c + d;
+}
+
+NOMIPS16 double
+madd_d (double b, double c, double d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 double
+msub_d (double b, double c, double d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 double
+not_nmadd_d (double b, double c, double d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 double
+not_nmsub_d (double b, double c, double d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 double
+not_nmadd_d_2 (double b, double c, double d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 double
+not_nmsub_d_2 (double b, double c, double d)
+{
+  return -b * c + d;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-13.c b/gcc/testsuite/gcc.target/mips/fma-13.c
new file mode 100644 (file)
index 0000000..2dbff9b
--- /dev/null
@@ -0,0 +1,81 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O2 -ffast-math" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tmadd\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.d\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.d\t" 2 } } */
+
+NOMIPS16 float
+madd_s (float b, float c, float d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 float
+msub_s (float b, float c, float d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 float
+nmadd_s (float b, float c, float d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 float
+nmsub_s (float b, float c, float d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 float
+nmadd_s_2 (float b, float c, float d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 float
+nmsub_s_2 (float b, float c, float d)
+{
+  return -b * c + d;
+}
+
+NOMIPS16 double
+madd_d (double b, double c, double d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 double
+msub_d (double b, double c, double d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 double
+nmadd_d (double b, double c, double d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 double
+nmsub_d (double b, double c, double d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 double
+nmadd_d_2 (double b, double c, double d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 double
+nmsub_d_2 (double b, double c, double d)
+{
+  return -b * c + d;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-14.c b/gcc/testsuite/gcc.target/mips/fma-14.c
new file mode 100644 (file)
index 0000000..383effd
--- /dev/null
@@ -0,0 +1,64 @@
+/* { dg-options "-mpaired-single -O3 -fno-fast-math -ftree-vectorize -ffp-contract=off" } */
+/* { dg-final { scan-assembler-not "\tmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tmsub\\." } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* No function should use fused operations, however high the -O level.  */
+
+#define N 512
+float a[N], b[N], c[N], d[N];
+
+NOMIPS16 void
+not_madd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = b[i] * c[i] + d[i];
+}
+
+NOMIPS16 float
+not_msub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = b[i] * c[i] - d[i];
+}
+
+NOMIPS16 float
+not_nmadd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -(b[i] * c[i] + d[i]);
+}
+
+NOMIPS16 float
+not_nmsub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -(b[i] * c[i] - d[i]);
+}
+
+NOMIPS16 float
+not_nmadd_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -b[i] * c[i] - d[i];
+}
+
+NOMIPS16 float
+not_nmsub_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -b[i] * c[i] + d[i];
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-15.c b/gcc/testsuite/gcc.target/mips/fma-15.c
new file mode 100644 (file)
index 0000000..4fdfeab
--- /dev/null
@@ -0,0 +1,65 @@
+/* { dg-options "-mpaired-single -O2 -fno-fast-math -ftree-vectorize -ffp-contract=fast" } */
+/* { dg-final { scan-assembler "\tmadd\\.ps" } } */
+/* { dg-final { scan-assembler "\tmsub\\.ps" } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* We should not use NMADD or NMSUB without -ffinite-math-only because
+   those instructions may perform arithmetic negation.  */
+
+#define N 512
+float a[N], b[N], c[N], d[N];
+
+NOMIPS16 void
+madd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = b[i] * c[i] + d[i];
+}
+
+NOMIPS16 float
+msub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = b[i] * c[i] - d[i];
+}
+
+NOMIPS16 float
+not_nmadd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -(b[i] * c[i] + d[i]);
+}
+
+NOMIPS16 float
+not_nmsub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -(b[i] * c[i] - d[i]);
+}
+
+NOMIPS16 float
+not_nmadd_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -b[i] * c[i] - d[i];
+}
+
+NOMIPS16 float
+not_nmsub_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -b[i] * c[i] + d[i];
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-16.c b/gcc/testsuite/gcc.target/mips/fma-16.c
new file mode 100644 (file)
index 0000000..16cda12
--- /dev/null
@@ -0,0 +1,62 @@
+/* { dg-options "-mpaired-single -O2 -ffast-math -ftree-vectorize" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.ps" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.ps" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.ps" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.ps" 2 } } */
+
+#define N 512
+float a[N], b[N], c[N], d[N];
+
+NOMIPS16 void
+madd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = b[i] * c[i] + d[i];
+}
+
+NOMIPS16 float
+msub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = b[i] * c[i] - d[i];
+}
+
+NOMIPS16 float
+nmadd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -(b[i] * c[i] + d[i]);
+}
+
+NOMIPS16 float
+nmsub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -(b[i] * c[i] - d[i]);
+}
+
+NOMIPS16 float
+nmadd_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -b[i] * c[i] - d[i];
+}
+
+NOMIPS16 float
+nmsub_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -b[i] * c[i] + d[i];
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-17.c b/gcc/testsuite/gcc.target/mips/fma-17.c
new file mode 100644 (file)
index 0000000..87b2de1
--- /dev/null
@@ -0,0 +1,82 @@
+/* { dg-options "-mgp64 -mhard-float isa=loongson -O3 -fno-fast-math -ffp-contract=off" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.s\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.s\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmadd\\.d\t" 3 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.d\t" 3 } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* We should not use NMADD or NMSUB without -ffinite-math-only because
+   those instructions may perform arithmetic negation.  */
+
+NOMIPS16 float
+madd_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+msub_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+not_nmadd_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+not_nmsub_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+not_nmadd_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, -d);
+}
+
+NOMIPS16 float
+not_nmsub_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, d);
+}
+
+NOMIPS16 double
+madd_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+msub_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+not_nmadd_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+not_nmsub_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+not_nmadd_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, -d);
+}
+
+NOMIPS16 double
+not_nmsub_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-18.c b/gcc/testsuite/gcc.target/mips/fma-18.c
new file mode 100644 (file)
index 0000000..244f232
--- /dev/null
@@ -0,0 +1,81 @@
+/* { dg-options "-mgp64 -mhard-float isa=loongson -O -ffast-math" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tmadd\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.d\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.d\t" 2 } } */
+
+NOMIPS16 float
+madd_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+msub_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+nmadd_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+nmsub_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+nmadd_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, -d);
+}
+
+NOMIPS16 float
+not_nmsub_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, d);
+}
+
+NOMIPS16 double
+madd_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+msub_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+nmadd_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+nmsub_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+nmadd_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, -d);
+}
+
+NOMIPS16 double
+nmsub_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-19.c b/gcc/testsuite/gcc.target/mips/fma-19.c
new file mode 100644 (file)
index 0000000..c038f19
--- /dev/null
@@ -0,0 +1,79 @@
+/* { dg-options "-mgp64 -mhard-float isa=loongson -O3 -fno-fast-math -ffp-contract=off" } */
+/* { dg-final { scan-assembler-not "\tmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tmsub\\." } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* No function should use fused operations, however high the -O level.  */
+
+NOMIPS16 float
+not_madd_s (float b, float c, float d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 float
+not_msub_s (float b, float c, float d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 float
+not_nmadd_s (float b, float c, float d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 float
+not_nmsub_s (float b, float c, float d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 float
+not_nmadd_s_2 (float b, float c, float d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 float
+not_nmsub_s_2 (float b, float c, float d)
+{
+  return -b * c + d;
+}
+
+NOMIPS16 double
+not_madd_d (double b, double c, double d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 double
+not_msub_d (double b, double c, double d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 double
+not_nmadd_d (double b, double c, double d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 double
+not_nmsub_d (double b, double c, double d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 double
+not_nmadd_d_2 (double b, double c, double d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 double
+not_nmsub_d_2 (double b, double c, double d)
+{
+  return -b * c + d;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-2.c b/gcc/testsuite/gcc.target/mips/fma-2.c
new file mode 100644 (file)
index 0000000..26c7742
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -fno-fast-math -ffp-contract=off -ffinite-math-only" } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+NOMIPS16 float
+nmadd_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 double
+nmadd_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-20.c b/gcc/testsuite/gcc.target/mips/fma-20.c
new file mode 100644 (file)
index 0000000..ab0cbdf
--- /dev/null
@@ -0,0 +1,81 @@
+/* { dg-options "-mgp64 -mhard-float isa=loongson -O2 -ffast-math" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tmadd\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.d\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.d\t" 2 } } */
+
+NOMIPS16 float
+madd_s (float b, float c, float d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 float
+msub_s (float b, float c, float d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 float
+nmadd_s (float b, float c, float d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 float
+nmsub_s (float b, float c, float d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 float
+nmadd_s_2 (float b, float c, float d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 float
+nmsub_s_2 (float b, float c, float d)
+{
+  return -b * c + d;
+}
+
+NOMIPS16 double
+madd_d (double b, double c, double d)
+{
+  return b * c + d;
+}
+
+NOMIPS16 double
+msub_d (double b, double c, double d)
+{
+  return b * c + -d;
+}
+
+NOMIPS16 double
+nmadd_d (double b, double c, double d)
+{
+  return -(b * c + d);
+}
+
+NOMIPS16 double
+nmsub_d (double b, double c, double d)
+{
+  return -(b * c + -d);
+}
+
+NOMIPS16 double
+nmadd_d_2 (double b, double c, double d)
+{
+  return -b * c - d;
+}
+
+NOMIPS16 double
+nmsub_d_2 (double b, double c, double d)
+{
+  return -b * c + d;
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-3.c b/gcc/testsuite/gcc.target/mips/fma-3.c
new file mode 100644 (file)
index 0000000..1a387c2
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -fno-fast-math -ffp-contract=off -ffinite-math-only" } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+
+NOMIPS16 float
+nmsub_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 double
+nmsub_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, -d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-4.c b/gcc/testsuite/gcc.target/mips/fma-4.c
new file mode 100644 (file)
index 0000000..4ae7f5f
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -fno-fast-math -ffp-contract=off -ffinite-math-only" } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* These patterns can only use NMADD if -fno-signed-zeros is in effect.  */
+
+NOMIPS16 float
+not_nmadd_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, -d);
+}
+
+NOMIPS16 double
+not_nmadd_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, -d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-5.c b/gcc/testsuite/gcc.target/mips/fma-5.c
new file mode 100644 (file)
index 0000000..410a904
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -fno-fast-math -ffp-contract=off -ffinite-math-only" } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* These patterns can only use NMSUB if -fno-signed-zeros is in effect.  */
+
+NOMIPS16 float
+not_nmsub_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, d);
+}
+
+NOMIPS16 double
+not_nmsub_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-6.c b/gcc/testsuite/gcc.target/mips/fma-6.c
new file mode 100644 (file)
index 0000000..3599837
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -ffast-math" } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+NOMIPS16 float
+nmadd_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, -d);
+}
+
+NOMIPS16 double
+nmadd_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, -d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-7.c b/gcc/testsuite/gcc.target/mips/fma-7.c
new file mode 100644 (file)
index 0000000..11817e6
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O3 -ffast-math" } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+
+NOMIPS16 float
+nmsub_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, d);
+}
+
+NOMIPS16 double
+nmsub_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-8.c b/gcc/testsuite/gcc.target/mips/fma-8.c
new file mode 100644 (file)
index 0000000..d54138d
--- /dev/null
@@ -0,0 +1,81 @@
+/* { dg-options "-mgp64 -mhard-float isa>=4 -O -ffast-math" } */
+/* { dg-final { scan-assembler-times "\tmadd\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.s\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tmadd\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tmsub\\.d\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tnmadd\\.d\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tnmsub\\.d\t" 2 } } */
+
+NOMIPS16 float
+madd_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+msub_s (float b, float c, float d)
+{
+  return __builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+nmadd_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, d);
+}
+
+NOMIPS16 float
+nmsub_s (float b, float c, float d)
+{
+  return -__builtin_fmaf (b, c, -d);
+}
+
+NOMIPS16 float
+nmadd_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, -d);
+}
+
+NOMIPS16 float
+nmsub_s_2 (float b, float c, float d)
+{
+  return __builtin_fmaf (-b, c, d);
+}
+
+NOMIPS16 double
+madd_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+msub_d (double b, double c, double d)
+{
+  return __builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+nmadd_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, d);
+}
+
+NOMIPS16 double
+nmsub_d (double b, double c, double d)
+{
+  return -__builtin_fma (b, c, -d);
+}
+
+NOMIPS16 double
+nmadd_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, -d);
+}
+
+NOMIPS16 double
+nmsub_d_2 (double b, double c, double d)
+{
+  return __builtin_fma (-b, c, d);
+}
diff --git a/gcc/testsuite/gcc.target/mips/fma-9.c b/gcc/testsuite/gcc.target/mips/fma-9.c
new file mode 100644 (file)
index 0000000..a0fc1b0
--- /dev/null
@@ -0,0 +1,70 @@
+/* { dg-options "-mpaired-single -O3 -fno-fast-math -ftree-vectorize -ffp-contract=off" } */
+/* { dg-final { scan-assembler "\tmadd\\.ps\t" } } */
+/* { dg-final { scan-assembler "\tmsub\\.s\t" } } */
+/* { dg-final { scan-assembler-not "\tmsub\\.ps\t" } } */
+/* { dg-final { scan-assembler-not "\tnmadd\\." } } */
+/* { dg-final { scan-assembler-not "\tnmsub\\." } } */
+
+/* We should not use NMADD or NMSUB without -ffinite-math-only because
+   those instructions may perform arithmetic negation.  We don't really
+   expect the nmadd_ps and nmsub_ps functions to use MADD.PS and MSUB.PS,
+   but there's no reason in principle why they shouldn't.
+
+   ??? At the moment, we don't vectorize msub_ps, but we probably should.  */
+
+#define N 512
+float a[N], b[N], c[N], d[N];
+
+NOMIPS16 void
+madd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (b[i], c[i], d[i]);
+}
+
+NOMIPS16 float
+msub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (b[i], c[i], -d[i]);
+}
+
+NOMIPS16 float
+not_nmadd_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -__builtin_fmaf (b[i], c[i], d[i]);
+}
+
+NOMIPS16 float
+not_nmsub_ps (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = -__builtin_fmaf (b[i], c[i], -d[i]);
+}
+
+NOMIPS16 float
+not_nmadd_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (-b[i], c[i], -d[i]);
+}
+
+NOMIPS16 float
+not_nmsub_ps_2 (void)
+{
+  int i;
+
+  for (i = 0; i < N; i++)
+    a[i] = __builtin_fmaf (-b[i], c[i], d[i]);
+}
index 0a7bc1de8dd7b6c32dc4848c5a0769ef95f34a94..1165b17cdf9ad87e7d03ce91b1ecdc91afe32fea 100644 (file)
@@ -292,6 +292,13 @@ foreach option {
     lappend mips_option_groups $option "-f(no-|)$option"
 }
 
+# Add -ffoo= options to mips_option_groups.
+foreach option {
+    fp-contract
+} {
+    lappend mips_option_groups $option "-f$option=.*"
+}
+
 # A list of option groups that have an impact on the ABI.
 set mips_abi_groups {
     abi