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.
----------------------------------------------------------------------

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

Reply via email to