v2: Add testcase Add an expander for isinf using integer arithmetic. This is typically faster and avoids generating spurious exceptions on signaling NaNs. This fixes part of PR66462.
int isinf1 (float x) { return __builtin_isinf (x); } Before: fabs s0, s0 mov w0, 2139095039 fmov s31, w0 fcmp s0, s31 cset w0, le eor w0, w0, 1 ret After: fmov w1, s0 mov w0, -16777216 cmp w0, w1, lsl 1 cset w0, eq ret gcc: PR middle-end/66462 * config/aarch64/aarch64.md (isinf<mode>2): Add new expander. * config/aarch64/iterators.md (mantissa_bits): Add new mode_attr. testsuite: PR middle-end/66462 * gcc.target/aarch64/pr66462.c: Add new test. --- diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index dc2be815ede6829aa6f8b1f435754c3e98fa5c12..d3bf85d1b67b6b777346fbd9a93f59cdc95f53ca 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -4524,7 +4524,7 @@ (define_insn "fcmpe<mode>" [(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") @@ -7716,6 +7716,22 @@ (define_expand "@xorsign<mode>3" } ) +(define_expand "isinf<mode>2" + [(match_operand:SI 0 "register_operand") + (match_operand:GPF 1 "register_operand")] + "TARGET_FLOAT" +{ + rtx op = 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))); + 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)); + rtx cmp = gen_rtx_fmt_ee (EQ, SImode, cc_reg, const0_rtx); + emit_insn (gen_aarch64_cstoresi (operands[0], cmp, cc_reg)); + DONE; +} +) + ;; ------------------------------------------------------------------- ;; Reload support ;; ------------------------------------------------------------------- diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md index 8f8237edf6cb07f80beaa5dcf7a7330b06fed3c9..8fea19469baeaf12a3a8acfad11589084c8c4301 100644 --- a/gcc/config/aarch64/iterators.md +++ b/gcc/config/aarch64/iterators.md @@ -1334,6 +1334,8 @@ (define_mode_attr short_mask [(HI "65535") (QI "255")]) (define_mode_attr half_mask [(HI "255") (SI "65535") (DI "4294967295")]) +(define_mode_attr mantissa_bits [(SF "23") (DF "52")]) + ;; For constraints used in scalar immediate vector moves (define_mode_attr hq [(HI "h") (QI "q")]) diff --git a/gcc/testsuite/gcc.target/aarch64/pr66462.c b/gcc/testsuite/gcc.target/aarch64/pr66462.c new file mode 100644 index 0000000000000000000000000000000000000000..9ebd48e922c95cfbccbe65987572b5c1c079bc8c --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr66462.c @@ -0,0 +1,45 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fsignaling-nans -fno-inline" } */ +/* { dg-require-effective-target fenv_exceptions } */ + +#include <fenv.h> + +static void t_inff (float x, bool res) +{ + if (__builtin_isinff (x) != res) + __builtin_abort (); + if (__builtin_isinff (-x) != res) + __builtin_abort (); + if (fetestexcept (FE_INVALID)) + __builtin_abort (); +} + +static void t_inf (double x, bool res) +{ + if (__builtin_isinf (x) != res) + __builtin_abort (); + if (__builtin_isinf (-x) != res) + __builtin_abort (); + if (fetestexcept (FE_INVALID)) + __builtin_abort (); +} + +int +main () +{ + feclearexcept (FE_INVALID); + + t_inff (0.0f, 0); + t_inff (1.0f, 0); + t_inff (__builtin_inff (), 1); + t_inff (__builtin_nansf (""), 0); + t_inff (__builtin_nanf (""), 0); + + t_inf (0.0, 0); + t_inf (1.0, 0); + t_inf (__builtin_inf (), 1); + t_inf (__builtin_nans (""), 0); + t_inf (__builtin_nan (""), 0); + + return 0; +}