]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: Add isnan expander [PR 66462]
authorXi Ruoyao <xry111@xry111.site>
Tue, 16 Sep 2025 15:10:26 +0000 (23:10 +0800)
committerXi Ruoyao <xry111@xry111.site>
Wed, 24 Sep 2025 08:24:41 +0000 (16:24 +0800)
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.

gcc/config/loongarch/loongarch.md
gcc/testsuite/gcc.target/loongarch/fclass-compile.c
gcc/testsuite/gcc.target/loongarch/fclass-run.c

index f42dc102d10912dbca7dc9e8b870ddea30150c0c..a275a2d0158e01f5533d8928875183414c0df679 100644 (file)
   [(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);
index 9c24d6e263ce4cacd89b216b90681eda654b8189..3db83e7b31d35c6f9a5f0f6d3b2027c6e8df57cf 100644 (file)
@@ -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;
 }
index e5585f9d557aaa4435be544686fb074b57b0df10..3852d2015b3aa2a66169adc4e5a3b65f5ac38682 100644 (file)
@@ -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);
 }