Add an expander for isfinite using integer arithmetic.  This is
typically faster and avoids generating spurious exceptions on 
signaling NaNs.  This fixes part of PR66462.

int isfinite1 (float x) { return __builtin_isfinite (x); }

Before:
        fabs    s0, s0
        mov     w0, 2139095039
        fmov    s31, w0
        fcmp    s0, s31
        cset    w0, hi
        eor     w0, w0, 1
        ret

After:
        fmov    w1, s0
        mov     w0, -16777216
        cmp     w0, w1, lsl 1
        cset    w0, hi
        ret

gcc:
        PR middle-end/66462
        * config/aarch64/aarch64.md (isfinite<mode>2): Add new expander.

testsuite:
        PR middle-end/66462
        * gcc.target/aarch64/pr66462.c: Add tests for isfinite.

---

diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 
d3bf85d1b67b6b777346fbd9a93f59cdc95f53ca..c11db4a51166f70dd3c9e0e09cca838498254fec
 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -7732,6 +7732,22 @@ (define_expand "isinf<mode>2"
 }
 )
 
+(define_expand "isfinite<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 (LTU, 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 
9ebd48e922c95cfbccbe65987572b5c1c079bc8c..476d47c9b1928447da2042003135f21cbf795633
 100644
--- a/gcc/testsuite/gcc.target/aarch64/pr66462.c
+++ b/gcc/testsuite/gcc.target/aarch64/pr66462.c
@@ -24,6 +24,26 @@ static void t_inf (double x, bool res)
     __builtin_abort ();
 }
 
+static void t_finf (float x, bool res)
+{
+  if (__builtin_isfinite (x) != res)
+    __builtin_abort ();
+  if (__builtin_isfinite (-x) != res)
+    __builtin_abort ();
+  if (fetestexcept (FE_INVALID))
+    __builtin_abort ();
+}
+
+static void t_fin (double x, bool res)
+{
+  if (__builtin_isfinite (x) != res)
+    __builtin_abort ();
+  if (__builtin_isfinite (-x) != res)
+    __builtin_abort ();
+  if (fetestexcept (FE_INVALID))
+    __builtin_abort ();
+}
+
 int
 main ()
 {
@@ -41,5 +61,17 @@ main ()
   t_inf (__builtin_nans (""), 0);
   t_inf (__builtin_nan (""), 0);
 
+  t_finf (0.0f, 1);
+  t_finf (1.0f, 1);
+  t_finf (__builtin_inff (), 0);
+  t_finf (__builtin_nansf (""), 0);
+  t_finf (__builtin_nanf (""), 0);
+
+  t_fin (0.0, 1);
+  t_fin (1.0, 1);
+  t_fin (__builtin_inf (), 0);
+  t_fin (__builtin_nans (""), 0);
+  t_fin (__builtin_nan (""), 0);
+
   return 0;
 }

Reply via email to