在 2024/7/11 下午7:45, Xi Ruoyao 写道:
Doing so can avoid loading FP constants from the memory.  It also
partially fixes PR 66462 as fclass does not signal on sNaN.

gcc/ChangeLog:

        * config/loongarch/loongarch.md (extendsidi2): Add ("=r", "f")
        alternative and use movfr2gr.s for it.  The spec clearly states
        movfr2gr.s sign extends the value to GRLEN.
        (fclass_<fmt>): Make the result SImode instead of a floating
        mode.  The fclass results are really not FP values.
        (FCLASS_MASK): New define_int_iterator.
        (fclass_optab): New define_int_attr.
        (<FCLASS_MASK:fclass_optab><ANYF:mode>): New define_expand
        template.

gcc/testsuite/ChangeLog:

        * gcc.target/loongarch/fclass-compile.c: New test.
        * gcc.target/loongarch/fclass-run.c: New test.
---

Bootstrapped and regtested on loongarch64-linux-gnu.  There are two
regressions: range-sincos.c and vrp-float-abs-1.c but they shall be
fixed by
https://gcc.gnu.org/pipermail/gcc-patches/2024-July/656937.html.

There is a redundant "andi" in the code generation for the test case:
https://gcc.gnu.org/pipermail/gcc-patches/2024-July/656764.html.

I suppose the fix of this redundant "andi" is using word_mode instead
of SImode for operand 0, but it does not work as at now:
https://gcc.gnu.org/pipermail/gcc-patches/2024-July/656772.html.

Ok for trunk (now, or after the fix for range-sincos.c and
vrp-float-abs-1.c are committed)?  IMO the redundant "andi" can be fixed
later.

Hi,

g++.dg/opt/pr107569. C and range-sincos.c vrp-float-abs-1.c is the same issue, right?

And I have no objection to code modifications. But I think it's better to wait until this builtin

function is fixed.

Thanks!


  gcc/config/loongarch/loongarch.md             | 53 ++++++++++++++++---
  .../gcc.target/loongarch/fclass-compile.c     | 20 +++++++
  .../gcc.target/loongarch/fclass-run.c         | 53 +++++++++++++++++++
  3 files changed, 119 insertions(+), 7 deletions(-)
  create mode 100644 gcc/testsuite/gcc.target/loongarch/fclass-compile.c
  create mode 100644 gcc/testsuite/gcc.target/loongarch/fclass-run.c

diff --git a/gcc/config/loongarch/loongarch.md 
b/gcc/config/loongarch/loongarch.md
index e4434c3bd4e..b3cae49832e 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -1829,16 +1829,17 @@ (define_insn "*zero_extendhi_truncqi"
  ;;  ....................
(define_insn "extendsidi2"
-  [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
+  [(set (match_operand:DI 0 "register_operand" "=r,r,r,r,r")
        (sign_extend:DI
-           (match_operand:SI 1 "nonimmediate_operand" "r,ZC,m,k")))]
+           (match_operand:SI 1 "nonimmediate_operand" "r,ZC,m,k,f")))]
    "TARGET_64BIT"
    "@
     slli.w\t%0,%1,0
     ldptr.w\t%0,%1
     ld.w\t%0,%1
-   ldx.w\t%0,%1"
-  [(set_attr "move_type" "sll0,load,load,load")
+   ldx.w\t%0,%1
+   movfr2gr.s\t%0,%1"
+  [(set_attr "move_type" "sll0,load,load,load,mftg")
     (set_attr "mode" "DI")])
