LoongArch: Provide fmin/fmax RTL pattern

We already had smin/smax RTL pattern using fmin/fmax instruction.  But
for smin/smax, it's unspecified what will happen if either operand is
NaN.  So we would generate calls to libc fmin/fmax functions with
-fno-finite-math-only (the default for all optimization levels expect
-Ofast).

But, LoongArch fmin/fmax instruction is IEEE-754-2008 conformant so we
can also use the instruction for fmin/fmax pattern and avoid the library
function call.

gcc/ChangeLog:

	* config/loongarch/loongarch.md (fmax<mode>3): New RTL pattern.
	(fmin<mode>3): Likewise.

gcc/testsuite/ChangeLog:

	* gcc.target/loongarch/fmax-fmin.c: New test.
This commit is contained in:
Xi Ruoyao 2022-08-16 15:34:36 +08:00
parent 80f78716c2
commit 3cab897a67
No known key found for this signature in database
GPG key ID: ACAAD20E19E710E3
2 changed files with 48 additions and 0 deletions

View file

@ -1023,6 +1023,24 @@
[(set_attr "type" "fmove")
(set_attr "mode" "<MODE>")])
(define_insn "fmax<mode>3"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(smax:ANYF (match_operand:ANYF 1 "register_operand" "f")
(match_operand:ANYF 2 "register_operand" "f")))]
""
"fmax.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
(set_attr "mode" "<MODE>")])
(define_insn "fmin<mode>3"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(smin:ANYF (match_operand:ANYF 1 "register_operand" "f")
(match_operand:ANYF 2 "register_operand" "f")))]
""
"fmin.<fmt>\t%0,%1,%2"
[(set_attr "type" "fmove")
(set_attr "mode" "<MODE>")])
(define_insn "smaxa<mode>3"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(if_then_else:ANYF

View file

@ -0,0 +1,30 @@
/* { dg-do compile } */
/* { dg-options "-mdouble-float -fno-finite-math-only" } */
/* { dg-final { scan-assembler "fmin\\.s" } } */
/* { dg-final { scan-assembler "fmin\\.d" } } */
/* { dg-final { scan-assembler "fmax\\.s" } } */
/* { dg-final { scan-assembler "fmax\\.d" } } */
double
_fmax(double a, double b)
{
return __builtin_fmax(a, b);
}
float
_fmaxf(float a, float b)
{
return __builtin_fmaxf(a, b);
}
double
_fmin(double a, double b)
{
return __builtin_fmin(a, b);
}
float
_fminf(float a, float b)
{
return __builtin_fminf(a, b);
}