MIPS: Add some floating point instructions support for MIPSr6
This patch adds some of the float point instructions from MIPS32 Release 6(mips32r6) with their respective built-in functions and tests: min_a_s, min_a_d max_a_s, max_a_d rint_s, rint_d class_s, class_d 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. (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_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, 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. (rint<mode>2): Generates RINT.fmt instructions. (fclass_<mode>): Generates CLASS.fmt instructions. * config/mips/p6600.md (p6600_fpu_fadd): Include frint type. (p6600_fpu_fabs): Include 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. Signed-off-by: Jie Mei <jie.mei@oss.cipunited.com> Co-authored-by: Xi Ruoyao <xry111@xry111.site>
This commit is contained in:
parent
b7008552b4
commit
86b9abc829
8 changed files with 151 additions and 10 deletions
|
@ -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
|
||||
|
|
|
@ -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,13 @@ 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_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 +17014,14 @@ 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 (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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
@ -8013,6 +8017,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 "rint<mode>2"
|
||||
[(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")
|
||||
|
|
|
@ -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")
|
||||
|
|
17
gcc/testsuite/gcc.target/mips/mips-class.c
Normal file
17
gcc/testsuite/gcc.target/mips/mips-class.c
Normal file
|
@ -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" } } */
|
31
gcc/testsuite/gcc.target/mips/mips-minamaxa.c
Normal file
31
gcc/testsuite/gcc.target/mips/mips-minamaxa.c
Normal file
|
@ -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" } } */
|
17
gcc/testsuite/gcc.target/mips/mips-rint.c
Normal file
17
gcc/testsuite/gcc.target/mips/mips-rint.c
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-mhard-float -march=mips32r6" } */
|
||||
|
||||
NOMIPS16 float
|
||||
test01 (float a)
|
||||
{
|
||||
return __builtin_rintf (a);
|
||||
}
|
||||
|
||||
NOMIPS16 double
|
||||
test02 (double a)
|
||||
{
|
||||
return __builtin_rint (a);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-assembler "rint\\.s" } } */
|
||||
/* { dg-final { scan-assembler "rint\\.d" } } */
|
Loading…
Add table
Reference in a new issue