diff mbox series

MIPS: Add MSUBF.fmt instruction for MIPSr6

Message ID 20240914070409.1781705-1-jie.mei@oss.cipunited.com
State New
Headers show
Series MIPS: Add MSUBF.fmt instruction for MIPSr6 | expand

Commit Message

Jie Mei Sept. 14, 2024, 7:04 a.m. UTC
GCC currently uses two instructions (NEG.fmt and MADDF.fmt) for
operations like `x - (y * z)' for MIPSr6. We can further tune this by
using only MSUBF.fmt instead of those two.

This patch adds MSUBF.fmt instrutions with corresponding tests.

gcc/ChangeLog:

	* config/mips/mips.md (fms<mode>4): Generates MSUBF.fmt
	instructions.
	(*fms<mode>4_msubf): Same as above.
	(fnma<mode>4): Same as above.
	(*fnma<mode>4_msubf): Same as above.

gcc/testsuite/ChangeLog:

	* gcc.target/mips/mips-msubf.c: New tests for MIPSr6.
---
 gcc/config/mips/mips.md                    | 28 ++++++++++++++++---
 gcc/testsuite/gcc.target/mips/mips-msubf.c | 31 ++++++++++++++++++++++
 2 files changed, 56 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/mips-msubf.c
diff mbox series

Patch

diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 737d2566ec8..e6f20af34f0 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2609,7 +2609,8 @@ 
 	(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)")
+  "(ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4)
+   || ISA_HAS_FUSED_MADDF")
 
 (define_insn "*fms<mode>4_msub3"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
@@ -2631,6 +2632,16 @@ 
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
+(define_insn "*fms<mode>4_msubf"
+  [(set (match_operand:ANYF 0 "register_operand" "=f")
+	(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_MADDF"
+  "msubf.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fmadd")
+   (set_attr "mode" "<UNITMODE>")])
+
 ;; 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)
@@ -2642,8 +2653,9 @@ 
 	(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)")
+  "((ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4)
+   && !HONOR_SIGNED_ZEROS (<MODE>mode))
+   || ISA_HAS_FUSED_MADDF")
 
 (define_insn "*fnma<mode>4_nmsub3"
   [(set (match_operand:ANYF 0 "register_operand" "=f")
@@ -2665,6 +2677,16 @@ 
   [(set_attr "type" "fmadd")
    (set_attr "mode" "<UNITMODE>")])
 
+(define_insn "*fnma<mode>4_msubf"
+  [(set (match_operand:ANYF 0 "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" "0")))]
+  "ISA_HAS_FUSED_MADDF"
+  "msubf.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fmadd")
+   (set_attr "mode" "<UNITMODE>")])
+
 ;; 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)
diff --git a/gcc/testsuite/gcc.target/mips/mips-msubf.c b/gcc/testsuite/gcc.target/mips/mips-msubf.c
new file mode 100644
index 00000000000..424ca21e7f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips-msubf.c
@@ -0,0 +1,31 @@ 
+/* { dg-do compile } */
+/* { dg-options "-mhard-float -ffast-math -march=mips32r6" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" "-O1" } { "" } } */
+/* { dg-final { scan-assembler-times "\tmsubf\\.s\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tmsubf\\.d\t" 2 } } */
+
+NOMIPS16 float
+test01 (float x, float y, float z)
+{
+  return x - (y * z);
+}
+
+NOMIPS16 double
+test02 (double x, double y, double z)
+{
+  return x - (y * z);
+}
+
+NOMIPS16 float
+test03 (float x, float y, float z)
+{
+  return (y * z) - x;
+}
+
+NOMIPS16 double
+test04 (double x, double y, double z)
+{
+  return (y * z) - x;
+}
+
+