Hi Jeff,

On 7/13/24 07:54, Vineet Gupta wrote:
> Changes since v4:
>   - No functional changes.
>   - Use int iterator and attr to implement expanders in md
>     (inspired by loongarch patch. Thx Xi Ruoyao)
>
> Changes since v3:
>   - Remove '*' from define_insn for fclass
>   - Remove the dummy expander for fclass.
>   - De-duplicate the expanders code by using a helper which takes fclass
>     val.
>
> Changes since v2:
>   - fclass define_insn tightened to check op0 mode "X" with additional
>     expander w/o mode for callers.
>   - builtins expander explicit mode check and FAIL if mode not appropriate.
>   - subreg promoted handling to elide potential extension of ret val.
>   - Added isinf builtin with bimodal retun value as others.
>
> Changes since v1:
>   - Removed UNSPEC_{INFINITE,ISNORMAL}
>   - Don't hardcode SI in patterns, try to keep X to avoid potential
>     sign extension pitfalls. Implementation wise requires skipping
>     :MODE specifier in match_operand which is flagged as missing mode
>     warning.
> ---
>
> Currently thsse builtins use float compare instructions which require
> FP flags to be save/restore around them.
> Our perf team complained this could be costly in uarch.
> RV Base ISA already has FCLASS.{d,s,h} instruction to compare/identify FP
> values w/o disturbing FP exception flags.
>
> Coincidently, upstream very recently got support for the corresponding
> optabs. So this just requires wiring up in the backend.
>
> Tested for rv64, one additioal failure g++.dg/opt/pr107569.C needs
> upstream ranger fix for the new optab.


Pre-commit CI reports [1] three additional failures which are related to
ranger patches in this space, same as what Loongarch folks are seeing [2]

FAIL: gcc.dg/tree-ssa/range-sincos.c scan-tree-dump-not evrp "link_error"
FAIL: gcc.dg/tree-ssa/vrp-float-abs-1.c scan-tree-dump-not evrp "link_error"
FAIL: g++.dg/opt/pr107569.C  -std=gnu++20  scan-tree-dump-times vrp1
"return 1;" 2

Here's my testing with trunk of this morning, which corroborates with
the same:
     2024-07-16 fec38d7987dd rtl-ssa: Fix removal of order_nodes
[PR115929] 

 rv64imafdc_zba_zbb_zbs_zicond_zfa/  lp64d/ medlow |  321 /    56 |    0
/     0 |    6 /     1 |   # upstream
 rv64imafdc_zba_zbb_zbs_zicond_zfa/  lp64d/ medlow |  323 /    58 |    1
/     1 |    6 /     1 |   # upstream + mypatch
 rv64imafdc_zba_zbb_zbs_zicond_zfa/  lp64d/ medlow |  321 /    56 |    0
/     0 |    6 /     1 |   # upstream + mypatch + ranger patches

Having said that I don't mind if you prefer the ranger patches make it
in first.

Thx,
-Vineet

[1] https://github.com/ewlu/gcc-precommit-ci/issues/1908
[2] https://gcc.gnu.org/pipermail/gcc-patches/2024-July/656972.html


