diff options
author | Jie Mei <jie.mei@oss.cipunited.com> | 2024-04-28 16:57:31 +0800 |
---|---|---|
committer | YunQiang Su <syq@gcc.gnu.org> | 2024-04-29 11:56:04 +0800 |
commit | 11c13111ac64a035d6c4ea6c118eff4ece7a9d9b (patch) | |
tree | ea255cf0f532fdaae78d0e6c9d4c7fb362f5729e /gcc | |
parent | deb69bfbb000339fbef316916cf6c46156c6af1b (diff) | |
download | gcc-11c13111ac64a035d6c4ea6c118eff4ece7a9d9b.zip gcc-11c13111ac64a035d6c4ea6c118eff4ece7a9d9b.tar.gz gcc-11c13111ac64a035d6c4ea6c118eff4ece7a9d9b.tar.bz2 |
MIPS: Add MIN/MAX.fmt instructions support for MIPS R6
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/mips/i6400.md | 6 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 2 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 50 | ||||
-rw-r--r-- | gcc/config/mips/p6600.md | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/mips-minmax1.c | 40 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/mips/mips-minmax2.c | 36 |
6 files changed, 134 insertions, 4 deletions
diff --git a/gcc/config/mips/i6400.md b/gcc/config/mips/i6400.md index 9f216fe..d6f691e 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 616a275..9d96596 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1262,6 +1262,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 b0fb585..26f758c 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 a9e3262..b6cb554 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 0000000..087ed29 --- /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 0000000..5359043 --- /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); +} |