Projects
openEuler:24.03:SP1:Everything
gcc
_service:tar_scm:0185-LoongArch-Implement-scala...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:0185-LoongArch-Implement-scalar-isinf-isnormal-and-isfini.patch of Package gcc
From 7e8e122306feaecf8d7b520b4e7c0b9908ca6fd2 Mon Sep 17 00:00:00 2001 From: Xi Ruoyao <xry111@xry111.site> Date: Thu, 4 Jul 2024 02:49:28 +0800 Subject: [PATCH 185/188] LoongArch: Implement scalar isinf, isnormal, and isfinite via fclass Doing so can avoid loading FP constants from the memory. It also partially fixes PR 66262 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. --- 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 867977b36..15960a79f 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -1851,16 +1851,17 @@ ;; .................... (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" @@ -4110,14 +4111,52 @@ "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:SI (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 000000000..9c24d6e26 --- /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 000000000..e5585f9d5 --- /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); +} -- 2.43.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2