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.
This commit is contained in:
parent
deb69bfbb0
commit
11c13111ac
6 changed files with 134 additions and 4 deletions
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
40
gcc/testsuite/gcc.target/mips/mips-minmax1.c
Normal file
40
gcc/testsuite/gcc.target/mips/mips-minmax1.c
Normal file
|
@ -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);
|
||||
}
|
||||
|
36
gcc/testsuite/gcc.target/mips/mips-minmax2.c
Normal file
36
gcc/testsuite/gcc.target/mips/mips-minmax2.c
Normal file
|
@ -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);
|
||||
}
|
Loading…
Add table
Reference in a new issue