(define_insn "extend<SHORT:mode><GPR:mode>2"
@@ -4162,14 +4163,52 @@ (define_insn "loongarch_movgr2fcsr"
    "movgr2fcsr\t$r%0,%1")
(define_insn "fclass_<fmt>"
-  [(set (match_operand:ANYF 0 "register_operand" "=f")
-       (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
-                     UNSPEC_FCLASS))]
+  [(set (match_operand:SI 0 "register_operand" "=f")
+       (unspec:SI [(match_operand:ANYF 1 "register_operand" "f")]
+                  UNSPEC_FCLASS))]
    "TARGET_HARD_FLOAT"
    "fclass.<fmt>\t%0,%1"
    [(set_attr "type" "unknown")
     (set_attr "mode" "<MODE>")])
+(define_int_iterator FCLASS_MASK [68 136 952])
+(define_int_attr fclass_optab
+  [(68 "isinf")
+   (136        "isnormal")
+   (952        "isfinite")])
+
+(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"
+  {
+    rtx ft0 = gen_reg_rtx (SImode);
+    rtx t0 = gen_reg_rtx (word_mode);
+    rtx mask = GEN_INT (<FCLASS_MASK>);
+
+    emit_insn (gen_fclass_<ANYF:fmt> (ft0, operands[1]));
+
+    if (TARGET_64BIT)
+      emit_insn (gen_extend_insn (t0, ft0, DImode, SImode, 0));
+    else
+      emit_move_insn (t0, ft0);
+
+    emit_move_insn (t0, gen_rtx_AND (word_mode, t0, mask));
+    emit_move_insn (t0, gen_rtx_NE (word_mode, t0, const0_rtx));
+
+    if (TARGET_64BIT)
+      {
+       t0 = lowpart_subreg (SImode, t0, DImode);
+       SUBREG_PROMOTED_VAR_P (t0) = 1;
+       SUBREG_PROMOTED_SET (t0, SRP_SIGNED);
+      }
+
+    emit_move_insn (operands[0], t0);
+
+    DONE;
+  })
+
  (define_insn "bytepick_w_<bytepick_imm>"
    [(set (match_operand:SI 0 "register_operand" "=r")
        (ior:SI (lshiftrt (match_operand:SI 1 "register_operand" "r")
diff --git a/gcc/testsuite/gcc.target/loongarch/fclass-compile.c 
b/gcc/testsuite/gcc.target/loongarch/fclass-compile.c
new file mode 100644
index 00000000000..9c24d6e263c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/fclass-compile.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mfpu=64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler-times "fclass\\.s" 1 } } */
+/* { dg-final { scan-assembler-times "fclass\\.d" 1 } } */
+
+__attribute__ ((noipa)) int
+test_fclass_f (float f)
+{
+  return __builtin_isinf (f)
+        | __builtin_isnormal (f) << 1
+        | __builtin_isfinite (f) << 2;
+}
+
+__attribute__ ((noipa)) int
+test_fclass_d (double d)
+{
+  return __builtin_isinf (d)
+        | __builtin_isnormal (d) << 1
+        | __builtin_isfinite (d) << 2;
+}
diff --git a/gcc/testsuite/gcc.target/loongarch/fclass-run.c 
b/gcc/testsuite/gcc.target/loongarch/fclass-run.c
new file mode 100644
index 00000000000..e5585f9d557
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/fclass-run.c
@@ -0,0 +1,53 @@
+/* { dg-do run } */
+/* { dg-options "-O2 -fsignaling-nans -D_GNU_SOURCE -std=c23" } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+#include "fclass-compile.c"
+
+#define ASSERT_EQ(x, y) (void)(x == y || (__builtin_abort (), 1))
+
+int
+main (void)
+{
+  volatile float f_inf = __builtin_inff ();
+  volatile float f_zero = 0;
+  volatile float f_normal = 114.514;
+  volatile float f_subnormal = 1e-40;
+  volatile float f_qnan = __builtin_nanf ("");
+  volatile float f_snan = __builtin_nansf ("");
+  volatile double d_inf = __builtin_inf ();
+  volatile double d_zero = 0;
+  volatile double d_normal = 1919.810;
+  volatile double d_subnormal = 1e-320;
+  volatile double d_qnan = __builtin_nan ("");
+  volatile double d_snan = __builtin_nans ("");
+
+#if __loongarch_frlen >= 64
+  /* With fclass.{s/d} we shouldn't signal, even if the input is sNaN.
+     PR 66462.  */
+  feenableexcept (FE_INVALID);
+#endif
+
+  ASSERT_EQ (test_fclass_f (f_inf), 0b001);
+  ASSERT_EQ (test_fclass_f (-f_inf), 0b001);
+  ASSERT_EQ (test_fclass_f (f_zero), 0b100);
+  ASSERT_EQ (test_fclass_f (-f_zero), 0b100);
+  ASSERT_EQ (test_fclass_f (f_normal), 0b110);
+  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_d (d_inf), 0b001);
+  ASSERT_EQ (test_fclass_d (-d_inf), 0b001);
+  ASSERT_EQ (test_fclass_d (d_zero), 0b100);
+  ASSERT_EQ (test_fclass_d (-d_zero), 0b100);
+  ASSERT_EQ (test_fclass_d (d_normal), 0b110);
+  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);
+}

Reply via email to