]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
MIPS: Add MSUBF.fmt instruction for MIPSr6
authorJie Mei <jie.mei@oss.cipunited.com>
Sat, 14 Sep 2024 07:04:09 +0000 (15:04 +0800)
committerYunQiang Su <syq@debian.org>
Sat, 27 Sep 2025 05:48:40 +0000 (13:48 +0800)
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
gcc/testsuite/gcc.target/mips/mips-msubf.c [new file with mode: 0644]

index aadf4dd676e23f3591940794811230349d1ed8b1..99654cc8fde0ccc378e112a56abb530ba131e32a 100644 (file)
        (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")
   [(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)
        (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")
   [(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 (file)
index 0000000..424ca21
--- /dev/null
@@ -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;
+}
+
+