Add an expander for isnan using fclass. Since isnan is
just a compare, enable it only with -fsignaling-nans to avoid
generating spurious exceptions. This fixes part of PR66462.
int isnan1 (float x) { return __builtin_isnan (x); }
With -fno-signaling-nans:
fcmp.cun.s $fcc0,$f0,$f0
movcf2fr $f0,$fcc0
movfr2gr.s $r4,$f0
jr $r1
With -fsignaling-nans:
fclass.s $f0,$f0
movfr2gr.s $r4,$f0
andi $r4,$r4,3
sltu $r4,$r0,$r4
jr $r1
PR middle-end/66462
gcc/
* config/loongarch/loongarch.md (FCLASS_MASK): Add 3.
(fclass_optab): Assign isnan for 3.
(<FCLASS_MASK:fclass_optab><ANYF:mode>2): If FCLASS_MASK is 3,
only enable when -fsignaling-nans.
gcc/testsuite:
* gcc.target/loongarch/fclass-compile.c: Update test.
* gcc.target/loongarch/fclass-run.c: Likewise.
---
Bootstrapped and regtested on loongarch64-linux-gnu. Ok for trunk?
gcc/config/loongarch/loongarch.md | 7 ++++---
gcc/testsuite/gcc.target/loongarch/fclass-compile.c | 9 ++++++---
gcc/testsuite/gcc.target/loongarch/fclass-run.c | 8 ++++----
3 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/gcc/config/loongarch/loongarch.md
b/gcc/config/loongarch/loongarch.md
index f42dc102d10..a275a2d0158 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -4193,17 +4193,18 @@ (define_insn "fclass_<fmt>"
[(set_attr "type" "unknown")
(set_attr "mode" "<MODE>")])
-(define_int_iterator FCLASS_MASK [68 136 952])
+(define_int_iterator FCLASS_MASK [68 136 952 3])
(define_int_attr fclass_optab
[(68 "isinf")
(136 "isnormal")
- (952 "isfinite")])
+ (952 "isfinite")
+ (3 "isnan")])
(define_expand "<FCLASS_MASK:fclass_optab><ANYF:mode>2"
[(match_operand:SI 0 "register_operand" "=r")
(match_operand:ANYF 1 "register_operand" " f")
(const_int FCLASS_MASK)]
- "TARGET_HARD_FLOAT"
+ "TARGET_HARD_FLOAT && (<FCLASS_MASK> != 3 || flag_signaling_nans)"
{
rtx ft0 = gen_reg_rtx (SImode);
rtx t0 = gen_reg_rtx (word_mode);
diff --git a/gcc/testsuite/gcc.target/loongarch/fclass-compile.c
b/gcc/testsuite/gcc.target/loongarch/fclass-compile.c
index 9c24d6e263c..3db83e7b31d 100644
--- a/gcc/testsuite/gcc.target/loongarch/fclass-compile.c
+++ b/gcc/testsuite/gcc.target/loongarch/fclass-compile.c
@@ -1,14 +1,16 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -march=loongarch64 -mfpu=64 -mabi=lp64d" } */
+/* { dg-options "-O2 -fsignaling-nans -march=loongarch64 -mfpu=64 -mabi=lp64d"
} */
/* { dg-final { scan-assembler-times "fclass\\.s" 1 } } */
/* { dg-final { scan-assembler-times "fclass\\.d" 1 } } */
+/* { dg-final { scan-assembler-not "fcmp" } } */
__attribute__ ((noipa)) int
test_fclass_f (float f)
{
return __builtin_isinf (f)
| __builtin_isnormal (f) << 1
- | __builtin_isfinite (f) << 2;
+ | __builtin_isfinite (f) << 2
+ | __builtin_isnan (f) << 3;
}
__attribute__ ((noipa)) int
@@ -16,5 +18,6 @@ test_fclass_d (double d)
{
return __builtin_isinf (d)
| __builtin_isnormal (d) << 1
- | __builtin_isfinite (d) << 2;
+ | __builtin_isfinite (d) << 2
+ | __builtin_isnan (d) << 3;
}
diff --git a/gcc/testsuite/gcc.target/loongarch/fclass-run.c
b/gcc/testsuite/gcc.target/loongarch/fclass-run.c
index e5585f9d557..3852d2015b3 100644
--- a/gcc/testsuite/gcc.target/loongarch/fclass-run.c
+++ b/gcc/testsuite/gcc.target/loongarch/fclass-run.c
@@ -37,8 +37,8 @@ main (void)
ASSERT_EQ (test_fclass_f (-f_normal), 0b110);
ASSERT_EQ (test_fclass_f (f_subnormal), 0b100);
ASSERT_EQ (test_fclass_f (-f_subnormal), 0b100);
- ASSERT_EQ (test_fclass_f (f_qnan), 0);
- ASSERT_EQ (test_fclass_f (f_snan), 0);
+ ASSERT_EQ (test_fclass_f (f_qnan), 0b1000);
+ ASSERT_EQ (test_fclass_f (f_snan), 0b1000);
ASSERT_EQ (test_fclass_d (d_inf), 0b001);
ASSERT_EQ (test_fclass_d (-d_inf), 0b001);
@@ -48,6 +48,6 @@ main (void)
ASSERT_EQ (test_fclass_d (-d_normal), 0b110);
ASSERT_EQ (test_fclass_d (d_subnormal), 0b100);
ASSERT_EQ (test_fclass_d (-d_subnormal), 0b100);
- ASSERT_EQ (test_fclass_d (d_qnan), 0);
- ASSERT_EQ (test_fclass_d (d_snan), 0);
+ ASSERT_EQ (test_fclass_d (d_qnan), 0b1000);
+ ASSERT_EQ (test_fclass_d (d_snan), 0b1000);
}
--
2.51.0