+1 to any change that reduces the number of fflags accesses.

On Fri, Jun 28, 2024 at 5:54 PM Vineet Gupta <vine...@rivosinc.com> wrote:
>
> Currently isfinite and isnormal use float compare instructions with fp
> flags save/restored around them. Our perf team complained this could be
> costly in uarch. RV Base ISA already has FCLASS.{d,s,h} instruction to
> do FP compares w/o disturbing FP exception flags.
>
> Coincidently, upstream ijust few days back got support for the
> corresponding optabs. All that is needed is to wire these up in the
> backend.
>
> I was also hoping to get __builtin_inf() done but unforutnately it
> requires little more rtl foo/bar to implement a tri-modal return.
>
> Currently going thru CI testing.
>
> gcc/ChangeLog:
>         * config/riscv/riscv.md: Add UNSPEC_FCLASS, UNSPEC_ISFINITE,
>         USPEC_ISNORMAL.
>         define_insn for fclass.
>         define_expand for isfinite and isnormal.
>
> gcc/testsuite/ChangeLog:
>         * gcc.target/riscv/fclass.c: New test.
>
> Signed-off-by: Vineet Gupta <vine...@rivosinc.com>
> ---
>  gcc/config/riscv/riscv.md               | 56 +++++++++++++++++++++++++
>  gcc/testsuite/gcc.target/riscv/fclass.c | 18 ++++++++
>  2 files changed, 74 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/fclass.c
>
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index ff37125e3f28..fc4441916137 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -68,6 +68,9 @@
>    UNSPEC_FMAX
>    UNSPEC_FMINM
>    UNSPEC_FMAXM
> +  UNSPEC_FCLASS
> +  UNSPEC_ISFINITE
> +  UNSPEC_ISNORMAL
>
>    ;; Stack tie
>    UNSPEC_TIE
> @@ -3436,6 +3439,59 @@
>     (set_attr "mode" "<UNITMODE>")
>     (set (attr "length") (const_int 16))])
>
> +;; fclass instruction output bitmap
> +;;   0 negative infinity
> +;;   1 negative normal number.
> +;;   2 negative subnormal number.
> +;;   3 -0
> +;;   4 +0
> +;;   5 positive subnormal number.
> +;;   6 positive normal number.
> +;;   7 positive infinity
> +;;   8 signaling NaN.
> +;;   9 quiet NaN
> +(define_insn "fclass<ANYF:mode>"
> +  [(set (match_operand:SI              0 "register_operand" "=r")
> +       (unspec:SI [(match_operand:ANYF 1 "register_operand" " f")]
> +                  UNSPEC_FCLASS))]
> +  "TARGET_HARD_FLOAT"
> +  "fclass.<fmt>\t%0,%1"
> +  [(set_attr "type" "fcmp")
> +   (set_attr "mode" "<UNITMODE>")])
> +
> +(define_expand "isfinite<ANYF:mode>2"
> +  [(set (match_operand:SI              0 "register_operand" "=r")
> +       (unspec:SI [(match_operand:ANYF 1 "register_operand" " f")]
> +                  UNSPEC_ISFINITE))]
> +  "TARGET_HARD_FLOAT"
> +{
> +  rtx tmp = gen_reg_rtx (SImode);
> +  emit_insn (gen_fclass<ANYF:mode> (tmp, operands[1]));
> +  riscv_emit_binary (AND, tmp, tmp, GEN_INT (0x7e));
> +  rtx cmp = gen_rtx_NE (SImode, tmp, const0_rtx);
> +  emit_insn (gen_cstoresi4 (operands[0], cmp, tmp, const0_rtx));
> +
> +  DONE;
> +})
> +
> +;; TODO: isinf is a bit tricky as it require trimodal return
> +;;  1 if 0x80, -1 if 0x1, 0 otherwise
> +
> +(define_expand "isnormal<ANYF:mode>2"
> +  [(set (match_operand:SI              0 "register_operand" "=r")
> +       (unspec:SI [(match_operand:ANYF 1 "register_operand" " f")]
> +                  UNSPEC_ISNORMAL))]
> +  "TARGET_HARD_FLOAT"
> +{
> +  rtx tmp = gen_reg_rtx (SImode);
> +  emit_insn (gen_fclass<ANYF:mode> (tmp, operands[1]));
> +  riscv_emit_binary (AND, tmp, tmp, GEN_INT (0x42));
> +  rtx cmp = gen_rtx_NE (SImode, tmp, const0_rtx);
> +  emit_insn (gen_cstoresi4 (operands[0], cmp, tmp, const0_rtx));
> +
> +  DONE;
> +})
> +
>  (define_insn "*seq_zero_<X:mode><GPR:mode>"
>    [(set (match_operand:GPR       0 "register_operand" "=r")
>         (eq:GPR (match_operand:X 1 "register_operand" " r")
> diff --git a/gcc/testsuite/gcc.target/riscv/fclass.c 
> b/gcc/testsuite/gcc.target/riscv/fclass.c
> new file mode 100644
> index 000000000000..0dfac982ebeb
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/fclass.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile } */
> +/* { dg-require-effective-target hard_float } */
> +/* { dg-options "-march=rv64gc -mabi=lp64d  -ftrapping-math { target { rv64 
> } } } */
> +/* { dg-options "-march=rv32gc -mabi=ilp32d -ftrapping-math { target { rv32 
> } } } */
> +
> +int t_isfinite(double a)
> +{
> +  return __builtin_isfinite(a);
> +}
> +
> +int t_isnormal(double a)
> +{
> +  return __builtin_isnormal(a);
> +}
> +
> +/* { dg-final { scan-assembler-not   {\mfrflags}  } } */
> +/* { dg-final { scan-assembler-not   {\mfsflags}  } } */
> +/* { dg-final { scan-assembler-times {\tfclass} 2 } } */
> --
> 2.34.1
>

Reply via email to