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;
+}

Reply via email to