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);
 }

Reply via email to