On Sun, Sep 20, 2026 at 10:25 AM Matt Turner <[email protected]> wrote:
>
> The isinf, isfinite and isnan expanders are restricted to SFmode and
> DFmode, so _Float16 and __bf16 still classify with FP comparisons.
> Extend them to the two 16-bit formats.
>
> Neither has 16-bit integer arithmetic, so zero-extend the encoding into
> a word and shift the sign bit out of the top of that instead of out of
> the top of the 16-bit value.
>
> int isinf1 (_Float16 x) { return __builtin_isinf (x); }
>
> Before:
>         umov    w0, v0.h[0]
>         mvni    v30.4h, 0x84, lsl 8
>         fcvt    s30, h30
>         and     w0, w0, 32767
>         dup     v31.4h, w0
>         fcvt    s31, h31
>         fcmp    s31, s30
>         cset    w0, eq
>         ret
>
> After:
>         umov    w0, v0.h[0]
>         mov     w1, -134217728
>         cmp     w1, w0, lsl 17
>         cset    w0, eq
>         ret
>
> gcc/ChangeLog:
>
>         PR middle-end/66462
>         * config/aarch64/aarch64.md (cmp_swp_<shift>_reg<mode>): Add a
>         parameterized name.
>         (isinf<mode>2): Use GPF_HF_BF and handle the 16-bit formats.
>         (isfinite<mode>2): Likewise.
>         (isnan<mode>2): Likewise.


Ok.

