[PATCH] MIPS: Add MIN/MAX.fmt instructions support for MIPS R6

2024-03-20 Thread Jie Mei
This patch adds MIN/MAX.fmt instructios from MIPS R6
with corresponding tests.

gcc/ChangeLog:

* config/mips/i6400.md (i6400_fpu_minmax): New
define_insn_reservation.
* config/mips/mips.h (ISA_HAS_FMIN_FMAX): Define new macro.
* config/mips/mips.md (type): Add fminmax.
(smin3): Generates MIN.fmt instructions.
(smax3): Generates MAX.fmt instructions.
* config/mips/p6600.md (p6600_fpu_fabs): Include fminmax
type.

gcc/testsuite/ChangeLog:

* gcc.target/mips/mips-minmax.c: new tests for MIPS R6.
---
 gcc/config/mips/i6400.md|  6 
 gcc/config/mips/mips.h  |  2 ++
 gcc/config/mips/mips.md | 26 --
 gcc/config/mips/p6600.md|  2 +-
 gcc/testsuite/gcc.target/mips/mips-minmax.c | 40 +
 5 files changed, 73 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/mips-minmax.c

diff --git a/gcc/config/mips/i6400.md b/gcc/config/mips/i6400.md
index 9f216fe0210..d6f691ee217 100644
--- a/gcc/config/mips/i6400.md
+++ b/gcc/config/mips/i6400.md
@@ -219,6 +219,12 @@
(eq_attr "type" "fabs,fneg,fmove"))
   "i6400_fpu_short, i6400_fpu_apu")
 
+;; min, max
+(define_insn_reservation "i6400_fpu_minmax" 2
+  (and (eq_attr "cpu" "i6400")
+   (eq_attr "type" "fminmax"))
+  "i6400_fpu_short+i6400_fpu_logic")
+
 ;; fadd, fsub, fcvt
 (define_insn_reservation "i6400_fpu_fadd" 4
   (and (eq_attr "cpu" "i6400")
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 7145d23c650..5ce984ac99b 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1259,6 +1259,8 @@ struct mips_cpu_info {
 #define ISA_HAS_9BIT_DISPLACEMENT  (mips_isa_rev >= 6  \
 || ISA_HAS_MIPS16E2)
 
+#define ISA_HAS_FMIN_FMAX  (mips_isa_rev >= 6)
+
 /* ISA has data indexed prefetch instructions.  This controls use of
'prefx', along with TARGET_HARD_FLOAT and TARGET_DOUBLE_FLOAT.
(prefx is a cop1x instruction, so can only be used if FP is
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index b0fb5850a9e..d309ebb6848 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -370,6 +370,7 @@
 ;; frsqrt   floating point reciprocal square root
 ;; frsqrt1  floating point reciprocal square root step1
 ;; frsqrt2  floating point reciprocal square root step2
+;; fminmax  floating point min/max
 ;; dspmac   DSP MAC instructions not saturating the accumulator
 ;; dspmacsatDSP MAC instructions that saturate the accumulator
 ;; accext   DSP accumulator extract instructions
@@ -387,8 +388,8 @@
prefetch,prefetchx,condmove,mtc,mfc,mthi,mtlo,mfhi,mflo,const,arith,logical,
shift,slt,signext,clz,pop,trap,imul,imul3,imul3nc,imadd,idiv,idiv3,move,
fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,
-   frsqrt,frsqrt1,frsqrt2,dspmac,dspmacsat,accext,accmod,dspalu,dspalusat,
-   multi,atomic,syncloop,nop,ghost,multimem,
+   frsqrt,frsqrt1,frsqrt2,fminmax,dspmac,dspmacsat,accext,accmod,dspalu,
+   dspalusat,multi,atomic,syncloop,nop,ghost,multimem,
simd_div,simd_fclass,simd_flog2,simd_fadd,simd_fcvt,simd_fmul,simd_fmadd,
simd_fdiv,simd_bitins,simd_bitmov,simd_insert,simd_sld,simd_mul,simd_fcmp,
simd_fexp2,simd_int_arith,simd_bit,simd_shift,simd_splat,simd_fill,
@@ -7971,6 +7972,27 @@
   [(set_attr "move_type" "load")
(set_attr "insn_count" "2")])
 
+;;
+;;  Float point MIN/MAX
+;;
+
+(define_insn "smin3"
+  [(set (match_operand:SCALARF 0 "register_operand" "=f")
+   (smin:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
+  (match_operand:SCALARF 2 "register_operand" "f")))]
+  "ISA_HAS_FMIN_FMAX"
+  "min.\t%0,%1,%2"
+  [(set_attr "type" "fminmax")
+   (set_attr "mode" "")])
+
+(define_insn "smax3"
+  [(set (match_operand:SCALARF 0 "register_operand" "=f")
+   (smax:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
+  (match_operand:SCALARF 2 "register_operand" "f")))]
+  "ISA_HAS_FMIN_FMAX"
+  "max.\t%0,%1,%2"
+  [(set_attr "type" "fminmax")
+  (set_attr "mode" "")])
 
 ;; 2 HI loads are joined.
 (define_peephole2
diff --git a/gcc/config/mips/p6600.md b/gcc/config/mips/p6600.md
index a9e3262cc18..c502f0eb5c6 100644
--- a/gcc/config/mips/p6600.md
+++ b/gcc/config/mips/p6600.md
@@ -170,7 +170,7 @@
 ;; fabs, fneg, fcmp
 (define_insn_reservation "p6600_fpu_fabs" 2
   (and (eq_attr "cpu" "p6600")
-   (ior (eq_attr "type" "fabs,fneg,fcmp,fmove")
+   (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax")
   (and (eq_attr "type" "condmove")
(eq_attr "mode" "SF,DF"
   "p6600_fpu_short, p6600_fpu_apu")
diff --git a/gcc/testsuite/gcc.target/mips/mips-minmax.c 
b/gcc/testsuite/gcc.target/mips/mips-minmax.c
new file mode 100644
index 000..2d234ac4b1d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips

Re: [PATCH] MIPS: Add MIN/MAX.fmt instructions support for MIPS R6

2024-03-21 Thread Xi Ruoyao
On Thu, 2024-03-21 at 10:14 +0800, Jie Mei wrote:
> diff --git a/gcc/testsuite/gcc.target/mips/mips-minmax.c 
> b/gcc/testsuite/gcc.target/mips/mips-minmax.c
> new file mode 100644
> index 000..2d234ac4b1d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/mips/mips-minmax.c
> @@ -0,0 +1,40 @@
> +/* { dg-do compile } */
> +/* { dg-options "-mhard-float -ffinite-math-only -march=mips32r6" } */

You may want to add fmin3 and fmax3 in addition to
smin3 and smax3 so it will work without -ffinite-math-only.

‘fminM3’, ‘fmaxM3’
 IEEE-conformant minimum and maximum operations.  If one operand is
 a quiet ‘NaN’, then the other operand is returned.  If both
 operands are quiet ‘NaN’, then a quiet ‘NaN’ is returned.  In the
 case when gcc supports signaling ‘NaN’ (-fsignaling-nans) an
 invalid floating point exception is raised and a quiet ‘NaN’ is
 returned.

And the MIPS 6.06 manual says:

Numbers are preferred to NaNs: if one input is a NaN, but not both, the
value of the numeric input is returned. If both are NaNs, the NaN in fs
is returned.

for MAX.fmt and MIN.fmt, so they matches fmin3 and fmax3.

> +/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */

-- 
Xi Ruoyao 
School of Aerospace Science and Technology, Xidian University