Jie Mei <jie....@oss.cipunited.com> 于2024年3月25日周一 17:46写道: > > 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-minmax.c: New test for MIPS R6. > --- > gcc/config/mips/i6400.md | 6 +++ > gcc/config/mips/mips.h | 2 + > gcc/config/mips/mips.md | 50 ++++++++++++++++++++- > gcc/config/mips/p6600.md | 2 +- > gcc/testsuite/gcc.target/mips/mips-minmax.c | 40 +++++++++++++++++ > 5 files changed, 97 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..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..c502f0eb5c6 100644 > --- a/gcc/config/mips/p6600.md > +++ b/gcc/config/mips/p6600.md > @@ -170,7 +170,7 @@ > ;; fabs, fneg, fcmp
add `fminmax` here? > (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 00000000000..087ed299d8f > --- /dev/null > +++ b/gcc/testsuite/gcc.target/mips/mips-minmax.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); > +} > + With -ffinite-math-only -fno-signed-zeros, it does work with x >= y ? x : y while without `-ffinite-math-only -fno-signed-zeros`, it cannot. @Xi Ruoyao Is it expected by IEEE? And `fmaxf` is also expanded to fmax. #include <math.h> float x (float a1, float a2) { return fmaxf (a1, a2); } I think that we should add such a testcase. > -- > 2.43.0