From: Jie Mei Date: Sat, 14 Sep 2024 07:04:09 +0000 (+0800) Subject: MIPS: Add MSUBF.fmt instruction for MIPSr6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=51a3669ab65586c3cffe302a1bf7c368ad08e61a;p=thirdparty%2Fgcc.git 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 (fms4): Generates MSUBF.fmt instructions. (*fms4_msubf): Same as above. (fnma4): Same as above. (*fnma4_msubf): Same as above. gcc/testsuite/ChangeLog: * gcc.target/mips/mips-msubf.c: New tests for MIPSr6. --- diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index aadf4dd676e..99654cc8fde 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 "*fms4_msub3" [(set (match_operand:ANYF 0 "register_operand" "=f") @@ -2639,6 +2640,16 @@ [(set_attr "type" "fmadd") (set_attr "mode" "")]) +(define_insn "*fms4_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.\t%0,%1,%2" + [(set_attr "type" "fmadd") + (set_attr "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) @@ -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)") + "((ISA_HAS_FUSED_MADD3 || ISA_HAS_FUSED_MADD4) + && !HONOR_SIGNED_ZEROS (mode)) + || ISA_HAS_FUSED_MADDF") (define_insn "*fnma4_nmsub3" [(set (match_operand:ANYF 0 "register_operand" "=f") @@ -2673,6 +2685,16 @@ [(set_attr "type" "fmadd") (set_attr "mode" "")]) +(define_insn "*fnma4_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.\t%0,%1,%2" + [(set_attr "type" "fmadd") + (set_attr "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) 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; +} + +