[RFC] Clarify -ffinite-math-only documentation

Richard Biener richard.guenther@gmail.com
Tue Apr 28 13:09:22 GMT 2020


On Tue, Apr 28, 2020 at 12:04 PM Richard Sandiford
<richard.sandiford@arm.com> wrote:
>
> Matthias Kretz <m.kretz@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.kretz@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


More information about the Gcc-patches mailing list