"Dr. Matthias Kretz" <m.kr...@gsi.de> writes:
> On Montag, 27. April 2020 18:59:08 CEST Richard Sandiford wrote:
>> Richard Biener via Gcc-patches <gcc-patches@gcc.gnu.org> writes:
>> > On Mon, Apr 27, 2020 at 6:09 PM Matthias Kretz <m.kr...@gsi.de> wrote:
>> >> Hi,
>> >> 
>> >> This documentation change clarifies the effect of -ffinite-math-only.
>> >> With the current documentation, it is unclear what the presence of NaN
>> >> and Inf representations means if (arithmetic) operations on such values
>> >> are unspecified and even classification functions like isnan are
>> >> unreliable. If the hardware thinks a certain bit pattern is a NaN, but
>> >> the software assumes a NaN value cannot ever exist, it is questionable
>> >> whether, from a language viewpoint, a representation for NaNs really
>> >> exists. Because, a NaN is defined by its behavior. This change also
>> >> clarifies that isnan(nan) returning false is fine.
>> >> 
>> >> This relates to PR84949.
>> >> 
>> >>         * doc/invoke.texi: Clarify the effects of -ffinite-math-only.
>> >> 
>> >> ---
>> >> 
>> >>  gcc/doc/invoke.texi | 6 ++++--
>> >>  1 file changed, 4 insertions(+), 2 deletions(-)
>> >> 
>> >> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
>> >> index a37a2ee9c19..9e76ab057a9 100644
>> >> --- a/gcc/doc/invoke.texi
>> >> +++ b/gcc/doc/invoke.texi
>> >> @@ -11619,8 +11619,10 @@ The default is @option{-fno-reciprocal-math}.
>> >> 
>> >>  @item -ffinite-math-only
>> >>  @opindex ffinite-math-only
>> >> 
>> >> -Allow optimizations for floating-point arithmetic that assume
>> >> -that arguments and results are not NaNs or +-Infs.
>> >> +Assume that floating-point types in the language do not have
>> >> representations for
>> >> +NaNs and +-Inf. Whether floating-point hardware supports and acts on
>> >> NaNs and ++-Inf is not affected. The behavior of a program that uses a
>> >> NaN or +-Inf value
>> >> +as function argument, macro argument, or operand is undefined.
>> > 
>> > Minor nit here - I'd avoid the 'undefined' word which has bad connotation
>> > and use 'unspecified'.  Maybe we can even use ISO C language specification
>> > terms but I'm not sure which one is most appropriate here.
>
> I'm an ISO C++ person, and unspecified sounds too reliable to me:
> https://wg21.link/intro.defs#defns.unspecified.
>
>> > Curiously __builtin_nan ("nan") still gets you a NaN representation
>> > but isnan(__builtin_nan("nan")) is resolved to false.
>
> Right, that's because only the hardware thinks __builtin_nan ("nan") is a NaN 
> representation. With -ffinite-math-only, the double data type in C/C++ can 
> either hold a finite real value, or an invalid value (i.e. a value that the 
> optimizer unconditionally excludes as a possible value for any object of 
> floating-point type). FWIW, with -ffinite-math-only, ubsan should flag 
> isnan(__builtin_nan("nan")) or any f(constexpr nan).
>
> With the above documentation change, it is clear that with https://wg21.link/
> P1841 std::numbers::quiet_NaN<float> would be ill-formed under -ffinite-math-
> only. Without the documentation change, it can be argued either way.
>
> There's another interesting observation resulting from the above: double and 
> double under -ffinite-math-only are different types. Any function call from 
> one world to the other is dangerous. Inline functions translated in different 
> TUs compiled with different math flags violate the ODR. But that's all the 
> more reason to have a very precise documentation/understanding of what 
> -ffinite-math-only does. Because this gotcha is already the status quo.
>  
>> Yeah, for that and other reasons, I think it would be good to avoid
>> giving the impression that -ffinite-math-only can be relied on to make
>> the assumption above.  Wouldn't it be more accurate to say that the
>> compiler is allowed to make the assumption, at any point that it seems
>> convenient?
>
> I think undefined behavior does what you're asking for while unspecified 
> behavior does what you want to avoid. I.e. its an undocumented behavior, but 
> it can be relied on with a given implementation (compiler).

Although it wasn't obvious from my quoting, I was worried more about
the wording of the first "Assume X" sentence than the unspecified vs.
undefined thing.  I think saying "Assume X" loses an important but
correct nuance of the original wording: that completely ignoring the
option would be a valid (if not very useful) implementation.  "Assume X"
instead makes it sound like the compiler is required to do something
(at least to me).

E.g., does making it undefined behaviour mean that:

  constexpr bool e = __builtin_isnan(__builtin_nan("nan"));

must be rejected for -ffinite-math-only, since AIUI constexprs aren't
allowed to invoke UB?  (Sorry if this has already been covered in the
earlier conversation.)

Thanks,
Richard

Reply via email to