[llvm-dev] [cfe-dev] Intrinsic llvm::isnan

Serge Pavlov via llvm-dev llvm-dev at lists.llvm.org
Mon Aug 23 06:38:09 PDT 2021


> How is this call in LLVM different than the semantics of "isnan(x)" that
is required by IEEE-754 or the C standard?

If either of the arguments of `llvm.experimental.constrained.fcmp` is
signaling NaN, this function should raise an 'Invalid' exception. 'isnan'
never raises exceptions.

Thanks,
--Serge


On Mon, Aug 23, 2021 at 8:10 PM Sanjay Patel <spatel at rotateright.com> wrote:

> I'm confused about the definition of:
>
> https://llvm.org/docs/LangRef.html#llvm-experimental-constrained-fcmp-and-llvm-experimental-constrained-fcmps-intrinsics
>
> These intrinsics require an "exception behavior" argument. That argument
> can take the value “fpexcept.ignore” which is defined as:
> "optimization passes may assume that the exception status flags will not
> be read and that floating-point exceptions will be masked"
>
> i1 @llvm.experimental.constrained.fcmp.f64(double %x, double %x, metadata
> !"uno", metadata !"fpexcept.ignore")
>
> How is this call in LLVM different than the semantics of "isnan(x)" that
> is required by IEEE-754 or the C standard?
>
> On Mon, Aug 23, 2021 at 9:00 AM Serge Pavlov via cfe-dev <
> cfe-dev at lists.llvm.org> wrote:
>
>>
>> On Mon, Aug 23, 2021 at 6:12 PM Roman Lebedev <lebedev.ri at gmail.com>
>> wrote:
>>
>>> Thank you for posting the RFC!
>>>
>>> I do not believe we should conflate StrictFP support, and
>>> `-ffast-math` handling, these are two separate/separatable concerns.
>>>
>>
>> You are right, they are separate, but they originate from the
>> implementation of the same function and can be solved with the same
>> solution.
>>
>>
>>>
>>> As for the latter, right now i'm not convinced that we should
>>> second-guess/override explicit user request.
>>> This is inconsistent, and does not match how at least the GCC deals with
>>> it.
>>> I think changing the status-quo (before said patch) should be a separate
>>> RFC,
>>> and that change should be undone until after that RFC is accepted.
>>>
>>>
>> Actually we have two explicit user requests, a call of 'isnan' and an
>> option '-ffast-math'. IMHO they do not contradict each other as 'isnan' is
>> not an arithmetic operation. There is a discussion in
>> https://reviews.llvm.org/D18513#387418, which also expresses the opinion
>> that limitations imposed by '-ffast-math' should be applied only to 'math'
>> functions but not to 'tests'. As for GCC behavior, they agree that this
>> behavior is a bag: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949.
>> Intel and Microsoft compilers do not replace 'isnan' with assumed value.
>>
>>
>>> As for the latter, the main point of confusion is,
>>> why is `@llvm.isnan` still used in non-StrictFP code?
>>>
>>
>> We have to introduce an intrinsic to represent `isnan` in strictfp
>> environment. It is natural to use it for the default environment as
>> well. Besides, a target may have a more efficient way to represent `isnan`
>> than unordered comparison.
>>
>> The argument that we need `@llvm.isnan` because we *might* transition
>>> in and out of StrictFP section does not seem to hold for me, because
>>> https://llvm.org/docs/LangRef.html#constrainedfp says:
>>>
>>> > If any FP operation in a function is constrained then they all must be
>>> constrained. This is required for correct LLVM IR.
>>>
>>
>> There was no such intention. The primary motivation was strict fp
>> exceptions.
>>
>>
>>> So presumably when codegen'ing a function, we already know that we
>>> will use StrictFP ops, and that should be the knob to use `@llvm.isnan`,
>>> i think.
>>>
>>>
>>> Roman
>>>
>>>
>>>
>>>
>>> On Mon, Aug 23, 2021 at 1:57 PM Serge Pavlov via cfe-dev
>>> <cfe-dev at lists.llvm.org> wrote:
>>> >
>>> > Hi all,
>>> >
>>> > Some time ago a new intrinsic `llvm.isnan` was introduced, which is
>>> intended to represent IEEE-754 operation `isNaN` as well as a family of C
>>> library functions `isnan*`. Recently during post-commit review concern was
>>> raised (see  https://reviews.llvm.org/D104854) that this functionality
>>> must have had RFC to make sure there is consensus on semantics.
>>> >
>>> > Previously the frontend intrinsic `__builtin_isnan` was converted into
>>> `cmp uno` during IR generation in clang codegen. There are two main reasons
>>> why this solution is not satisfactory.
>>> >
>>> > 1.  Strict floating-point semantics.
>>> >
>>> > If FP exceptions are not ignored, `cmp uno` must be replaced with its
>>> constrained counterpart, namely `llvm.experimental.constrained.fcmp` or
>>> `llvm.experimental.constrained.fcmps`. None of them is compatible with the
>>> semantics of `isnan`. Both IEEE-754 (5.7.2) an C standard  (
>>> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf, F.3p6)
>>> demand that this function does not raise floating point exceptions. Both
>>> the constrained compare intrinsics raise an exception if either operand is
>>> a SNAN (https://llvm.org/docs/LangRef.html#id1131). So there was no
>>> target-independent IR construct that could express `isnan`.
>>> >
>>> > This drawback was significant enough and some attempts to alleviate it
>>> were undertaken. In https://reviews.llvm.org/D95948 `isnan` was
>>> implemented using integer operations in strictfp functions. It however is
>>> not suitable for targets where a more efficient way exists, like dedicated
>>> instruction. Another solution was implemented in
>>> https://reviews.llvm.org/D96568, where a hook
>>> 'clang::TargetCodeGenInfo::testFPKind' was introduced, which injects target
>>> specific code into IR. Such a solution makes IR more target-dependent and
>>> prevents some IR-level optimizations.
>>> >
>>> > 2. Compilation with -ffast-math
>>> >
>>> > The option '-ffast-math' is often used for performance critical code,
>>> as it can produce faster code. In this case the user must ensure that NaNs
>>> are not used as operand values. `isnan` is just proposed for such checks,
>>> but it was unusable when `isnan` was represented by compare instruction,
>>> because the latter may be optimized out. One of use cases is data in
>>> memory, which is processed by a function compiled with `-ffast-math`. Some
>>> items in the data are NaNs to denote absence of values.
>>> >
>>> > This point requires some remarks about using NaNs when a function is
>>> compiled with `-ffast-math`. GCC manual does not specify how this option
>>> works, it only states about `-ffinite-math-only` (
>>> https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Optimize-Options.html#Optimize-Options
>>> ):
>>> >
>>> > `Allow optimizations for floating-point arithmetic that assume that
>>> arguments and results are not NaNs or +-Infs.`
>>> >
>>> > `isnan` does not do any arithmetic, only check, so this statement
>>> apparently does not apply to it. There is a GCC bug report
>>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949, where investigation
>>> conforms that std::isnan() and std::fpclassify() should works with NaNs as
>>> specified even in -ffast-math mode.
>>> >
>>> > Extending NaN restrictions in -ffast-math mode to functions like
>>> `isnan` does not make code faster, but is a source of broken user
>>> expectations. If a user writes `isnan` they usually expect an actual check.
>>> Silently removing the check is a stronger action than assuming that float
>>> value contains only real numbers.
>>> >
>>> > Intrinsic `llvm.isnan` solves these problems. It
>>> > - represents the check throughout the IR pipeline and saves it from
>>> undesired optimizations,
>>> > - is lowered in selector, which can choose the most suitable
>>> implementation for particular target,
>>> > - helps keeping IR target-independent,
>>> > - facilitates program analysis as the operation is presented
>>> explicitly and is not hidden behind general nodes.
>>> >
>>> > Note that `llvm.isnan` is optimized out if its argument is an
>>> operation with `nnan` flag, this behavior agrees with the definition of
>>> this flag in LLVM documentation.
>>> >
>>> > Any feedback is welcome.
>>> >
>>> > Thanks,
>>> > --Serge
>>> > _______________________________________________
>>> > cfe-dev mailing list
>>> > cfe-dev at lists.llvm.org
>>> > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>>
>> _______________________________________________
>> cfe-dev mailing list
>> cfe-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20210823/cd2c6a08/attachment.html>


More information about the llvm-dev mailing list