https://gcc.gnu.org/g:52330debcdf1fcbb858aa1a07d10c5c286828a97
commit r17-4524-g52330debcdf1fcbb858aa1a07d10c5c286828a97 Author: Matt Turner <[email protected]> Date: Mon Sep 21 07:28:28 2026 -0600 [PATCH 4/5] AArch64: Support HFmode and BFmode in isinf, isfinite and isnan [PR 66462] 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. gcc/testsuite/ChangeLog: PR middle-end/66462 * gcc.target/aarch64/pr66462.c: Add _Float16 and __bf16 tests for isinf, isfinite and isnan. Diff: --- gcc/config/aarch64/aarch64.md | 59 ++++++++++++++++++++++-------- gcc/testsuite/gcc.target/aarch64/pr66462.c | 41 +++++++++++++++++++++ 2 files changed, 84 insertions(+), 16 deletions(-) diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 625c9996348f..40f7e8e2881a 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/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 a/gcc/testsuite/gcc.target/aarch64/pr66462.c b/gcc/testsuite/gcc.target/aarch64/pr66462.c index c6367ac16f68..7fa7faf3d739 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr66462.c +++ b/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);
