https://gcc.gnu.org/g:51a3669ab65586c3cffe302a1bf7c368ad08e61a

commit r16-4110-g51a3669ab65586c3cffe302a1bf7c368ad08e61a
Author: Jie Mei <[email protected]>
Date:   Sat Sep 14 15:04:09 2024 +0800

    MIPS: Add MSUBF.fmt instruction for MIPSr6
    
    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.

Diff:
---
 gcc/config/mips/mips.md                    | 28 ++++++++++++++++++++++++---
 gcc/testsuite/gcc.target/mips/mips-msubf.c | 31 ++++++++++++++++++++++++++++++
 2 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index aadf4dd676e2..99654cc8fde0 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2617,7 +2617,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")
@@ -2639,6 +2640,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)
@@ -2650,8 +2661,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")
@@ -2673,6 +2685,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 000000000000..424ca21e7f8b
--- /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;
+}
+
+

Reply via email to