<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Sep 2, 2021 at 2:34 PM 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"><div dir="ltr"><br clear="all"><div><div dir="ltr">On Fri, Sep 3, 2021 at 12:58 AM Sanjay Patel <<a href="mailto:spatel@rotateright.com" target="_blank">spatel@rotateright.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"><div dir="ltr"><div>Thank you for restarting this proposal. It's a bit more work, but let's make sure we have a good design, so we don't miss any details.</div><div><br></div><div><div>What optimizations/analysis does this intrinsic enable **in IR** in strict-FP mode?<br></div><div>If
 it is only constant folding, we don't need to add an intrinsic. We fold
 lots of math library calls with no corresponding LLVM intrinsic under 
llvm::ConstantFoldCall().</div><div>We also do transforms based on operands/uses of library calls in SimplifyLibCalls.</div></div></div></blockquote><div><br></div><div>Optimization is not the motivation for this intrinsic. If FP exceptions are ignored, unordered comparison can be used to implement `isnan`. If not, we need to make the test without affecting FP exceptions. Without this intrinsic there is no way to represent such a test. <br></div></div></div></blockquote><div><br></div><div>Here's a way to represent such a test without an intrinsic:</div><div>declare i1 @isnan(double)</div><div>...<br></div><div>%r = call i1 isnan(double x) #1</div><div>...</div><div>attributes #1 = { nounwind }</div><div><br></div><div>The IR optimizer shouldn't do anything with that call because it might read/write arbitrary memory - assuming I got the (lack of) function attributes correct; let me know if this should be spelled differently. <br></div><div>We can guarantee that an arbitrary call will survive as-is through the entire IR optimizer pipeline since optimization is not the motivation.<br></div><div><br></div><div>I think there's even proof that this already works the way you want because on the clang on macOS, I see:</div><div>#include <math.h>  <br>int a_libcall(double x) {<br>  return isnan(x);<br>}<br></div><div><br></div><div>$ clang -O2 isnan.c -S -emit-llvm -o - -ffast-math</div><div>define i32 @a_libcall(double %0) local_unnamed_addr #1 {<br>  %2 = tail call i32 @__isnand(double %0) #3<br>  ret i32 %2<br>}<br></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"><div dir="ltr"><div class="gmail_quote"><div></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><div><br></div><div>So I'm really asking: why do we translate isnan() in clang into something else in the first place? The backend can lower that call into whatever suits the target without involving LLVM IR.</div></div></div></blockquote><div><br></div><div>It must be a function, known to the backend without declarations/definitions, that is an intrinsic.</div></div></div></blockquote><div><br></div><div>Here's a sqrt() mathlib call in IR that gets simultaneously lowered to both a target-specific instruction AND a libcall on x86:</div><div><a href="https://godbolt.org/z/89xETxK6h" target="_blank">https://godbolt.org/z/89xETxK6h</a></div><div><br></div><div>We can do something like that for isnan() - if the target has an instruction that implements the IEEE/C definition of isnan, use it. Otherwise, make a call to the mathlib.<br></div><div><br></div><div><br></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"><div dir="ltr"><div class="gmail_quote"><div></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><div> <br></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Sep 2, 2021 at 8:33 AM Serge Pavlov via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-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">Hi all,<br><br>Some time ago a new intrinsic `llvm.isnan` was introduced, which was intended to represent IEEE-754 operation `isNaN` as well as a family of C library functions `isnan*`. Then a concern was raised (see  <a href="https://reviews.llvm.org/D104854" target="_blank">https://reviews.llvm.org/D104854</a>) that this functionality should be removed. Discussion in the subsequent RFC (<a href="https://lists.llvm.org/pipermail/llvm-dev/2021-August/152257.html" target="_blank">https://lists.llvm.org/pipermail/llvm-dev/2021-August/152257.html</a>) came to consensus that such intrinsic is necessary. Nevertheless the patches related to the new intrinsic were reverted. I have to restart the discussion in hope to convince the community that this intrinsic and other classification functions are necessary.<br><br>There are two main reasons why this intrinsic is necessary:<br>  1. It allows correct implementation of `isnan` if strict floating point semantics is in effect,<br>       2. It allows preserving the check in -ffast-math compilation.<br><br>To facilitate the discussion let's concentrate on the first problem.<br><br>Previously the frontend intrinsic `__builtin_isnan` was converted into `cmp uno` during IR generation in clang codegen. This solution is not suitable if FP exceptions are not ignored, because compare instructions raise exceptions if its argument is signaling NaN. Both IEEE-754 (5.7.2) an C standard  (<a href="http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf" 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.  There was no target-independent IR construct that could represent `isnan`.<br><br>This drawback was significant enough and some attempts to alleviate it were undertaken. In <a href="https://reviews.llvm.org/D95948" 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" 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>To have a solution suitable for all cases, a new intrinsic function `llvm.isnan` was introduced (<a href="https://reviews.llvm.org/D104854" target="_blank">https://reviews.llvm.org/D104854</a>). It protects the check from undesirable optimizations and preserves it till selector, where it can be lowered in optimal for a particular target way.<br><br>Other classification functions also need their own intrinsics. In strictfp mode even a check for zero (`iszero`) cannot be made by comparing a value against zero, - if the value is signaling NaN, FP exceptions would be raised. James Y Knight in the previous discussion (<a href="https://lists.llvm.org/pipermail/llvm-dev/2021-August/152282.html" target="_blank">https://lists.llvm.org/pipermail/llvm-dev/2021-August/152282.html</a>) listed such "non-computational" functions, which should not signal if provided with an sNAN argument.<br><br>It looks like new intrinsic is the only consistent and in target-agnostic way to implement these checks in all environments including the case when FP exceptions are not ignored.<br><br>Any feedback is welcome.<div><br><div><div dir="ltr">Thanks,<br>--Serge<br></div></div></div></div>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>
</blockquote></div></div>
</blockquote></div></div>