>
> gcc/ChangeLog:
>       * config/riscv/iterators.md (FCLASS_MASK): New define_int_iterator.
>       (fclass_optab): New define_int_attr.
>       * config/riscv/riscv.md: Add UNSPEC_FCLASS.
>       (fclass<ANYF:mode><X:mode>): New define_insn.
>       (<FCLASS_MASK:fclass_optab><ANYF:mode>2): New define_expand template
>       for isfinite, isnormal, isinf.
>
> gcc/testsuite/ChangeLog:
>       * gcc.target/riscv/fclass.c: New tests.
>
> Signed-off-by: Vineet Gupta <vine...@rivosinc.com>
> ---
>  gcc/config/riscv/iterators.md           |  7 +++
>  gcc/config/riscv/riscv.md               | 57 +++++++++++++++++++++++++
>  gcc/testsuite/gcc.target/riscv/fclass.c | 38 +++++++++++++++++
>  3 files changed, 102 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/riscv/fclass.c
>
> diff --git a/gcc/config/riscv/iterators.md b/gcc/config/riscv/iterators.md
> index 20745faa55ef..20413737f775 100644
> --- a/gcc/config/riscv/iterators.md
> +++ b/gcc/config/riscv/iterators.md
> @@ -219,6 +219,13 @@
>  
>  (define_code_attr fix_uns [(fix "fix") (unsigned_fix "fixuns")])
>  
> +;; fclass mask values for corresponding builtins
> +(define_int_iterator FCLASS_MASK [126 66 129])
> +
> +(define_int_attr fclass_optab
> +  [(126      "isfinite")
> +   (66       "isnormal")
> +   (129      "isinf")])
>  
>  ;; -------------------------------------------------------------------
>  ;; Code Attributes
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index ff37125e3f28..1e1be1f5c192 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -68,6 +68,7 @@
>    UNSPEC_FMAX
>    UNSPEC_FMINM
>    UNSPEC_FMAXM
> +  UNSPEC_FCLASS
>  
>    ;; Stack tie
>    UNSPEC_TIE
> @@ -3436,6 +3437,62 @@
>     (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><X:mode>"
> +  [(set (match_operand:X          0 "register_operand" "=r")
> +     (unspec [(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>")])
> +
> +;; Implements optab for isfinite, isnormal, isinf
> +
> +(define_expand "<FCLASS_MASK:fclass_optab><ANYF:mode>2"
> +  [(match_operand      0 "register_operand" "=r")
> +   (match_operand:ANYF 1 "register_operand" " f")
> +   (const_int FCLASS_MASK)]
> +  "TARGET_HARD_FLOAT"
> +{
> +  if (GET_MODE (operands[0]) != SImode
> +      && GET_MODE (operands[0]) != word_mode)
> +    FAIL;
> +
> +  rtx t = gen_reg_rtx (word_mode);
> +  rtx t_op0 = gen_reg_rtx (word_mode);
> +
> +  if (TARGET_64BIT)
> +    emit_insn (gen_fclass<ANYF:mode>di (t, operands[1]));
> +  else
> +    emit_insn (gen_fclass<ANYF:mode>si (t, operands[1]));
> +
> +  riscv_emit_binary (AND, t, t, GEN_INT (<FCLASS_MASK>));
> +  rtx cmp = gen_rtx_NE (word_mode, t, const0_rtx);
> +  emit_insn (gen_cstore<mode>4 (t_op0, cmp, t, const0_rtx));
> +
> +  if (TARGET_64BIT)
> +    {
> +      t_op0 = gen_lowpart (SImode, t_op0);
> +      SUBREG_PROMOTED_VAR_P (t_op0) = 1;
> +      SUBREG_PROMOTED_SET (t_op0, SRP_SIGNED);
> +    }
> +
> +  emit_move_insn (operands[0], t_op0);
> +  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..ea0f173ecf4b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/riscv/fclass.c
> @@ -0,0 +1,38 @@
> +/* { 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 d_isfinite(double a)
> +{
> +  return __builtin_isfinite(a);
> +}
> +
> +int d_isnormal(double a)
> +{
> +  return __builtin_isnormal(a);
> +}
> +
> +int d_isinf(double a)
> +{
> +  return __builtin_isinf(a);
> +}
> +
> +int f_isfinite(float a)
> +{
> +  return __builtin_isfinite(a);
> +}
> +
> +int f_isnormal(float a)
> +{
> +  return __builtin_isnormal(a);
> +}
> +
> +int f_isinf(float a)
> +{
> +  return __builtin_isinf(a);
> +}
> +
> +/* { dg-final { scan-assembler-not   {\mfrflags}  } } */
> +/* { dg-final { scan-assembler-not   {\mfsflags}  } } */
> +/* { dg-final { scan-assembler-times {\tfclass} 6 } } */

Reply via email to