[llvm-dev] [cfe-dev] Should isnan be optimized out in fast-math mode?

Serge Pavlov via llvm-dev llvm-dev at lists.llvm.org
Tue Sep 21 06:05:08 PDT 2021


On Tue, Sep 21, 2021 at 3:46 AM antlists via llvm-dev <
llvm-dev at lists.llvm.org> wrote:

> I know I may be coming in at half cock, but what is the CORRECT
> MATHEMATICAL behaviour?


I'll use your question to make a summary.

 Now clang removes calls to `isnan` in -ffinite-math-only. The
justification for such behavior comes from early GCC viewpoint (
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724#c1):

"With -ffinite-math-only you are telling that there are no NaNs"

On this assumption the removal of `isnan` is a perfectly valid
optimization, it produces a program that behaves identically to the initial
program, which contains `isnan`. For all valid input data it produces  the
same output.

Actually the existence of NaNs cannot be ignored even if no operations on
NaNs take place. There are several reasons for that, at least:
- Users need  to check the input data, for example to assert, or to choose
a slower but general path.
- NaN can be used as a sentinel. In this case it is actually not a number
but some distinguishable bit pattern.
- NaNs can be produced by operations on "allowed" numbers. It is easier to
demonstrate on infinities. The expression `x * y` may produce infinity when
its operands are finite numbers and it is hard to reveal that without
execution of the operation.
- Code compiled with `-ffinite-math-only` may call functions from libraries
or from other parts of the program, compiled without this flag. These
functions may return infinities and NaNs. It is often impractical to check
the arguments prior to the call to ensure the result would be finite. In
some cases it is even impossible. In this case it is necessary to check if
the result is finite.

The "correct behavior" depends on whether NaNs are allowed in the code
compiled with -ffinite-math-only:
- if no, we have the current behavior,
- if yes, `isnan` cannot be optimized out.

The approach "-ffinite-math-only means there are no NaNs" is an abstraction
that does not fit user needs. This problem is actually common. There are
many user feedbacks, in GCC bug tracker:
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949
as well as in forums:
-
https://stackoverflow.com/questions/38978951/can-ffast-math-be-safely-used-on-a-typical-project
-
https://stackoverflow.com/questions/47703436/isnan-does-not-work-correctly-with-ofast-flags
To support `isnan` with -ffinite-math-only users have to use kludges like
emulating `isnan` with integer arithmetic, calling libs implementation or
moving their own `isnan` implementation to separate translation units. All
of them have drawbacks and bring loss in portability and performance.

The proposal was to support the programming model, anticipated by many
users. Advantages and risks were discussed in the thread previously.

Thanks,
--Serge
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210921/4b29d5f3/attachment.html>


More information about the llvm-dev mailing list