https://gcc.gnu.org/g:2c98d7cf3a151e3d464a8e4a161d084494281d76
commit r16-4071-g2c98d7cf3a151e3d464a8e4a161d084494281d76 Author: Xi Ruoyao <xry...@xry111.site> Date: Tue Sep 16 23:10:26 2025 +0800 LoongArch: Add isnan expander [PR 66462] 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. Diff: --- 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 f42dc102d109..a275a2d0158e 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -4193,17 +4193,18 @@ [(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 9c24d6e263ce..3db83e7b31d3 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 e5585f9d557a..3852d2015b3a 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); }