On Mon, 15 Aug 2022, Jakub Jelinek wrote: > On Mon, Aug 15, 2022 at 11:24:14AM +0000, Richard Biener wrote: > > Unlike the issignalling macro from glibc the builtin will return > > false for sNaN arguments when -fno-signalling-nans is used (similar > > to isinf, isnan, etc.). I think this deserves mentioning in the > > documentation (and I have my reservations about this long-time > > behavior of FP classification builtins we have). > > I have actually tried to make the builtin working even with > -fno-signaling-nans (i.e. the default). > That is why the folding is done only if the argument is REAL_CST > or if !tree_expr_maybe_nan_p (arg). > At one point I was doing the folding when > tree_expr_signaling_nan_p (arg) (to true) or > !tree_expr_maybe_signaling_nan_p (arg) (to false) and in that > case indeed -fsignaling-nans was a requirement. > -fsignaling-nans is used in the tests nevertheless because the > tests really do care about sNaNs, so I've turned on the option > that says they should be honored.
Ah, I misread +static rtx +expand_builtin_issignaling (tree exp, rtx target) +{ + if (!validate_arglist (exp, REAL_TYPE, VOID_TYPE)) + return NULL_RTX; + + tree arg = CALL_EXPR_ARG (exp, 0); + scalar_float_mode fmode = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (arg)); + const struct real_format *fmt = REAL_MODE_FORMAT (fmode); + + /* Expand the argument yielding a RTX expression. */ + rtx temp = expand_normal (arg); + + /* If mode doesn't support NaN, always return 0. */ + if (!HONOR_NANS (fmode)) + { + emit_move_insn (target, const0_rtx); + return target; which doesn't use HONOR_SNANS but still HONOR_NANS and thus -ffinite-math-only. You possibly want MODE_HAS_NANS instead here? > > Generally it looks OK - what does it do to size optimized code? > > The problem is that except for the glibc __issignaling{f,,l,f128} > entrypoints, other C libraries don't implement it, so there is nothing to > fallback to (unless we want to also implement it in libgcc.a). > > For float/double, it is relatively short: > movd %xmm0, %eax > xorl $4194304, %eax > andl $2147483647, %eax > cmpl $2143289344, %eax > seta %al > movzbl %al, %eax > which e.g. for if (__builtin_issignaling (arg)) could be even simplified > further by just doing ja or jna, resp. > movabsq $9221120237041090560, %rdx > movq %xmm0, %rax > btcq $51, %rax > btrq $63, %rax > cmpq %rax, %rdx > setb %al > movzbl %al, %eax > For long double (especially Intel) / _Float128 it is larger (26 insns for > XFmode, > 15 for _Float128), sure. > > > glibc 2.31 seems to silently accept > > > > #include <tgmath.h> > > > > int foo(_Complex double x) > > { > > return issignaling (x); > > } > > That seems like a glibc bug/weird feature in the __MATH_TG macro > or _Generic. > When compiled with C++ it is rejected. So what about __builtin_issignaling then? Do we want to silently ignore errors there? Richard.