This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- From: Steve Ellcey <sellcey at imgtec dot com>
- To: Richard Sandiford <richard dot sandiford at arm dot com>, "Maciej W. Rozycki" <macro at linux-mips dot org>
- Cc: Joseph Myers <joseph at codesourcery dot com>, <gcc-patches at gcc dot gnu dot org>, Catherine Moore <clm at codesourcery dot com>, Matthew Fortune <matthew dot fortune at imgtec dot com>
- Date: Wed, 17 Jun 2015 10:36:11 -0700
- Subject: Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Authentication-results: sourceware.org; auth=none
- References: <4c25620c-546c-40ae-b330-3652fe25f791 at BAMAIL02 dot ba dot imgtec dot org> <alpine dot DEB dot 2 dot 10 dot 1506112002380 dot 15628 at digraph dot polyomino dot org dot uk> <alpine dot LFD dot 2 dot 11 dot 1506152042580 dot 5418 at eddie dot linux-mips dot org> <alpine dot DEB dot 2 dot 10 dot 1506152047390 dot 9772 at digraph dot polyomino dot org dot uk> <alpine dot LFD dot 2 dot 11 dot 1506152215570 dot 5418 at eddie dot linux-mips dot org> <alpine dot DEB dot 2 dot 10 dot 1506152157470 dot 9772 at digraph dot polyomino dot org dot uk> <alpine dot LFD dot 2 dot 11 dot 1506161240330 dot 5418 at eddie dot linux-mips dot org> <alpine dot DEB dot 2 dot 10 dot 1506161215400 dot 4909 at digraph dot polyomino dot org dot uk> <alpine dot LFD dot 2 dot 11 dot 1506161421560 dot 5418 at eddie dot linux-mips dot org> <87mvzy4nwu dot fsf at e105548-lin dot cambridge dot arm dot com>
- Reply-to: <sellcey at imgtec dot com>
On Wed, 2015-06-17 at 11:41 +0100, Richard Sandiford wrote:
> "Maciej W. Rozycki" <macro@linux-mips.org> writes:
> > In that case I think the HONOR_NANS checks will best be globally removed
> > first (where applicable of course), with a separate preparatory change.
>
> With a comment though :-) I.e. say that although NEG is the IEEE negate
> operation, we don't need to honour NaNs in the unfused combiner patterns
> because the rtx operations with which they're being combined don't preserve
> the signs of NaNs.
>
> Thanks,
> Richard
Well, I don't mind removing the HONOR_NAN checks from the MIPS code in
my patch but I am not sure I can do a patch to remove it from the shared
code. I see about 80 HONOR_NAN checks in the shared code and I am not
sure which ones can and cannot be removed.
Is there any reason why my patch (minus the HONOR_NAN checks) would have
to wait for the other changes? Here is a new copy with the HONOR_NAN
checks removed from the fused and unfused fma style instructions (and
with comments to explain why it is not needed).
Steve Ellcey
sellcey@imgtec.com
2015-06-17 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..2d1a233 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -4068,14 +4068,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_NANS (mode)
- && !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)
@@ -4102,9 +4099,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 +4131,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_NANS (mode)
- && 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)
@@ -4163,8 +4154,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..4f5692c 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2475,165 +2475,239 @@
;; 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 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)
- && !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_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)
- && !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_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_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>"
+;; 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)
- && !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"
+ "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
- && !HONOR_SIGNED_ZEROS (<MODE>mode)
- && !HONOR_NANS (<MODE>mode)"
- "nmsub.<fmt>\t%0,%1,%2,%3"
+ (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)"
+ "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
- && !HONOR_SIGNED_ZEROS (<MODE>mode)
- && !HONOR_NANS (<MODE>mode)"
- "nmsub.<fmt>\t%0,%1,%2"
+ (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,%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
- References:
- [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd
- Re: [Patch, MIPS] Enable fp-contract on MIPS and update -mfused-madd