在 2023/11/24 上午10:39, Xi Ruoyao 写道:
On Thu, 2023-11-23 at 18:03 +0000, Joseph Myers wrote:
The rint functions indeed don't set errno (don't have domain or range
errors, at least if you ignore the option for signaling NaNs arguments to
be domain errors - which is in TS 18661-1, but not what glibc does, and
not in C23).

The lrint / llrint functions should logically set errno for a domain error
in the cases where they raise "invalid".  That they don't in glibc is
glibc bug 6798.  And __builtin_irint functions can fall back to calling
lrint functions if not expanded inline.  So the potential for errno
setting explains why -fno-math-errno is required.
I agree.  But this is not preventing optimizing vectorized "(int)
rintf(x[i])" into a vftint.w.s instruction which does not set errno.

I'm sorry. Please forgive my stupidity. I don't see a description in TS 18661-1 that explicitly

says rint does not set errno.

I only saw lrint llrint in n2310 with this description:

F7.12.9.5

"The lrint and llrint functions round their argument to the nearest integer value, rounding according to the current rounding direction. If the rounded value is outside the range of the return type, the numeric result is unspecified and a domain error or range error may occur."

I don't know if I'm right?




I don't see an obvious need for -funsafe-math-optimizations here - but at
least -fno-trapping-math should be needed in some cases.  That's because
rint raises "inexact" for noninteger argument - but lrint doesn't raise
"inexact" when raising "invalid".  So if, for example, long is 32-bit and
the floating type in use is double, calling rint for a noninteger argument
too large for long, and then converting to a 32-bit signed integer type
(long or int), raises both "inexact" and "invalid" - but a direct call to
lrint raises such "invalid".
Interesting...  But for (i32)rintf(x) it's impossible to have a non-
integer value out of [-2147483648, 2147483648) except NaN and +-Inf,
likewise for (i64)rint(x).  So using vftint.w.s and vftint.l.d
instructions should still be fine.  We also have a vftint.w.d
instruction but it's only used as an intrinsic as at now, and my patch
does not attempt to use it.

Lulu: so my conclusion is an (i32)rintf -> irintf transformation is
indeed "unsafe" generally, but a machine-specific transformation to
vftint.w.s is fine and we should use the define_insn to do it.  Do you
agree?


Reply via email to