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 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? -- Xi Ruoyao <xry...@xry111.site> School of Aerospace Science and Technology, Xidian University