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