<div dir="ltr">When codegen lowers this call, it does not know if this is a regular compare and it may create CMP instruction, as for default environment, or this is 'isnan' for which it should generate different code, which does not influence FP state.<div><br></div><div>On most architectures compare instructions change FP state, in default environment it is just ignored, but actually hardware registers can be modified, For 'isnan' instructions must actually leave FP state intact.<br><div><br clear="all"><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">Thanks,<br>--Serge<br></div></div><br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 23, 2021 at 8:43 PM Sanjay Patel <<a href="mailto:spatel@rotateright.com">spatel@rotateright.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">You're saying that the function definition text overrides the argument definition text. Why are we choosing that interpretation rather than the inverse (and documenting it one way or the other)?<br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 23, 2021 at 9:38 AM Serge Pavlov <<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">>
How is this call in LLVM different than the semantics of "isnan(x)" that is required by IEEE-754 or the C standard?<div><br></div><div>If either of the arguments of `llvm.experimental.constrained.fcmp` is signaling NaN, this function should raise an 'Invalid' exception. 'isnan' never raises exceptions.</div><div><br clear="all"><div><div dir="ltr">Thanks,<br>--Serge<br></div></div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 23, 2021 at 8:10 PM Sanjay Patel <<a href="mailto:spatel@rotateright.com" target="_blank">spatel@rotateright.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div>I'm confused about the definition of:</div><div><a href="https://llvm.org/docs/LangRef.html#llvm-experimental-constrained-fcmp-and-llvm-experimental-constrained-fcmps-intrinsics" target="_blank">https://llvm.org/docs/LangRef.html#llvm-experimental-constrained-fcmp-and-llvm-experimental-constrained-fcmps-intrinsics</a></div><div><br></div><div>These
intrinsics require an "exception behavior" argument. That argument can
take the value “fpexcept.ignore” which is defined as:</div><div>"optimization passes may assume that the
exception status flags will not be read and that floating-point exceptions will
be masked"</div><div><br></div><div>i1 @llvm.experimental.constrained.fcmp.f64(double %x, double %x, metadata !"uno", metadata !"fpexcept.ignore")</div><div><br></div><div>How is this call in LLVM different than the semantics of "isnan(x)" that is required by IEEE-754 or the C standard?<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Aug 23, 2021 at 9:00 AM Serge Pavlov via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><br clear="all"><div><div dir="ltr">On Mon, Aug 23, 2021 at 6:12 PM Roman Lebedev <<a href="mailto:lebedev.ri@gmail.com" target="_blank">lebedev.ri@gmail.com</a>> wrote:<br></div></div></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Thank you for posting the RFC!<br>
<br>
I do not believe we should conflate StrictFP support, and<br>
`-ffast-math` handling, these are two separate/separatable concerns.<br></blockquote><div><br></div><div>You are right, they are separate, but they originate from the implementation of the same function and can be solved with the same solution.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
As for the latter, right now i'm not convinced that we should<br>
second-guess/override explicit user request.<br>
This is inconsistent, and does not match how at least the GCC deals with it.<br>
I think changing the status-quo (before said patch) should be a separate RFC,<br>
and that change should be undone until after that RFC is accepted.<br>
<br></blockquote><div> </div><div>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 <a href="https://reviews.llvm.org/D18513#387418" target="_blank">https://reviews.llvm.org/D18513#387418</a>, 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: <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949" target="_blank">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949</a>. Intel and Microsoft compilers do not replace 'isnan' with assumed value.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
As for the latter, the main point of confusion is,<br>
why is `@llvm.isnan` still used in non-StrictFP code?<br></blockquote><div><br></div><div>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.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
The argument that we need `@llvm.isnan` because we *might* transition<br>
in and out of StrictFP section does not seem to hold for me, because<br>
<a href="https://llvm.org/docs/LangRef.html#constrainedfp" rel="noreferrer" target="_blank">https://llvm.org/docs/LangRef.html#constrainedfp</a> says:<br>
<br>
> If any FP operation in a function is constrained then they all must be constrained. This is required for correct LLVM IR.<br></blockquote><div><br></div><div>There was no such intention. The primary motivation was strict fp exceptions.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
So presumably when codegen'ing a function, we already know that we<br>
will use StrictFP ops, and that should be the knob to use `@llvm.isnan`,<br>
i think.<br>
<br>
<br>
Roman<br>
<br>
<br>
<br>
<br>
On Mon, Aug 23, 2021 at 1:57 PM Serge Pavlov via cfe-dev<br>
<<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br>
><br>
> Hi all,<br>
><br>
> 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 <a href="https://reviews.llvm.org/D104854" rel="noreferrer" target="_blank">https://reviews.llvm.org/D104854</a>) that this functionality must have had RFC to make sure there is consensus on semantics.<br>
><br>
> 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.<br>
><br>
> 1. Strict floating-point semantics.<br>
><br>
> 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 (<a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf" rel="noreferrer" target="_blank">http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf</a>, 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 (<a href="https://llvm.org/docs/LangRef.html#id1131" rel="noreferrer" target="_blank">https://llvm.org/docs/LangRef.html#id1131</a>). So there was no target-independent IR construct that could express `isnan`.<br>
><br>
> This drawback was significant enough and some attempts to alleviate it were undertaken. In <a href="https://reviews.llvm.org/D95948" rel="noreferrer" target="_blank">https://reviews.llvm.org/D95948</a> `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 <a href="https://reviews.llvm.org/D96568" rel="noreferrer" target="_blank">https://reviews.llvm.org/D96568</a>, 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.<br>
><br>
> 2. Compilation with -ffast-math<br>
><br>
> 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.<br>
><br>
> 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` (<a href="https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Optimize-Options.html#Optimize-Options" rel="noreferrer" target="_blank">https://gcc.gnu.org/onlinedocs/gcc-11.2.0/gcc/Optimize-Options.html#Optimize-Options</a>):<br>
><br>
> `Allow optimizations for floating-point arithmetic that assume that arguments and results are not NaNs or +-Infs.`<br>
><br>
> `isnan` does not do any arithmetic, only check, so this statement apparently does not apply to it. There is a GCC bug report <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949" rel="noreferrer" target="_blank">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949</a>, where investigation conforms that std::isnan() and std::fpclassify() should works with NaNs as specified even in -ffast-math mode.<br>
><br>
> 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.<br>
><br>
> Intrinsic `llvm.isnan` solves these problems. It<br>
> - represents the check throughout the IR pipeline and saves it from undesired optimizations,<br>
> - is lowered in selector, which can choose the most suitable implementation for particular target,<br>
> - helps keeping IR target-independent,<br>
> - facilitates program analysis as the operation is presented explicitly and is not hidden behind general nodes.<br>
><br>
> 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.<br>
><br>
> Any feedback is welcome.<br>
><br>
> Thanks,<br>
> --Serge<br>
> _______________________________________________<br>
> cfe-dev mailing list<br>
> <a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div></div>
_______________________________________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
</blockquote></div>
</blockquote></div>
</blockquote></div>
</blockquote></div>