On Wed, Sep 16, 2026 at 5:14 AM Matt Turner <[email protected]> wrote:
>
> Add an expander for isnormal using integer arithmetic. This is
> typically faster and avoids generating spurious exceptions on
> signaling NaNs. This fixes part of PR66462.
>
> int isnormal1 (float x) { return __builtin_isnormal (x); }
>
> Before:
> fabs s0, s0
> mov w0, 2139095039
> fmov s31, w0
> fcmp s0, s31
> movi v31.2s, 0x80, lsl 16
> fccmp s0, s31, 1, ls
> cset w0, lt
> eor w0, w0, 1
> ret
>
> After:
> fmov w0, s0
> ubfx w0, w0, 23, 8
> sub w0, w0, #1
> cmp w0, 254
> cset w0, cc
> ret
>
> gcc/ChangeLog:
>
> PR middle-end/66462
> * config/aarch64/aarch64.md (isnormal<mode>2): Add new expander.
>
> gcc/testsuite/ChangeLog:
>
> PR middle-end/66462
> * gcc.target/aarch64/pr66462.c: Add tests for isnormal.
> ---
> gcc/config/aarch64/aarch64.md | 24 ++++++++++++++
> gcc/testsuite/gcc.target/aarch64/pr66462.c | 38 ++++++++++++++++++++++
> 2 files changed, 62 insertions(+)
>
> diff --git ./gcc/config/aarch64/aarch64.md ./gcc/config/aarch64/aarch64.md
> index 4ae5c074cd1..bf7dc993d56 100644
> --- ./gcc/config/aarch64/aarch64.md
> +++ ./gcc/config/aarch64/aarch64.md
> @@ -7900,6 +7900,30 @@
> }
> )
>
> +;; A number is normal iff its exponent field E is neither 0 nor all ones,
> +;; i.e. (unsigned) (E - 1) < EXP_MAX - 1.
> +(define_expand "isnormal<mode>2"
> + [(match_operand:SI 0 "register_operand")
> + (match_operand:GPF 1 "register_operand")]
> + "TARGET_FLOAT"
> +{
> + machine_mode imode = <V_INT_EQUIV>mode;
> + int exp_bits = GET_MODE_BITSIZE (<MODE>mode) - <mantissa_bits> - 1;
> + HOST_WIDE_INT exp_max = (HOST_WIDE_INT_1 << exp_bits) - 1;
> + rtx op = force_lowpart_subreg (imode, operands[1], <MODE>mode);
> + op = expand_simple_binop (imode, LSHIFTRT, op, GEN_INT (<mantissa_bits>),
> + NULL_RTX, 1, OPTAB_DIRECT);
> + op = expand_simple_binop (imode, AND, op, GEN_INT (exp_max),
> + NULL_RTX, 1, OPTAB_DIRECT);
> + op = expand_simple_binop (imode, PLUS, op, constm1_rtx,
> + NULL_RTX, 1, OPTAB_DIRECT);
> + rtx cc_reg = aarch64_gen_compare_reg (LTU, op, GEN_INT (exp_max - 1));
> + rtx cmp = gen_rtx_fmt_ee (LTU, SImode, cc_reg, const0_rtx);
> + emit_insn (gen_aarch64_cstoresi (operands[0], cmp, cc_reg));
> + DONE;
> +}
> +)
Oh I missed in my review this does not support HFmode. Though I don't
expect you to fix that. But it would be useful to add support for
_Float16 too.
It would also be useful to add support for BFmode too.
> +
> ;; -------------------------------------------------------------------
> ;; Reload support
> ;; -------------------------------------------------------------------
> diff --git ./gcc/testsuite/gcc.target/aarch64/pr66462.c
> ./gcc/testsuite/gcc.target/aarch64/pr66462.c
> index 2bd734b3193..b5f719bf2d8 100644
> --- ./gcc/testsuite/gcc.target/aarch64/pr66462.c
> +++ ./gcc/testsuite/gcc.target/aarch64/pr66462.c
> @@ -64,6 +64,26 @@ static void t_nan (double x, bool res)
> __builtin_abort ();
> }
>
> +static void t_normalf (float x, bool res)
> +{
> + if (__builtin_isnormal (x) != res)
> + __builtin_abort ();
> + if (__builtin_isnormal (-x) != res)
> + __builtin_abort ();
> + if (fetestexcept (FE_INVALID))
> + __builtin_abort ();
> +}
> +
> +static void t_normal (double x, bool res)
> +{
> + if (__builtin_isnormal (x) != res)
> + __builtin_abort ();
> + if (__builtin_isnormal (-x) != res)
> + __builtin_abort ();
> + if (fetestexcept (FE_INVALID))
> + __builtin_abort ();
> +}
> +
>
> int
> main ()
> @@ -106,5 +126,23 @@ main ()
> t_nan (__builtin_nans (""), 1);
> t_nan (__builtin_nan (""), 1);
>
> + t_normalf (0.0f, 0);
> + t_normalf (1.0f, 1);
> + t_normalf (__FLT_MIN__, 1);
> + t_normalf (__FLT_MAX__, 1);
> + t_normalf (__FLT_DENORM_MIN__, 0);
> + t_normalf (__builtin_inff (), 0);
> + t_normalf (__builtin_nansf (""), 0);
> + t_normalf (__builtin_nanf (""), 0);
> +
> + t_normal (0.0, 0);
> + t_normal (1.0, 1);
> + t_normal (__DBL_MIN__, 1);
> + t_normal (__DBL_MAX__, 1);
> + t_normal (__DBL_DENORM_MIN__, 0);
> + t_normal (__builtin_inf (), 0);
> + t_normal (__builtin_nans (""), 0);
> + t_normal (__builtin_nan (""), 0);
> +
> return 0;
> }
> --
> 2.54.0
>