From: Wilco Dijkstra Date: Thu, 4 Sep 2025 14:31:16 +0000 (+0000) Subject: AArch64: Add isnan expander [PR 66462] X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b531aa5cc216b5ec4d740940b43ca7a7728cc90;p=thirdparty%2Fgcc.git AArch64: Add isnan expander [PR 66462] Add an expander for isnan using integer arithmetic. Since isnan is just a compare, enable it only with -fsignaling-nans to avoid generating spurious exceptions. This fixes part of PR66462. int isnan1 (float x) { return __builtin_isnan (x); } Before: fcmp s0, s0 cset w0, vs ret After: fmov w1, s0 mov w0, -16777216 cmp w0, w1, lsl 1 cset w0, cc ret gcc: PR middle-end/66462 * config/aarch64/aarch64.md (isnan2): Add new expander. gcc/testsuite: PR middle-end/66462 * gcc.target/aarch64/pr66462.c: Update test. --- diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 6d30226c597..ca612dac600 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -7722,6 +7722,22 @@ } ) +(define_expand "isnan2" + [(match_operand:SI 0 "register_operand") + (match_operand:GPF 1 "register_operand")] + "TARGET_FLOAT && flag_signaling_nans" +{ + rtx op = force_lowpart_subreg (mode, operands[1], mode); + rtx tmp = gen_reg_rtx (mode); + emit_move_insn (tmp, GEN_INT (HOST_WIDE_INT_M1U << ( + 1))); + rtx cc_reg = gen_rtx_REG (CC_SWPmode, CC_REGNUM); + emit_insn (gen_cmp_swp_lsl_reg (op, GEN_INT (1), tmp)); + rtx cmp = gen_rtx_fmt_ee (GTU, SImode, cc_reg, const0_rtx); + emit_insn (gen_aarch64_cstoresi (operands[0], cmp, cc_reg)); + DONE; +} +) + ;; ------------------------------------------------------------------- ;; Reload support ;; ------------------------------------------------------------------- diff --git a/gcc/testsuite/gcc.target/aarch64/pr66462.c b/gcc/testsuite/gcc.target/aarch64/pr66462.c index 476d47c9b19..2bd734b3193 100644 --- a/gcc/testsuite/gcc.target/aarch64/pr66462.c +++ b/gcc/testsuite/gcc.target/aarch64/pr66462.c @@ -44,6 +44,27 @@ static void t_fin (double x, bool res) __builtin_abort (); } +static void t_nanf (float x, bool res) +{ + if (__builtin_isnan (x) != res) + __builtin_abort (); + if (__builtin_isnan (-x) != res) + __builtin_abort (); + if (fetestexcept (FE_INVALID)) + __builtin_abort (); +} + +static void t_nan (double x, bool res) +{ + if (__builtin_isnan (x) != res) + __builtin_abort (); + if (__builtin_isnan (-x) != res) + __builtin_abort (); + if (fetestexcept (FE_INVALID)) + __builtin_abort (); +} + + int main () { @@ -73,5 +94,17 @@ main () t_fin (__builtin_nans (""), 0); t_fin (__builtin_nan (""), 0); + t_nanf (0.0f, 0); + t_nanf (1.0f, 0); + t_nanf (__builtin_inff (), 0); + t_nanf (__builtin_nansf (""), 1); + t_nanf (__builtin_nanf (""), 1); + + t_nan (0.0, 0); + t_nan (1.0, 0); + t_nan (__builtin_inf (), 0); + t_nan (__builtin_nans (""), 1); + t_nan (__builtin_nan (""), 1); + return 0; }