>
> gcc/testsuite/ChangeLog:
>
>         PR middle-end/66462
>         * gcc.target/aarch64/pr66462.c: Add _Float16 and __bf16 tests for
>         isinf, isfinite and isnan.
> ---
>  gcc/config/aarch64/aarch64.md              | 59 ++++++++++++++++------
>  gcc/testsuite/gcc.target/aarch64/pr66462.c | 41 +++++++++++++++
>  2 files changed, 84 insertions(+), 16 deletions(-)
>
> diff --git ./gcc/config/aarch64/aarch64.md ./gcc/config/aarch64/aarch64.md
> index 58383483b12..eb4436a9fc9 100644
> --- ./gcc/config/aarch64/aarch64.md
> +++ ./gcc/config/aarch64/aarch64.md
> @@ -4697,7 +4697,7 @@
>    [(set_attr "type" "fcmp<stype>")]
>  )
>
> -(define_insn "cmp_swp_<shift>_reg<mode>"
> +(define_insn "@cmp_swp_<shift>_reg<mode>"
>    [(set (reg:CC_SWP CC_REGNUM)
>         (compare:CC_SWP (ASHIFT:GPI
>                          (match_operand:GPI 0 "register_operand" "r")
> @@ -7854,14 +7854,23 @@
>
>  (define_expand "isinf<mode>2"
>   [(match_operand:SI 0 "register_operand")
> -  (match_operand:GPF 1 "register_operand")]
> +  (match_operand:GPF_HF_BF 1 "register_operand")]
>   "TARGET_FLOAT"
>  {
> -  rtx op = force_lowpart_subreg (<V_INT_EQUIV>mode, operands[1], <MODE>mode);
> -  rtx tmp = gen_reg_rtx (<V_INT_EQUIV>mode);
> -  emit_move_insn (tmp, GEN_INT (HOST_WIDE_INT_M1U << (<mantissa_bits> + 1)));
> +  scalar_int_mode imode = <V_INT_EQUIV>mode;
> +  rtx op = force_lowpart_subreg (imode, operands[1], <MODE>mode);
> +  /* There is no 16-bit arithmetic, so zero-extend the encoding of the
> +     16-bit formats into a word and shift the sign bit out of the top of
> +     that instead.  */
> +  if (imode == HImode)
> +    imode = SImode;
> +  op = convert_to_mode (imode, op, 1);
> +  int pad = GET_MODE_BITSIZE (imode) - GET_MODE_BITSIZE (<MODE>mode);
> +  rtx tmp = gen_reg_rtx (imode);
> +  emit_move_insn (tmp, gen_int_mode (HOST_WIDE_INT_M1U
> +                                    << (<mantissa_bits> + 1 + pad), imode));
>    rtx cc_reg = gen_rtx_REG (CC_SWPmode, CC_REGNUM);
> -  emit_insn (gen_cmp_swp_lsl_reg<v_int_equiv> (op, GEN_INT (1), tmp));
> +  emit_insn (gen_cmp_swp_reg (ASHIFT, imode, op, GEN_INT (1 + pad), tmp));
>    rtx cmp = gen_rtx_fmt_ee (EQ, SImode, cc_reg, const0_rtx);
>    emit_insn (gen_aarch64_cstoresi (operands[0], cmp, cc_reg));
>    DONE;
> @@ -7870,14 +7879,23 @@
>
>  (define_expand "isfinite<mode>2"
>   [(match_operand:SI 0 "register_operand")
> -  (match_operand:GPF 1 "register_operand")]
> +  (match_operand:GPF_HF_BF 1 "register_operand")]
>   "TARGET_FLOAT"
>  {
> -  rtx op = force_lowpart_subreg (<V_INT_EQUIV>mode, operands[1], <MODE>mode);
> -  rtx tmp = gen_reg_rtx (<V_INT_EQUIV>mode);
> -  emit_move_insn (tmp, GEN_INT (HOST_WIDE_INT_M1U << (<mantissa_bits> + 1)));
> +  scalar_int_mode imode = <V_INT_EQUIV>mode;
> +  rtx op = force_lowpart_subreg (imode, operands[1], <MODE>mode);
> +  /* There is no 16-bit arithmetic, so zero-extend the encoding of the
> +     16-bit formats into a word and shift the sign bit out of the top of
> +     that instead.  */
> +  if (imode == HImode)
> +    imode = SImode;
> +  op = convert_to_mode (imode, op, 1);
> +  int pad = GET_MODE_BITSIZE (imode) - GET_MODE_BITSIZE (<MODE>mode);
> +  rtx tmp = gen_reg_rtx (imode);
> +  emit_move_insn (tmp, gen_int_mode (HOST_WIDE_INT_M1U
> +                                    << (<mantissa_bits> + 1 + pad), imode));
>    rtx cc_reg = gen_rtx_REG (CC_SWPmode, CC_REGNUM);
> -  emit_insn (gen_cmp_swp_lsl_reg<v_int_equiv> (op, GEN_INT (1), tmp));
> +  emit_insn (gen_cmp_swp_reg (ASHIFT, imode, op, GEN_INT (1 + pad), tmp));
>    rtx cmp = gen_rtx_fmt_ee (LTU, SImode, cc_reg, const0_rtx);
>    emit_insn (gen_aarch64_cstoresi (operands[0], cmp, cc_reg));
>    DONE;
> @@ -7886,14 +7904,23 @@
>
>  (define_expand "isnan<mode>2"
>   [(match_operand:SI 0 "register_operand")
> -  (match_operand:GPF 1 "register_operand")]
> +  (match_operand:GPF_HF_BF 1 "register_operand")]
>   "TARGET_FLOAT && flag_signaling_nans"
>  {
> -  rtx op = force_lowpart_subreg (<V_INT_EQUIV>mode, operands[1], <MODE>mode);
> -  rtx tmp = gen_reg_rtx (<V_INT_EQUIV>mode);
> -  emit_move_insn (tmp, GEN_INT (HOST_WIDE_INT_M1U << (<mantissa_bits> + 1)));
> +  scalar_int_mode imode = <V_INT_EQUIV>mode;
> +  rtx op = force_lowpart_subreg (imode, operands[1], <MODE>mode);
> +  /* There is no 16-bit arithmetic, so zero-extend the encoding of the
> +     16-bit formats into a word and shift the sign bit out of the top of
> +     that instead.  */
> +  if (imode == HImode)
> +    imode = SImode;
> +  op = convert_to_mode (imode, op, 1);
> +  int pad = GET_MODE_BITSIZE (imode) - GET_MODE_BITSIZE (<MODE>mode);
> +  rtx tmp = gen_reg_rtx (imode);
> +  emit_move_insn (tmp, gen_int_mode (HOST_WIDE_INT_M1U
> +                                    << (<mantissa_bits> + 1 + pad), imode));
>    rtx cc_reg = gen_rtx_REG (CC_SWPmode, CC_REGNUM);
> -  emit_insn (gen_cmp_swp_lsl_reg<v_int_equiv> (op, GEN_INT (1), tmp));
> +  emit_insn (gen_cmp_swp_reg (ASHIFT, imode, op, GEN_INT (1 + pad), tmp));
>    rtx cmp = gen_rtx_fmt_ee (GTU, SImode, cc_reg, const0_rtx);
>    emit_insn (gen_aarch64_cstoresi (operands[0], cmp, cc_reg));
>    DONE;
> diff --git ./gcc/testsuite/gcc.target/aarch64/pr66462.c 
> ./gcc/testsuite/gcc.target/aarch64/pr66462.c
> index c6367ac16f6..7fa7faf3d73 100644
> --- ./gcc/testsuite/gcc.target/aarch64/pr66462.c
> +++ ./gcc/testsuite/gcc.target/aarch64/pr66462.c
> @@ -98,7 +98,14 @@ static void NAME (TYPE x, bool res)          \
>      __builtin_abort ();                                \
>  }
>
> +DEF_TEST (t_inf16, _Float16, __builtin_isinf)
> +DEF_TEST (t_fin16, _Float16, __builtin_isfinite)
> +DEF_TEST (t_nan16, _Float16, __builtin_isnan)
>  DEF_TEST (t_normal16, _Float16, __builtin_isnormal)
> +
> +DEF_TEST (t_infbf, __bf16, __builtin_isinf)
> +DEF_TEST (t_finbf, __bf16, __builtin_isfinite)
> +DEF_TEST (t_nanbf, __bf16, __builtin_isnan)
>  DEF_TEST (t_normalbf, __bf16, __builtin_isnormal)
>
>  int
> @@ -160,6 +167,40 @@ main ()
>    t_normal (__builtin_nans (""), 0);
>    t_normal (__builtin_nan (""), 0);
>
> +  t_inf16 (1.0f16, 0);
> +  t_inf16 ((_Float16) __builtin_inff (), 1);
> +  t_inf16 (__builtin_nansf16 (""), 0);
> +  t_inf16 (__builtin_nanf16 (""), 0);
> +
> +  t_infbf (1.0bf16, 0);
> +  t_infbf ((__bf16) __builtin_inff (), 1);
> +  t_infbf (__builtin_nansf16b (""), 0);
> +  t_infbf ((__bf16) __builtin_nanf (""), 0);
> +
> +  t_fin16 (0.0f16, 1);
> +  t_fin16 (1.0f16, 1);
> +  t_fin16 ((_Float16) __builtin_inff (), 0);
> +  t_fin16 (__builtin_nansf16 (""), 0);
> +  t_fin16 (__builtin_nanf16 (""), 0);
> +
> +  t_finbf (0.0bf16, 1);
> +  t_finbf (1.0bf16, 1);
> +  t_finbf ((__bf16) __builtin_inff (), 0);
> +  t_finbf (__builtin_nansf16b (""), 0);
> +  t_finbf ((__bf16) __builtin_nanf (""), 0);
> +
> +  t_nan16 (0.0f16, 0);
> +  t_nan16 (1.0f16, 0);
> +  t_nan16 ((_Float16) __builtin_inff (), 0);
> +  t_nan16 (__builtin_nansf16 (""), 1);
> +  t_nan16 (__builtin_nanf16 (""), 1);
> +
> +  t_nanbf (0.0bf16, 0);
> +  t_nanbf (1.0bf16, 0);
> +  t_nanbf ((__bf16) __builtin_inff (), 0);
> +  t_nanbf (__builtin_nansf16b (""), 1);
> +  t_nanbf ((__bf16) __builtin_nanf (""), 1);
> +
>    t_normal16 (0.0f16, 0);
>    t_normal16 (1.0f16, 1);
>    t_normal16 (__FLT16_MIN__, 1);
> --
> 2.54.0
>

Reply via email to