Message ID | 20240726063626.33588-1-jie.mei@oss.cipunited.com |
---|---|
State | New |
Headers | show |
Series | MIPS: Add some floating point instructions support for MIPSr6 | expand |
Jie Mei <jie.mei@oss.cipunited.com> 于2024年7月26日周五 14:50写道: > > This patch adds some floating point instructiions from mips32r6, > for instance, MINA/MAXA.fmt, RINT.fmt, CLASS.fmt etc. > > Also add built-in functions to MIPSr6 to better handle tests > for MIPSr6. > > gcc/ChangeLog: > > * config/mips/i6400.md (i6400_fpu_minmax): Include > fclass type. > (i6400_fpu_fadd): Include frint type. > * config/mips/mips.cc (AVAIL_NON_MIPS16): Add an entry > for __builtin_mipsr6_xxx. Since libc has fmaxmag/fminmag, maybe we should use __builtin_fmaxmag. And `rint/rintf` exist in libc. > (MIPSR6_BUILTIN_PURE): Same as above. > (CODE_FOR_mipsr6_min_a_s, CODE_FOR_mipsr6_min_a_d) > (CODE_FOR_mipsr6_max_a_s, CODE_FOR_mipsr6_max_a_d) > (CODE_FOR_mipsr6_rint_s, CODE_FOR_mipsr6_rint_d) > (CODE_FOR_mipsr6_class_s, CODE_FOR_mipsr6_class_d): > New code_aliasing macros. > (mips_builtins): Add mips32r6 min_a_s, min_a_d, max_a_s, > max_a_d, rint_s, rint_d, class_s, class_d builtins. > * config/mips/mips.h (ISA_HAS_FRINT): Define a new macro. > (ISA_HAS_FCLASS): Same as above. > * config/mips/mips.md (UNSPEC_FRINT): New unspec. > (UNSPEC_FCLASS): Same as above. > (type): Add frint and fclass. > (fmin_a_<mode>): Generates MINA.fmt instructions. > (fmax_a_<mode>): Generates MAXA.fmt instructions. > (frint_<mode>): Generates RINT.fmt instructions. > (fclass_<mode>): Generates CLASS.fmt instructions. > * config/mips/p6600.md (p6600_fpu_fadd): Include > frint type. > (p6600_fpu_fabs): Incled fclass type. > > gcc/testsuite/ChangeLog: > > * gcc.target/mips/mips-class.c: New tests for MIPSr6 > * gcc.target/mips/mips-minamaxa.c: Same as above. > * gcc.target/mips/mips-rint.c: Same as above. > --- > gcc/config/mips/i6400.md | 8 +-- > gcc/config/mips/mips.cc | 28 ++++++++++ > gcc/config/mips/mips.h | 4 ++ > gcc/config/mips/mips.md | 52 ++++++++++++++++++- > gcc/config/mips/p6600.md | 8 +-- > gcc/testsuite/gcc.target/mips/mips-class.c | 17 ++++++ > gcc/testsuite/gcc.target/mips/mips-minamaxa.c | 31 +++++++++++ > gcc/testsuite/gcc.target/mips/mips-rint.c | 17 ++++++ > 8 files changed, 155 insertions(+), 10 deletions(-) > create mode 100644 gcc/testsuite/gcc.target/mips/mips-class.c > create mode 100644 gcc/testsuite/gcc.target/mips/mips-minamaxa.c > create mode 100644 gcc/testsuite/gcc.target/mips/mips-rint.c > > diff --git a/gcc/config/mips/i6400.md b/gcc/config/mips/i6400.md > index d6f691ee217..48ce980e1c2 100644 > --- a/gcc/config/mips/i6400.md > +++ b/gcc/config/mips/i6400.md > @@ -219,16 +219,16 @@ > (eq_attr "type" "fabs,fneg,fmove")) > "i6400_fpu_short, i6400_fpu_apu") > > -;; min, max > +;; min, max, fclass > (define_insn_reservation "i6400_fpu_minmax" 2 > (and (eq_attr "cpu" "i6400") > - (eq_attr "type" "fminmax")) > + (eq_attr "type" "fminmax,fclass")) > "i6400_fpu_short+i6400_fpu_logic") > > -;; fadd, fsub, fcvt > +;; fadd, fsub, fcvt, frint > (define_insn_reservation "i6400_fpu_fadd" 4 > (and (eq_attr "cpu" "i6400") > - (eq_attr "type" "fadd,fcvt")) > + (eq_attr "type" "fadd,fcvt,frint")) > "i6400_fpu_long, i6400_fpu_apu") > > ;; fmul > diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc > index 6c797b62164..14a1f23eb70 100644 > --- a/gcc/config/mips/mips.cc > +++ b/gcc/config/mips/mips.cc > @@ -15775,6 +15775,7 @@ AVAIL_NON_MIPS16 (dspr2_32, !TARGET_64BIT && TARGET_DSPR2) > AVAIL_NON_MIPS16 (loongson, TARGET_LOONGSON_MMI) > AVAIL_MIPS16E2_OR_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN) > AVAIL_NON_MIPS16 (msa, TARGET_MSA) > +AVAIL_NON_MIPS16 (r6, mips_isa_rev >= 6) > > /* Construct a mips_builtin_description from the given arguments. > > @@ -15940,6 +15941,14 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA) > "__builtin_msa_" #INSN, MIPS_BUILTIN_DIRECT_NO_TARGET, \ > FUNCTION_TYPE, mips_builtin_avail_msa, false } > > +/* Define a MIPSr6 MIPS_BUILTIN_DIRECT pure function __builtin_mipsr6_<INSN> > + for instruction CODE_FOR_mipsr6_<INSN>. FUNCTION_TYPE is a builtin_description > + field. */ > +#define MIPSR6_BUILTIN_PURE(INSN, FUNCTION_TYPE) \ > + { CODE_FOR_mipsr6_ ## INSN, MIPS_FP_COND_f, \ > + "__builtin_mipsr6_" #INSN, MIPS_BUILTIN_DIRECT, \ > + FUNCTION_TYPE, mips_builtin_avail_r6, true } > + > #define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2 > #define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3 > #define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3 > @@ -16177,6 +16186,15 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA) > #define CODE_FOR_msa_ldi_w CODE_FOR_msa_ldiv4si > #define CODE_FOR_msa_ldi_d CODE_FOR_msa_ldiv2di > > +#define CODE_FOR_mipsr6_min_a_s CODE_FOR_fmin_a_sf > +#define CODE_FOR_mipsr6_min_a_d CODE_FOR_fmin_a_df > +#define CODE_FOR_mipsr6_max_a_s CODE_FOR_fmax_a_sf > +#define CODE_FOR_mipsr6_max_a_d CODE_FOR_fmax_a_df > +#define CODE_FOR_mipsr6_rint_s CODE_FOR_frint_sf > +#define CODE_FOR_mipsr6_rint_d CODE_FOR_frint_df > +#define CODE_FOR_mipsr6_class_s CODE_FOR_fclass_sf > +#define CODE_FOR_mipsr6_class_d CODE_FOR_fclass_df > + > static const struct mips_builtin_description mips_builtins[] = { > #define MIPS_GET_FCSR 0 > DIRECT_BUILTIN (get_fcsr, MIPS_USI_FTYPE_VOID, hard_float), > @@ -16998,6 +17016,16 @@ static const struct mips_builtin_description mips_builtins[] = { > MSA_NO_TARGET_BUILTIN (ctcmsa, MIPS_VOID_FTYPE_UQI_SI), > MSA_BUILTIN_PURE (cfcmsa, MIPS_SI_FTYPE_UQI), > MSA_BUILTIN_PURE (move_v, MIPS_V16QI_FTYPE_V16QI), > + > + /* Built-in functions for MIPSr6. */ > + MIPSR6_BUILTIN_PURE (min_a_s, MIPS_SF_FTYPE_SF_SF), > + MIPSR6_BUILTIN_PURE (min_a_d, MIPS_DF_FTYPE_DF_DF), > + MIPSR6_BUILTIN_PURE (max_a_s, MIPS_SF_FTYPE_SF_SF), > + MIPSR6_BUILTIN_PURE (max_a_d, MIPS_DF_FTYPE_DF_DF), > + MIPSR6_BUILTIN_PURE (rint_s, MIPS_SF_FTYPE_SF), > + MIPSR6_BUILTIN_PURE (rint_d, MIPS_DF_FTYPE_DF), > + MIPSR6_BUILTIN_PURE (class_s, MIPS_SF_FTYPE_SF), > + MIPSR6_BUILTIN_PURE (class_d, MIPS_DF_FTYPE_DF), > }; > > /* Index I is the function declaration for mips_builtins[I], or null if the > diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h > index 84dd64d98a0..b4bb99e19b1 100644 > --- a/gcc/config/mips/mips.h > +++ b/gcc/config/mips/mips.h > @@ -1264,6 +1264,10 @@ struct mips_cpu_info { > > #define ISA_HAS_FMIN_FMAX (mips_isa_rev >= 6) > > +#define ISA_HAS_FRINT (mips_isa_rev >= 6) > + > +#define ISA_HAS_FCLASS (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 737d2566ec8..297c5141b1f 100644 > --- a/gcc/config/mips/mips.md > +++ b/gcc/config/mips/mips.md > @@ -100,6 +100,8 @@ > ;; Floating-point unspecs. > UNSPEC_FMIN > UNSPEC_FMAX > + UNSPEC_FRINT > + UNSPEC_FCLASS > > ;; HI/LO moves. > UNSPEC_MFHI > @@ -375,6 +377,8 @@ > ;; frsqrt1 floating point reciprocal square root step1 > ;; frsqrt2 floating point reciprocal square root step2 > ;; fminmax floating point min/max > +;; frint floating point round to integral > +;; fclass floating point class mask > ;; dspmac DSP MAC instructions not saturating the accumulator > ;; dspmacsat DSP MAC instructions that saturate the accumulator > ;; accext DSP accumulator extract instructions > @@ -392,8 +396,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,fminmax,dspmac,dspmacsat,accext,accmod,dspalu, > - dspalusat,multi,atomic,syncloop,nop,ghost,multimem, > + frsqrt,frsqrt1,frsqrt2,fminmax,frint,fclass,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, > @@ -8007,6 +8011,50 @@ > [(set_attr "type" "fminmax") > (set_attr "mode" "<UNITMODE>")]) > > +(define_insn "fmin_a_<mode>" > + [(set (match_operand:SCALARF 0 "register_operand" "=f") > + (if_then_else > + (lt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f")) > + (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f"))) > + (match_dup 1) > + (match_dup 2)))] > + "ISA_HAS_FMIN_FMAX" > + "mina.<fmt>\t%0,%1,%2" > + [(set_attr "type" "fminmax") > + (set_attr "mode" "<UNITMODE>")]) > + > +(define_insn "fmax_a_<mode>" > + [(set (match_operand:SCALARF 0 "register_operand" "=f") > + (if_then_else > + (gt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f")) > + (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f"))) > + (match_dup 1) > + (match_dup 2)))] > + "ISA_HAS_FMIN_FMAX" > + "maxa.<fmt>\t%0,%1,%2" > + [(set_attr "type" "fminmax") > + (set_attr "mode" "<UNITMODE>")]) > + > +;;Float point round to integral > +(define_insn "frint_<mode>" > + [(set (match_operand:SCALARF 0 "register_operand" "=f") > + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")] > + UNSPEC_FRINT))] > + "ISA_HAS_FRINT" > + "rint.<fmt>\t%0,%1" > + [(set_attr "type" "frint") > + (set_attr "mode" "<UNITMODE>")]) > + > +;;Float point class mask > +(define_insn "fclass_<mode>" > + [(set (match_operand:SCALARF 0 "register_operand" "=f") > + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")] > + UNSPEC_FCLASS))] > + "ISA_HAS_FCLASS" > + "class.<fmt>\t%0,%1" > + [(set_attr "type" "fclass") > + (set_attr "mode" "<UNITMODE>")]) > + > ;; 2 HI loads are joined. > (define_peephole2 > [(set (match_operand:SI 0 "register_operand") > diff --git a/gcc/config/mips/p6600.md b/gcc/config/mips/p6600.md > index b6cb554939a..d541e98fdec 100644 > --- a/gcc/config/mips/p6600.md > +++ b/gcc/config/mips/p6600.md > @@ -161,16 +161,16 @@ > ;; FPU pipe > ;; > > -;; fadd, fsub > +;; fadd, fsub, frint > (define_insn_reservation "p6600_fpu_fadd" 4 > (and (eq_attr "cpu" "p6600") > - (eq_attr "type" "fadd")) > + (eq_attr "type" "fadd,frint")) > "p6600_fpu_long, p6600_fpu_apu") > > -;; fabs, fneg, fcmp, fminmax > +;; fabs, fneg, fcmp, fminmax, fclass > (define_insn_reservation "p6600_fpu_fabs" 2 > (and (eq_attr "cpu" "p6600") > - (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax") > + (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax,fclass") > (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-class.c b/gcc/testsuite/gcc.target/mips/mips-class.c > new file mode 100644 > index 00000000000..e71a853fb8c > --- /dev/null > +++ b/gcc/testsuite/gcc.target/mips/mips-class.c > @@ -0,0 +1,17 @@ > +/* { dg-do compile } */ > +/* { dg-options "-mhard-float -march=mips32r6" } */ > + > +NOMIPS16 float > +test01 (float a) > +{ > + return __builtin_mipsr6_class_s (a); > +} > + > +NOMIPS16 double > +test02 (double a) > +{ > + return __builtin_mipsr6_class_d (a); > +} > + > +/* { dg-final { scan-assembler "class\\.s" } } */ > +/* { dg-final { scan-assembler "class\\.d" } } */ > diff --git a/gcc/testsuite/gcc.target/mips/mips-minamaxa.c b/gcc/testsuite/gcc.target/mips/mips-minamaxa.c > new file mode 100644 > index 00000000000..d41d6078779 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/mips/mips-minamaxa.c > @@ -0,0 +1,31 @@ > +/* { dg-do compile } */ > +/* { dg-options "-mhard-float -march=mips32r6" } */ > + > +NOMIPS16 float > +test01 (float a, float b) > +{ > + return __builtin_mipsr6_min_a_s (a, b); > +} > + > +NOMIPS16 double > +test02 (double a, double b) > +{ > + return __builtin_mipsr6_min_a_d (a, b); > +} > + > +NOMIPS16 float > +test03 (float a, float b) > +{ > + return __builtin_mipsr6_max_a_s (a, b); > +} > + > +NOMIPS16 double > +test04 (double a, double b) > +{ > + return __builtin_mipsr6_max_a_d (a, b); > +} > + > +/* { dg-final { scan-assembler "mina\\.s" } } */ > +/* { dg-final { scan-assembler "mina\\.d" } } */ > +/* { dg-final { scan-assembler "maxa\\.s" } } */ > +/* { dg-final { scan-assembler "maxa\\.d" } } */ > diff --git a/gcc/testsuite/gcc.target/mips/mips-rint.c b/gcc/testsuite/gcc.target/mips/mips-rint.c > new file mode 100644 > index 00000000000..a964b8c4267 > --- /dev/null > +++ b/gcc/testsuite/gcc.target/mips/mips-rint.c > @@ -0,0 +1,17 @@ > +/* { dg-do compile } */ > +/* { dg-options "-mhard-float -march=mips32r6" } */ > + > +NOMIPS16 float > +test01 (float a) > +{ > + return __builtin_mipsr6_rint_s (a); > +} > + > +NOMIPS16 double > +test02 (double a) > +{ > + return __builtin_mipsr6_rint_d (a); > +} > + > +/* { dg-final { scan-assembler "rint\\.s" } } */ > +/* { dg-final { scan-assembler "rint\\.d" } } */ > -- > 2.41.0
在 2024/9/3 08:30, YunQiang Su 写道: > Jie Mei <jie.mei@oss.cipunited.com> 于2024年7月26日周五 14:50写道: >> >> This patch adds some floating point instructiions from mips32r6, >> for instance, MINA/MAXA.fmt, RINT.fmt, CLASS.fmt etc. >> >> Also add built-in functions to MIPSr6 to better handle tests >> for MIPSr6. >> >> gcc/ChangeLog: >> >> * config/mips/i6400.md (i6400_fpu_minmax): Include >> fclass type. >> (i6400_fpu_fadd): Include frint type. >> * config/mips/mips.cc (AVAIL_NON_MIPS16): Add an entry >> for __builtin_mipsr6_xxx. > > Since libc has fmaxmag/fminmag, maybe we should use __builtin_fmaxmag. > And `rint/rintf` exist in libc. > > There is no such built-in function `__builtin_fmaxmag` in gcc, as the only file that mentioned `fmaxmag/fminmag` in the code tree `fortan/trans-intrinsic.cc` stated: > IEEE_MIN_NUM_MAG and IEEE_MAX_NUM_MAG translate to C > fminmag() and fmaxmag(), which do not exist as built-ins. As for the function `__builtin_rint`, although it exists, however, after defining the instruction in `mips.md`, GCC still won't generate `RINT.fmt` instruction for MIPS, it generates following code instead: > lui $28,%hi(__gnu_local_gp) > addiu $28,$28,%lo(__gnu_local_gp) > lw $25,%call16(rint)($28) > .reloc 1f,R_MIPS_JALR,rint This patch tries to fix said problem with an extra built-in function like the MSA solution for `FRINT.fmt`. >> (MIPSR6_BUILTIN_PURE): Same as above. >> (CODE_FOR_mipsr6_min_a_s, CODE_FOR_mipsr6_min_a_d) >> (CODE_FOR_mipsr6_max_a_s, CODE_FOR_mipsr6_max_a_d) >> (CODE_FOR_mipsr6_rint_s, CODE_FOR_mipsr6_rint_d) >> (CODE_FOR_mipsr6_class_s, CODE_FOR_mipsr6_class_d): >> New code_aliasing macros. >> (mips_builtins): Add mips32r6 min_a_s, min_a_d, max_a_s, >> max_a_d, rint_s, rint_d, class_s, class_d builtins. >> * config/mips/mips.h (ISA_HAS_FRINT): Define a new macro. >> (ISA_HAS_FCLASS): Same as above. >> * config/mips/mips.md (UNSPEC_FRINT): New unspec. >> (UNSPEC_FCLASS): Same as above. >> (type): Add frint and fclass. >> (fmin_a_<mode>): Generates MINA.fmt instructions. >> (fmax_a_<mode>): Generates MAXA.fmt instructions. >> (frint_<mode>): Generates RINT.fmt instructions. >> (fclass_<mode>): Generates CLASS.fmt instructions. >> * config/mips/p6600.md (p6600_fpu_fadd): Include >> frint type. >> (p6600_fpu_fabs): Incled fclass type. >> >> gcc/testsuite/ChangeLog: >> >> * gcc.target/mips/mips-class.c: New tests for MIPSr6 >> * gcc.target/mips/mips-minamaxa.c: Same as above. >> * gcc.target/mips/mips-rint.c: Same as above. >> --- >> gcc/config/mips/i6400.md | 8 +-- >> gcc/config/mips/mips.cc | 28 ++++++++++ >> gcc/config/mips/mips.h | 4 ++ >> gcc/config/mips/mips.md | 52 ++++++++++++++++++- >> gcc/config/mips/p6600.md | 8 +-- >> gcc/testsuite/gcc.target/mips/mips-class.c | 17 ++++++ >> gcc/testsuite/gcc.target/mips/mips-minamaxa.c | 31 +++++++++++ >> gcc/testsuite/gcc.target/mips/mips-rint.c | 17 ++++++ >> 8 files changed, 155 insertions(+), 10 deletions(-) >> create mode 100644 gcc/testsuite/gcc.target/mips/mips-class.c >> create mode 100644 gcc/testsuite/gcc.target/mips/mips-minamaxa.c >> create mode 100644 gcc/testsuite/gcc.target/mips/mips-rint.c >> >> diff --git a/gcc/config/mips/i6400.md b/gcc/config/mips/i6400.md >> index d6f691ee217..48ce980e1c2 100644 >> --- a/gcc/config/mips/i6400.md >> +++ b/gcc/config/mips/i6400.md >> @@ -219,16 +219,16 @@ >> (eq_attr "type" "fabs,fneg,fmove")) >> "i6400_fpu_short, i6400_fpu_apu") >> >> -;; min, max >> +;; min, max, fclass >> (define_insn_reservation "i6400_fpu_minmax" 2 >> (and (eq_attr "cpu" "i6400") >> - (eq_attr "type" "fminmax")) >> + (eq_attr "type" "fminmax,fclass")) >> "i6400_fpu_short+i6400_fpu_logic") >> >> -;; fadd, fsub, fcvt >> +;; fadd, fsub, fcvt, frint >> (define_insn_reservation "i6400_fpu_fadd" 4 >> (and (eq_attr "cpu" "i6400") >> - (eq_attr "type" "fadd,fcvt")) >> + (eq_attr "type" "fadd,fcvt,frint")) >> "i6400_fpu_long, i6400_fpu_apu") >> >> ;; fmul >> diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc >> index 6c797b62164..14a1f23eb70 100644 >> --- a/gcc/config/mips/mips.cc >> +++ b/gcc/config/mips/mips.cc >> @@ -15775,6 +15775,7 @@ AVAIL_NON_MIPS16 (dspr2_32, !TARGET_64BIT && TARGET_DSPR2) >> AVAIL_NON_MIPS16 (loongson, TARGET_LOONGSON_MMI) >> AVAIL_MIPS16E2_OR_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN) >> AVAIL_NON_MIPS16 (msa, TARGET_MSA) >> +AVAIL_NON_MIPS16 (r6, mips_isa_rev >= 6) >> >> /* Construct a mips_builtin_description from the given arguments. >> >> @@ -15940,6 +15941,14 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA) >> "__builtin_msa_" #INSN, MIPS_BUILTIN_DIRECT_NO_TARGET, \ >> FUNCTION_TYPE, mips_builtin_avail_msa, false } >> >> +/* Define a MIPSr6 MIPS_BUILTIN_DIRECT pure function __builtin_mipsr6_<INSN> >> + for instruction CODE_FOR_mipsr6_<INSN>. FUNCTION_TYPE is a builtin_description >> + field. */ >> +#define MIPSR6_BUILTIN_PURE(INSN, FUNCTION_TYPE) \ >> + { CODE_FOR_mipsr6_ ## INSN, MIPS_FP_COND_f, \ >> + "__builtin_mipsr6_" #INSN, MIPS_BUILTIN_DIRECT, \ >> + FUNCTION_TYPE, mips_builtin_avail_r6, true } >> + >> #define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2 >> #define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3 >> #define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3 >> @@ -16177,6 +16186,15 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA) >> #define CODE_FOR_msa_ldi_w CODE_FOR_msa_ldiv4si >> #define CODE_FOR_msa_ldi_d CODE_FOR_msa_ldiv2di >> >> +#define CODE_FOR_mipsr6_min_a_s CODE_FOR_fmin_a_sf >> +#define CODE_FOR_mipsr6_min_a_d CODE_FOR_fmin_a_df >> +#define CODE_FOR_mipsr6_max_a_s CODE_FOR_fmax_a_sf >> +#define CODE_FOR_mipsr6_max_a_d CODE_FOR_fmax_a_df >> +#define CODE_FOR_mipsr6_rint_s CODE_FOR_frint_sf >> +#define CODE_FOR_mipsr6_rint_d CODE_FOR_frint_df >> +#define CODE_FOR_mipsr6_class_s CODE_FOR_fclass_sf >> +#define CODE_FOR_mipsr6_class_d CODE_FOR_fclass_df >> + >> static const struct mips_builtin_description mips_builtins[] = { >> #define MIPS_GET_FCSR 0 >> DIRECT_BUILTIN (get_fcsr, MIPS_USI_FTYPE_VOID, hard_float), >> @@ -16998,6 +17016,16 @@ static const struct mips_builtin_description mips_builtins[] = { >> MSA_NO_TARGET_BUILTIN (ctcmsa, MIPS_VOID_FTYPE_UQI_SI), >> MSA_BUILTIN_PURE (cfcmsa, MIPS_SI_FTYPE_UQI), >> MSA_BUILTIN_PURE (move_v, MIPS_V16QI_FTYPE_V16QI), >> + >> + /* Built-in functions for MIPSr6. */ >> + MIPSR6_BUILTIN_PURE (min_a_s, MIPS_SF_FTYPE_SF_SF), >> + MIPSR6_BUILTIN_PURE (min_a_d, MIPS_DF_FTYPE_DF_DF), >> + MIPSR6_BUILTIN_PURE (max_a_s, MIPS_SF_FTYPE_SF_SF), >> + MIPSR6_BUILTIN_PURE (max_a_d, MIPS_DF_FTYPE_DF_DF), >> + MIPSR6_BUILTIN_PURE (rint_s, MIPS_SF_FTYPE_SF), >> + MIPSR6_BUILTIN_PURE (rint_d, MIPS_DF_FTYPE_DF), >> + MIPSR6_BUILTIN_PURE (class_s, MIPS_SF_FTYPE_SF), >> + MIPSR6_BUILTIN_PURE (class_d, MIPS_DF_FTYPE_DF), >> }; >> >> /* Index I is the function declaration for mips_builtins[I], or null if the >> diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h >> index 84dd64d98a0..b4bb99e19b1 100644 >> --- a/gcc/config/mips/mips.h >> +++ b/gcc/config/mips/mips.h >> @@ -1264,6 +1264,10 @@ struct mips_cpu_info { >> >> #define ISA_HAS_FMIN_FMAX (mips_isa_rev >= 6) >> >> +#define ISA_HAS_FRINT (mips_isa_rev >= 6) >> + >> +#define ISA_HAS_FCLASS (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 737d2566ec8..297c5141b1f 100644 >> --- a/gcc/config/mips/mips.md >> +++ b/gcc/config/mips/mips.md >> @@ -100,6 +100,8 @@ >> ;; Floating-point unspecs. >> UNSPEC_FMIN >> UNSPEC_FMAX >> + UNSPEC_FRINT >> + UNSPEC_FCLASS >> >> ;; HI/LO moves. >> UNSPEC_MFHI >> @@ -375,6 +377,8 @@ >> ;; frsqrt1 floating point reciprocal square root step1 >> ;; frsqrt2 floating point reciprocal square root step2 >> ;; fminmax floating point min/max >> +;; frint floating point round to integral >> +;; fclass floating point class mask >> ;; dspmac DSP MAC instructions not saturating the accumulator >> ;; dspmacsat DSP MAC instructions that saturate the accumulator >> ;; accext DSP accumulator extract instructions >> @@ -392,8 +396,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,fminmax,dspmac,dspmacsat,accext,accmod,dspalu, >> - dspalusat,multi,atomic,syncloop,nop,ghost,multimem, >> + frsqrt,frsqrt1,frsqrt2,fminmax,frint,fclass,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, >> @@ -8007,6 +8011,50 @@ >> [(set_attr "type" "fminmax") >> (set_attr "mode" "<UNITMODE>")]) >> >> +(define_insn "fmin_a_<mode>" >> + [(set (match_operand:SCALARF 0 "register_operand" "=f") >> + (if_then_else >> + (lt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f")) >> + (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f"))) >> + (match_dup 1) >> + (match_dup 2)))] >> + "ISA_HAS_FMIN_FMAX" >> + "mina.<fmt>\t%0,%1,%2" >> + [(set_attr "type" "fminmax") >> + (set_attr "mode" "<UNITMODE>")]) >> + >> +(define_insn "fmax_a_<mode>" >> + [(set (match_operand:SCALARF 0 "register_operand" "=f") >> + (if_then_else >> + (gt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f")) >> + (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f"))) >> + (match_dup 1) >> + (match_dup 2)))] >> + "ISA_HAS_FMIN_FMAX" >> + "maxa.<fmt>\t%0,%1,%2" >> + [(set_attr "type" "fminmax") >> + (set_attr "mode" "<UNITMODE>")]) >> + >> +;;Float point round to integral >> +(define_insn "frint_<mode>" >> + [(set (match_operand:SCALARF 0 "register_operand" "=f") >> + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")] >> + UNSPEC_FRINT))] >> + "ISA_HAS_FRINT" >> + "rint.<fmt>\t%0,%1" >> + [(set_attr "type" "frint") >> + (set_attr "mode" "<UNITMODE>")]) >> + >> +;;Float point class mask >> +(define_insn "fclass_<mode>" >> + [(set (match_operand:SCALARF 0 "register_operand" "=f") >> + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")] >> + UNSPEC_FCLASS))] >> + "ISA_HAS_FCLASS" >> + "class.<fmt>\t%0,%1" >> + [(set_attr "type" "fclass") >> + (set_attr "mode" "<UNITMODE>")]) >> + >> ;; 2 HI loads are joined. >> (define_peephole2 >> [(set (match_operand:SI 0 "register_operand") >> diff --git a/gcc/config/mips/p6600.md b/gcc/config/mips/p6600.md >> index b6cb554939a..d541e98fdec 100644 >> --- a/gcc/config/mips/p6600.md >> +++ b/gcc/config/mips/p6600.md >> @@ -161,16 +161,16 @@ >> ;; FPU pipe >> ;; >> >> -;; fadd, fsub >> +;; fadd, fsub, frint >> (define_insn_reservation "p6600_fpu_fadd" 4 >> (and (eq_attr "cpu" "p6600") >> - (eq_attr "type" "fadd")) >> + (eq_attr "type" "fadd,frint")) >> "p6600_fpu_long, p6600_fpu_apu") >> >> -;; fabs, fneg, fcmp, fminmax >> +;; fabs, fneg, fcmp, fminmax, fclass >> (define_insn_reservation "p6600_fpu_fabs" 2 >> (and (eq_attr "cpu" "p6600") >> - (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax") >> + (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax,fclass") >> (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-class.c b/gcc/testsuite/gcc.target/mips/mips-class.c >> new file mode 100644 >> index 00000000000..e71a853fb8c >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/mips/mips-class.c >> @@ -0,0 +1,17 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-mhard-float -march=mips32r6" } */ >> + >> +NOMIPS16 float >> +test01 (float a) >> +{ >> + return __builtin_mipsr6_class_s (a); >> +} >> + >> +NOMIPS16 double >> +test02 (double a) >> +{ >> + return __builtin_mipsr6_class_d (a); >> +} >> + >> +/* { dg-final { scan-assembler "class\\.s" } } */ >> +/* { dg-final { scan-assembler "class\\.d" } } */ >> diff --git a/gcc/testsuite/gcc.target/mips/mips-minamaxa.c b/gcc/testsuite/gcc.target/mips/mips-minamaxa.c >> new file mode 100644 >> index 00000000000..d41d6078779 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/mips/mips-minamaxa.c >> @@ -0,0 +1,31 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-mhard-float -march=mips32r6" } */ >> + >> +NOMIPS16 float >> +test01 (float a, float b) >> +{ >> + return __builtin_mipsr6_min_a_s (a, b); >> +} >> + >> +NOMIPS16 double >> +test02 (double a, double b) >> +{ >> + return __builtin_mipsr6_min_a_d (a, b); >> +} >> + >> +NOMIPS16 float >> +test03 (float a, float b) >> +{ >> + return __builtin_mipsr6_max_a_s (a, b); >> +} >> + >> +NOMIPS16 double >> +test04 (double a, double b) >> +{ >> + return __builtin_mipsr6_max_a_d (a, b); >> +} >> + >> +/* { dg-final { scan-assembler "mina\\.s" } } */ >> +/* { dg-final { scan-assembler "mina\\.d" } } */ >> +/* { dg-final { scan-assembler "maxa\\.s" } } */ >> +/* { dg-final { scan-assembler "maxa\\.d" } } */ >> diff --git a/gcc/testsuite/gcc.target/mips/mips-rint.c b/gcc/testsuite/gcc.target/mips/mips-rint.c >> new file mode 100644 >> index 00000000000..a964b8c4267 >> --- /dev/null >> +++ b/gcc/testsuite/gcc.target/mips/mips-rint.c >> @@ -0,0 +1,17 @@ >> +/* { dg-do compile } */ >> +/* { dg-options "-mhard-float -march=mips32r6" } */ >> + >> +NOMIPS16 float >> +test01 (float a) >> +{ >> + return __builtin_mipsr6_rint_s (a); >> +} >> + >> +NOMIPS16 double >> +test02 (double a) >> +{ >> + return __builtin_mipsr6_rint_d (a); >> +} >> + >> +/* { dg-final { scan-assembler "rint\\.s" } } */ >> +/* { dg-final { scan-assembler "rint\\.d" } } */ >> -- >> 2.41.0
On Tue, 2024-09-10 at 16:50 +0800, 梅杰 wrote: > As for the function `__builtin_rint`, although it exists, however, after > defining the instruction in `mips.md`, GCC still won't generate `RINT.fmt` > instruction for MIPS, it generates following code instead: > > > lui $28,%hi(__gnu_local_gp) > > addiu $28,$28,%lo(__gnu_local_gp) > > lw $25,%call16(rint)($28) > > .reloc 1f,R_MIPS_JALR,rint Why? Whis this: diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index f147667d63a..0c1ef77a816 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -100,6 +100,7 @@ (define_c_enum "unspec" [ ;; Floating-point unspecs. UNSPEC_FMIN UNSPEC_FMAX + UNSPEC_RINT ;; HI/LO moves. UNSPEC_MFHI @@ -8025,6 +8026,14 @@ (define_peephole2 (any_extend:SI (match_dup 3)))])] "") +(define_insn "rint<mode>2" + [(set (match_operand:SCALARF 0 "register_operand" "=f") + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" " f")] + UNSPEC_RINT))] + "mips_isa_rev >= 6" + "rint.<fmt>\t%0,%1") + + ;; Synchronization instructions. it works for me: $ cat t.c double test(double x) { return __builtin_rint(x); } $ ./gcc/cc1 t.c -nostdinc -O2 -mips64r6 -mexplicit-relocs -mabi=64 $ grep rint t.s rint.d $f0,$f12
在 2024/9/10 17:30, Xi Ruoyao 写道: > On Tue, 2024-09-10 at 16:50 +0800, 梅杰 wrote: >> As for the function `__builtin_rint`, although it exists, however, after >> defining the instruction in `mips.md`, GCC still won't generate `RINT.fmt` >> instruction for MIPS, it generates following code instead: >> >>> lui $28,%hi(__gnu_local_gp) >>> addiu $28,$28,%lo(__gnu_local_gp) >>> lw $25,%call16(rint)($28) >>> .reloc 1f,R_MIPS_JALR,rint > > Why? > > Whis this: > > diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md > index f147667d63a..0c1ef77a816 100644 > --- a/gcc/config/mips/mips.md > +++ b/gcc/config/mips/mips.md > @@ -100,6 +100,7 @@ (define_c_enum "unspec" [ > ;; Floating-point unspecs. > UNSPEC_FMIN > UNSPEC_FMAX > + UNSPEC_RINT > > ;; HI/LO moves. > UNSPEC_MFHI > @@ -8025,6 +8026,14 @@ (define_peephole2 > (any_extend:SI (match_dup 3)))])] > "") > > +(define_insn "rint<mode>2" > + [(set (match_operand:SCALARF 0 "register_operand" "=f") > + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" " f")] > + UNSPEC_RINT))] > + "mips_isa_rev >= 6" > + "rint.<fmt>\t%0,%1") > + > + > > > ;; Synchronization instructions. > > it works for me: Yes, you are right! I have applied this patch into my current code and I can confirm that by changing `frint_<mode>` to `rint<mode>2` works. GCC will generate `RINT.fmt` instruction correctly with built-in funtion `__builtin_rint` after applying the patch. Maybe you can write a patch for `RINT.fmt`? I will update this patch and remove code related to `RINT.fmt`, if you could do that. At the same time, could anyone review the rest of this patch? Thanks!
On Wed, 2024-09-11 at 16:17 +0800, 梅杰 wrote: > 在 2024/9/10 17:30, Xi Ruoyao 写道: > > On Tue, 2024-09-10 at 16:50 +0800, 梅杰 wrote: > > > As for the function `__builtin_rint`, although it exists, however, after > > > defining the instruction in `mips.md`, GCC still won't generate `RINT.fmt` > > > instruction for MIPS, it generates following code instead: > > > > > > > lui $28,%hi(__gnu_local_gp) > > > > addiu $28,$28,%lo(__gnu_local_gp) > > > > lw $25,%call16(rint)($28) > > > > .reloc 1f,R_MIPS_JALR,rint > > > > Why? > > > > Whis this: > > > > diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md > > index f147667d63a..0c1ef77a816 100644 > > --- a/gcc/config/mips/mips.md > > +++ b/gcc/config/mips/mips.md > > @@ -100,6 +100,7 @@ (define_c_enum "unspec" [ > > ;; Floating-point unspecs. > > UNSPEC_FMIN > > UNSPEC_FMAX > > + UNSPEC_RINT > > > > ;; HI/LO moves. > > UNSPEC_MFHI > > @@ -8025,6 +8026,14 @@ (define_peephole2 > > (any_extend:SI (match_dup 3)))])] > > "") > > > > +(define_insn "rint<mode>2" > > + [(set (match_operand:SCALARF 0 "register_operand" "=f") > > + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" " f")] > > + UNSPEC_RINT))] > > + "mips_isa_rev >= 6" > > + "rint.<fmt>\t%0,%1") > > + > > + > > > > > > ;; Synchronization instructions. > > > > it works for me: > > Yes, you are right! > > I have applied this patch into my current code and I can confirm that > by changing `frint_<mode>` to `rint<mode>2` works. GCC will generate > `RINT.fmt` instruction correctly with built-in funtion `__builtin_rint` > after applying the patch. > > Maybe you can write a patch for `RINT.fmt`? I will update this patch and > remove code related to `RINT.fmt`, if you could do that. At the same time, > could anyone review the rest of this patch? Thanks! You can use my code in your v2 patch w/o attribution (or with a Co- authored-by if you'd like to attribute anyway). I don't have an r6 hardware and I don't like testing my change solely based on an emulator, so I'd not send a patch myself.
diff --git a/gcc/config/mips/i6400.md b/gcc/config/mips/i6400.md index d6f691ee217..48ce980e1c2 100644 --- a/gcc/config/mips/i6400.md +++ b/gcc/config/mips/i6400.md @@ -219,16 +219,16 @@ (eq_attr "type" "fabs,fneg,fmove")) "i6400_fpu_short, i6400_fpu_apu") -;; min, max +;; min, max, fclass (define_insn_reservation "i6400_fpu_minmax" 2 (and (eq_attr "cpu" "i6400") - (eq_attr "type" "fminmax")) + (eq_attr "type" "fminmax,fclass")) "i6400_fpu_short+i6400_fpu_logic") -;; fadd, fsub, fcvt +;; fadd, fsub, fcvt, frint (define_insn_reservation "i6400_fpu_fadd" 4 (and (eq_attr "cpu" "i6400") - (eq_attr "type" "fadd,fcvt")) + (eq_attr "type" "fadd,fcvt,frint")) "i6400_fpu_long, i6400_fpu_apu") ;; fmul diff --git a/gcc/config/mips/mips.cc b/gcc/config/mips/mips.cc index 6c797b62164..14a1f23eb70 100644 --- a/gcc/config/mips/mips.cc +++ b/gcc/config/mips/mips.cc @@ -15775,6 +15775,7 @@ AVAIL_NON_MIPS16 (dspr2_32, !TARGET_64BIT && TARGET_DSPR2) AVAIL_NON_MIPS16 (loongson, TARGET_LOONGSON_MMI) AVAIL_MIPS16E2_OR_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN) AVAIL_NON_MIPS16 (msa, TARGET_MSA) +AVAIL_NON_MIPS16 (r6, mips_isa_rev >= 6) /* Construct a mips_builtin_description from the given arguments. @@ -15940,6 +15941,14 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA) "__builtin_msa_" #INSN, MIPS_BUILTIN_DIRECT_NO_TARGET, \ FUNCTION_TYPE, mips_builtin_avail_msa, false } +/* Define a MIPSr6 MIPS_BUILTIN_DIRECT pure function __builtin_mipsr6_<INSN> + for instruction CODE_FOR_mipsr6_<INSN>. FUNCTION_TYPE is a builtin_description + field. */ +#define MIPSR6_BUILTIN_PURE(INSN, FUNCTION_TYPE) \ + { CODE_FOR_mipsr6_ ## INSN, MIPS_FP_COND_f, \ + "__builtin_mipsr6_" #INSN, MIPS_BUILTIN_DIRECT, \ + FUNCTION_TYPE, mips_builtin_avail_r6, true } + #define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2 #define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3 #define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3 @@ -16177,6 +16186,15 @@ AVAIL_NON_MIPS16 (msa, TARGET_MSA) #define CODE_FOR_msa_ldi_w CODE_FOR_msa_ldiv4si #define CODE_FOR_msa_ldi_d CODE_FOR_msa_ldiv2di +#define CODE_FOR_mipsr6_min_a_s CODE_FOR_fmin_a_sf +#define CODE_FOR_mipsr6_min_a_d CODE_FOR_fmin_a_df +#define CODE_FOR_mipsr6_max_a_s CODE_FOR_fmax_a_sf +#define CODE_FOR_mipsr6_max_a_d CODE_FOR_fmax_a_df +#define CODE_FOR_mipsr6_rint_s CODE_FOR_frint_sf +#define CODE_FOR_mipsr6_rint_d CODE_FOR_frint_df +#define CODE_FOR_mipsr6_class_s CODE_FOR_fclass_sf +#define CODE_FOR_mipsr6_class_d CODE_FOR_fclass_df + static const struct mips_builtin_description mips_builtins[] = { #define MIPS_GET_FCSR 0 DIRECT_BUILTIN (get_fcsr, MIPS_USI_FTYPE_VOID, hard_float), @@ -16998,6 +17016,16 @@ static const struct mips_builtin_description mips_builtins[] = { MSA_NO_TARGET_BUILTIN (ctcmsa, MIPS_VOID_FTYPE_UQI_SI), MSA_BUILTIN_PURE (cfcmsa, MIPS_SI_FTYPE_UQI), MSA_BUILTIN_PURE (move_v, MIPS_V16QI_FTYPE_V16QI), + + /* Built-in functions for MIPSr6. */ + MIPSR6_BUILTIN_PURE (min_a_s, MIPS_SF_FTYPE_SF_SF), + MIPSR6_BUILTIN_PURE (min_a_d, MIPS_DF_FTYPE_DF_DF), + MIPSR6_BUILTIN_PURE (max_a_s, MIPS_SF_FTYPE_SF_SF), + MIPSR6_BUILTIN_PURE (max_a_d, MIPS_DF_FTYPE_DF_DF), + MIPSR6_BUILTIN_PURE (rint_s, MIPS_SF_FTYPE_SF), + MIPSR6_BUILTIN_PURE (rint_d, MIPS_DF_FTYPE_DF), + MIPSR6_BUILTIN_PURE (class_s, MIPS_SF_FTYPE_SF), + MIPSR6_BUILTIN_PURE (class_d, MIPS_DF_FTYPE_DF), }; /* Index I is the function declaration for mips_builtins[I], or null if the diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index 84dd64d98a0..b4bb99e19b1 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -1264,6 +1264,10 @@ struct mips_cpu_info { #define ISA_HAS_FMIN_FMAX (mips_isa_rev >= 6) +#define ISA_HAS_FRINT (mips_isa_rev >= 6) + +#define ISA_HAS_FCLASS (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 737d2566ec8..297c5141b1f 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -100,6 +100,8 @@ ;; Floating-point unspecs. UNSPEC_FMIN UNSPEC_FMAX + UNSPEC_FRINT + UNSPEC_FCLASS ;; HI/LO moves. UNSPEC_MFHI @@ -375,6 +377,8 @@ ;; frsqrt1 floating point reciprocal square root step1 ;; frsqrt2 floating point reciprocal square root step2 ;; fminmax floating point min/max +;; frint floating point round to integral +;; fclass floating point class mask ;; dspmac DSP MAC instructions not saturating the accumulator ;; dspmacsat DSP MAC instructions that saturate the accumulator ;; accext DSP accumulator extract instructions @@ -392,8 +396,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,fminmax,dspmac,dspmacsat,accext,accmod,dspalu, - dspalusat,multi,atomic,syncloop,nop,ghost,multimem, + frsqrt,frsqrt1,frsqrt2,fminmax,frint,fclass,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, @@ -8007,6 +8011,50 @@ [(set_attr "type" "fminmax") (set_attr "mode" "<UNITMODE>")]) +(define_insn "fmin_a_<mode>" + [(set (match_operand:SCALARF 0 "register_operand" "=f") + (if_then_else + (lt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f")) + (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f"))) + (match_dup 1) + (match_dup 2)))] + "ISA_HAS_FMIN_FMAX" + "mina.<fmt>\t%0,%1,%2" + [(set_attr "type" "fminmax") + (set_attr "mode" "<UNITMODE>")]) + +(define_insn "fmax_a_<mode>" + [(set (match_operand:SCALARF 0 "register_operand" "=f") + (if_then_else + (gt (abs:SCALARF (match_operand:SCALARF 1 "register_operand" "f")) + (abs:SCALARF (match_operand:SCALARF 2 "register_operand" "f"))) + (match_dup 1) + (match_dup 2)))] + "ISA_HAS_FMIN_FMAX" + "maxa.<fmt>\t%0,%1,%2" + [(set_attr "type" "fminmax") + (set_attr "mode" "<UNITMODE>")]) + +;;Float point round to integral +(define_insn "frint_<mode>" + [(set (match_operand:SCALARF 0 "register_operand" "=f") + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")] + UNSPEC_FRINT))] + "ISA_HAS_FRINT" + "rint.<fmt>\t%0,%1" + [(set_attr "type" "frint") + (set_attr "mode" "<UNITMODE>")]) + +;;Float point class mask +(define_insn "fclass_<mode>" + [(set (match_operand:SCALARF 0 "register_operand" "=f") + (unspec:SCALARF [(match_operand:SCALARF 1 "register_operand" "f")] + UNSPEC_FCLASS))] + "ISA_HAS_FCLASS" + "class.<fmt>\t%0,%1" + [(set_attr "type" "fclass") + (set_attr "mode" "<UNITMODE>")]) + ;; 2 HI loads are joined. (define_peephole2 [(set (match_operand:SI 0 "register_operand") diff --git a/gcc/config/mips/p6600.md b/gcc/config/mips/p6600.md index b6cb554939a..d541e98fdec 100644 --- a/gcc/config/mips/p6600.md +++ b/gcc/config/mips/p6600.md @@ -161,16 +161,16 @@ ;; FPU pipe ;; -;; fadd, fsub +;; fadd, fsub, frint (define_insn_reservation "p6600_fpu_fadd" 4 (and (eq_attr "cpu" "p6600") - (eq_attr "type" "fadd")) + (eq_attr "type" "fadd,frint")) "p6600_fpu_long, p6600_fpu_apu") -;; fabs, fneg, fcmp, fminmax +;; fabs, fneg, fcmp, fminmax, fclass (define_insn_reservation "p6600_fpu_fabs" 2 (and (eq_attr "cpu" "p6600") - (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax") + (ior (eq_attr "type" "fabs,fneg,fcmp,fmove,fminmax,fclass") (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-class.c b/gcc/testsuite/gcc.target/mips/mips-class.c new file mode 100644 index 00000000000..e71a853fb8c --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips-class.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-mhard-float -march=mips32r6" } */ + +NOMIPS16 float +test01 (float a) +{ + return __builtin_mipsr6_class_s (a); +} + +NOMIPS16 double +test02 (double a) +{ + return __builtin_mipsr6_class_d (a); +} + +/* { dg-final { scan-assembler "class\\.s" } } */ +/* { dg-final { scan-assembler "class\\.d" } } */ diff --git a/gcc/testsuite/gcc.target/mips/mips-minamaxa.c b/gcc/testsuite/gcc.target/mips/mips-minamaxa.c new file mode 100644 index 00000000000..d41d6078779 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips-minamaxa.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-mhard-float -march=mips32r6" } */ + +NOMIPS16 float +test01 (float a, float b) +{ + return __builtin_mipsr6_min_a_s (a, b); +} + +NOMIPS16 double +test02 (double a, double b) +{ + return __builtin_mipsr6_min_a_d (a, b); +} + +NOMIPS16 float +test03 (float a, float b) +{ + return __builtin_mipsr6_max_a_s (a, b); +} + +NOMIPS16 double +test04 (double a, double b) +{ + return __builtin_mipsr6_max_a_d (a, b); +} + +/* { dg-final { scan-assembler "mina\\.s" } } */ +/* { dg-final { scan-assembler "mina\\.d" } } */ +/* { dg-final { scan-assembler "maxa\\.s" } } */ +/* { dg-final { scan-assembler "maxa\\.d" } } */ diff --git a/gcc/testsuite/gcc.target/mips/mips-rint.c b/gcc/testsuite/gcc.target/mips/mips-rint.c new file mode 100644 index 00000000000..a964b8c4267 --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/mips-rint.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-mhard-float -march=mips32r6" } */ + +NOMIPS16 float +test01 (float a) +{ + return __builtin_mipsr6_rint_s (a); +} + +NOMIPS16 double +test02 (double a) +{ + return __builtin_mipsr6_rint_d (a); +} + +/* { dg-final { scan-assembler "rint\\.s" } } */ +/* { dg-final { scan-assembler "rint\\.d" } } */