public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v3] MIPS: Add MIN/MAX.fmt instructions support for MIPS R6
@ 2024-04-28  8:57 Jie Mei
  2024-04-29  3:52 ` YunQiang Su
  0 siblings, 1 reply; 2+ messages in thread
From: Jie Mei @ 2024-04-28  8:57 UTC (permalink / raw)
  To: gcc-patches; +Cc: YunQiang Su, Xi Ruoyao

This patch adds the smin/smax RTL mode for the
min/max.fmt instructions.

Also, since the min/max.fmt instrucions applies to the
IEEE 754-2008 "minNum" and "maxNum" operations, this
patch also provides the new "fmin<mode>3" and
"fmax<mode>3" modes.

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 (UNSPEC_FMIN): New unspec.
	(UNSPEC_FMAX): Same as above.
	(type): Add fminmax.
	(smin<mode>3): Generates MIN.fmt instructions.
	(smax<mode>3): Generates MAX.fmt instructions.
	(fmin<mode>3): Generates MIN.fmt instructions.
	(fmax<mode>3): Generates MAX.fmt instructions.
	* config/mips/p6600.md (p6600_fpu_fabs): Include fminmax
	type.

gcc/testsuite/ChangeLog:

	* gcc.target/mips/mips-minmax1.c: New test for MIPS R6.
	* gcc.target/mips/mips-minmax2.c: Same as above.
---
 gcc/config/mips/i6400.md                     |  6 +++
 gcc/config/mips/mips.h                       |  2 +
 gcc/config/mips/mips.md                      | 50 +++++++++++++++++++-
 gcc/config/mips/p6600.md                     |  4 +-
 gcc/testsuite/gcc.target/mips/mips-minmax1.c | 40 ++++++++++++++++
 gcc/testsuite/gcc.target/mips/mips-minmax2.c | 36 ++++++++++++++
 6 files changed, 134 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/mips/mips-minmax1.c
 create mode 100644 gcc/testsuite/gcc.target/mips/mips-minmax2.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..26f758c90dd 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -97,6 +97,10 @@
   UNSPEC_GET_FCSR
   UNSPEC_SET_FCSR
 
+  ;; Floating-point unspecs.
+  UNSPEC_FMIN
+  UNSPEC_FMAX
+
   ;; HI/LO moves.
   UNSPEC_MFHI
   UNSPEC_MTHI
@@ -370,6 +374,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
 ;; dspmacsat    DSP MAC instructions that saturate the accumulator
 ;; accext       DSP accumulator extract instructions
@@ -387,8 +392,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 +7976,47 @@
   [(set_attr "move_type" "load")
    (set_attr "insn_count" "2")])
 
+;;
+;;  Float point MIN/MAX
+;;
+
+(define_insn "smin<mode>3"
+  [(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.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fminmax")
+   (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "smax<mode>3"
+  [(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.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fminmax")
+  (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "fmin<mode>3"
+  [(set (match_operand:SCALARF 0 "register_operand" "=f")
+	(unspec:SCALARF [(use (match_operand:SCALARF 1 "register_operand" "f"))
+			 (use (match_operand:SCALARF 2 "register_operand" "f"))]
+			UNSPEC_FMIN))]
+  "ISA_HAS_FMIN_FMAX"
+  "min.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fminmax")
+   (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "fmax<mode>3"
+  [(set (match_operand:SCALARF 0 "register_operand" "=f")
+	(unspec:SCALARF [(use (match_operand:SCALARF 1 "register_operand" "f"))
+			 (use (match_operand:SCALARF 2 "register_operand" "f"))]
+			UNSPEC_FMAX))]
+  "ISA_HAS_FMIN_FMAX"
+  "max.<fmt>\t%0,%1,%2"
+  [(set_attr "type" "fminmax")
+  (set_attr "mode" "<UNITMODE>")])
 
 ;; 2 HI loads are joined.
 (define_peephole2
diff --git a/gcc/config/mips/p6600.md b/gcc/config/mips/p6600.md
index a9e3262cc18..b6cb554939a 100644
--- a/gcc/config/mips/p6600.md
+++ b/gcc/config/mips/p6600.md
@@ -167,10 +167,10 @@
        (eq_attr "type" "fadd"))
   "p6600_fpu_long, p6600_fpu_apu")
 
-;; fabs, fneg, fcmp
+;; fabs, fneg, fcmp, fminmax
 (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-minmax1.c b/gcc/testsuite/gcc.target/mips/mips-minmax1.c
new file mode 100644
index 00000000000..087ed299d8f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips-minmax1.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-mhard-float -fno-finite-math-only -march=mips32r6" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+/* Test MIN.D.  */
+
+/* { dg-final { scan-assembler "\tmin\\.d\t" } } */
+double
+test01 (double x, double y)
+{
+  return __builtin_fmin (x, y);
+}
+
+/* Test MIN.S.  */
+
+/* { dg-final { scan-assembler "\tmin\\.s\t" } } */
+float
+test02 (float x, float y)
+{
+  return __builtin_fminf (x, y);
+}
+
+/* Test MAX.D.  */
+
+/* { dg-final { scan-assembler "\tmax\\.d\t" } } */
+double
+test03 (double x, double y)
+{
+  return __builtin_fmax (x, y);
+}
+
+/* Test MAX.S.  */
+
+/* { dg-final { scan-assembler "\tmax\\.s\t" } } */
+float
+test04 (float x, float y)
+{
+  return __builtin_fmaxf (x, y);
+}
+
diff --git a/gcc/testsuite/gcc.target/mips/mips-minmax2.c b/gcc/testsuite/gcc.target/mips/mips-minmax2.c
new file mode 100644
index 00000000000..5359043f06f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/mips-minmax2.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-mhard-float -march=mips32r6" } */
+/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
+
+extern double fmin (double, double);
+extern double fmax (double, double);
+extern float fminf (float, float);
+extern float fmaxf (float, float);
+
+/* Test MIN.D.  */
+
+/* { dg-final { scan-assembler "\tmin\\.d\t" } } */
+double test01 (double x, double y) {
+    return fmin (x, y);
+}
+
+/* Test MIN.S.  */
+
+/* { dg-final { scan-assembler "\tmin\\.s\t" } } */
+float test02 (float x, float y) {
+    return fminf (x, y);
+}
+
+/* Test MAX.D.  */
+
+/* { dg-final { scan-assembler "\tmax\\.d\t" } } */
+double test03 (double x, double y) {
+    return fmax (x, y);
+}
+
+/* Test MAX.S.  */
+
+/* { dg-final { scan-assembler "\tmax\\.s\t" } } */
+float test04 (float x, float y) {
+    return fmaxf (x, y);
+}
-- 
2.43.0

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v3] MIPS: Add MIN/MAX.fmt instructions support for MIPS R6
  2024-04-28  8:57 [PATCH v3] MIPS: Add MIN/MAX.fmt instructions support for MIPS R6 Jie Mei
@ 2024-04-29  3:52 ` YunQiang Su
  0 siblings, 0 replies; 2+ messages in thread
From: YunQiang Su @ 2024-04-29  3:52 UTC (permalink / raw)
  To: Jie Mei; +Cc: gcc-patches, Xi Ruoyao

I will apply this patch.
While we still have a problem about
```
float max(float a, float b) { return a>=b?a:b; }
```
If it is compiled with `-ffinite-math-only -fsigned-zeros -O2
-mips32r6 -mabi=32`,
`max.s` can be used.

The max.fmt/min.fmt of MIPSr6 can process +0/-0 correctly.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-04-29  3:52 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-04-28  8:57 [PATCH v3] MIPS: Add MIN/MAX.fmt instructions support for MIPS R6 Jie Mei
2024-04-29  3:52 ` YunQiang Su

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).