On Tue, Apr 28, 2020 at 12:04 PM Richard Sandiford <richard.sandif...@arm.com> wrote: > > Matthias Kretz <m.kr...@gsi.de> writes: > > On Dienstag, 28. April 2020 09:21:38 CEST Richard Biener wrote: > >> On Mon, Apr 27, 2020 at 11:26 PM Matthias Kretz <m.kr...@gsi.de> wrote: > >> > * Why not disable NaN and Inf independently? Inf is just a reciprocal 0. > >> > Inf is as far away from numeric_limits::max as 0 is from > >> > numeric_limits::min (infinitely many steps on a floating-point "type" > >> > with infinite exponent). > >> > >> Just a comment on the last point - internally it's already split into > >> HONOR_NANS and HONOR_INFINITIES that there's just > >> a single user-facing option -ffinite-math-only is historical (IMHO more > >> options are more opportunities for users to get confused ;)). > >> > >> Maybe also interesting to the discussion the internal comments say > >> > >> /* True if the given mode has a NaN representation and the treatment of > >> NaN operands is important. Certain optimizations, such as folding > >> x * 0 into 0, are not correct for NaN operands, and are normally > >> disabled for modes with NaNs. The user can ask for them to be > >> done anyway using the -funsafe-math-optimizations switch. */ > >> extern bool HONOR_NANS (machine_mode); > >> [...] > >> note how the comment says "treatment of NaN operands is important" > > > > ... if HONOR_NANS(mode) == true. So with -ffinite-math-only that implies > > "treatment of NaN operands is not important", right? > > > >> and the example of simplifying x * 0 to 0 is about preserving NaNs > >> during expression simplification when the FPU would. > > > > Yes, the `nan * 0 -> 0` simplification with -ffinite-math-only is why I'm > > saying the status quo already has no NaN representation *in C/C++* anymore. > > Because a float with NaN bits doesn't behave like C17 5.2.4.2.2/4 requires. > > And thus it's an invalid/unspecified/undefined value, not a NaN. If there > > are > > no NaNs (as defined by C), then there is no NaN representation and > > __FLT_HAS_QUIET_NAN__ must be 0. > > > >> I think these > >> kind of optimizations are what originally was intended to be allowed > >> with -ffinite-math-only - that we started to simplify isnan(x) to false > >> was extending the scope and that change wasn't uncontested since > >> it makes -ffinite-math-only less useful to some people. > > > > I understand and agree with this point. However I think the problem with the > > current -ffinite-math-only is that it doesn't do enough. I.e. it's a > > dangerous > > optimization for people who rely on nan+inf in some way. But in many cases > > people don't realize they do, and it may be a latent issue that turns into a > > bug on unrelated code changes (or compiler changes). By going all the way, > > aggressively optimizing assuming there can't ever be nan/inf in the program, > > making the use of inf/nan ill-formed NDR, and integrating with ubsan, I > > think > > the option becomes less dangerous and more useful. That would be a bold > > move, > > certainly. > > I think I understand your position, but what about options like > -fassociative-math: > > ---------------------------------------------------------------------- > Allow re-association of operands in series of floating-point operations. > This violates the ISO C and C++ language standard by possibly changing > computation result. NOTE: re-ordering may change the sign of zero as > well as ignore NaNs and inhibit or create underflow or overflow (and > thus cannot be used on code that relies on rounding behavior like > @code{(x + 2**52) - 2**52}. May also reorder floating-point comparisons > and thus may not be used when ordered comparisons are required. > This option requires that both @option{-fno-signed-zeros} and > @option{-fno-trapping-math} be in effect. Moreover, it doesn't make > much sense with @option{-frounding-math}. For Fortran the option > is automatically enabled when both @option{-fno-signed-zeros} and > @option{-fno-trapping-math} are in effect. > ----------------------------------------------------------------------
Just to add some additional information - this option (like a few others) was added in the attempt to decompose the kitchen-sink -funsafe-math-optimizations into more specific bits based on the kind of transforms they allow. That is in contrast to the set of options trying to enable/disable certain parts of the IEEE specs. But of course both sets interact and certain combinations of options do not make sense (some are rejected and some options enable/disable other options automatically). Overall it's quite a mess ;) Usually I advocate an all-or-nothing approach - if -ffast-math works for you use it, otherwise don't try to be "clever" with any of the more specific flags. > The point about NaN handling doesn't seem obviously different from the > X * 0 -> 0 case. But on its own, -fassociative-math doesn't give us > the freedom to make __builtin_isnan always return false. I.e. with > -fassociative-math on its own, NaNs definitely still exist, but don't > always behave as the standard says they should. > > I think the spirit of the two options was supposed to be the same. > We're deliberately setting aside normal language rules rather than > working within the framework of the standard. So in that sense, what > the standard says about __FLT_HAS_QUIET_NAN__ isn't necessarily binding. > It can just be another rule that we're setting aside. The same goes > for the numeric_limits question: I think the fact that it can currently > be argued both ways is an accurate reflection of how the option was > supposed to “work”. > > In other words, we're leaving the standard behind, so trying to define > how the option works in terms of the standard isn't necessarily meaningful. > I realise that isn't very elegant from a language definition POV though... > > This sound similar to the situation Richard Smith was trying to avoid > (in the context of initialisation) in: > > http://lists.llvm.org/pipermail/cfe-dev/2020-April/065223.html > > Maybe the same principle should apply here: if we want a version of > -ffinite-math-only that's well-behaved in language terms (including > in terms of the macros that are defined and in the values of > numeric_limits), perhaps this should be an official (optional) C/C++ > extension that defines what the rules are. There'd then also be > more chance of GCC, clang and other compilers implementing it in > a consistent way. > > Thanks, > Richard