<div dir="ltr"><div dir="ltr">On Thu, 9 Sept 2021 at 13:55, Chris Tetreault via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></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 lang="EN-US" style="overflow-wrap: break-word;">
<div class="gmail-m_-6837852578495190315WordSection1">
<p class="MsoNormal">The point I was trying to make regarding the C++ standard is that fast-math is a non-standard language extension.</p></div></div></blockquote><div><br></div><div>-ffinite-math-only does not need to be a non-standard language extension. Neither C nor C++ requires that floating-point types can represent infinity or NaN, and we could define this flag as meaning that there are (notionally) simply no such values in the relevant types. Of course, that's not actually consistent with what we currently do, nor with what GCC does.</div><div><br></div><div>Would it be reasonable to treat operations on Inf and NaN values as UB in this mode only if the same operation on a signaling NaN might signal? (Approximately, that'd mean we imagine these non-finite value encodings all encode sNaNs that are UB if they would signal.) That means the operations that ISO 60559 defines as non-computational or quiet-computational would be permitted to receive NaN and Inf as input and produce them as output, but that other computational operations would not.</div><div><br></div><div>Per ISO 60559, the quiet-computational operations that I think are relevant to us are: copy, negate, abs, copySign, and conversions between encoding (eg, bitcast). The non-computational operations that I think are relevant to us are classification functions (including isNaN).</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"><div lang="EN-US" style="overflow-wrap: break-word;"><div class="gmail-m_-6837852578495190315WordSection1"><p class="MsoNormal">If you enable it, you should expect the compiler to diverge from the language standard. I’m sure there’s precedent for this.
 If I write #pragma once at the top of my header, and include it twice back to back, the preprocessor won’t paste my header twice. Should #pragma once be removed because it breaks #include?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Now, you have a real-world example that uses NaN as a sentinel value. In your case, it would be nice if the compiler worked as you suggest. Now, suppose I have a “safe matrix multiply”:<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">```<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">std::optional<MyMatrixT> safeMul(const MyMatrixT & lhs, const MyMatrixT & rhs) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">  for (int i = 0; i < lhs.rows; ++i) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    for (int j = 0; j < lhs.cols; ++j) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">      if (isnan(lhs[i][j])) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">        return {};<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">      }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">  }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">  for (int i = 0; i < rhs.rows; ++i) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    for (int j = 0; j < rhs.cols; ++j) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">      if (isnan(rhs[i][j])) {<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">        return {};<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">      }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">    }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""> }<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><u></u> <u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">  // do the multiply<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">}<u></u><u></u></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">```<u></u><u></u></span></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">In this case, if isnan(x) can be constant folded to false with fast-math enabled, then these two loops can be completely eliminated since they are empty and do nothing. If MyMatrixT is a 100 x 100 matrix, and/or safeMul is called in a hot
 loop, this could be huge. What should I do instead here?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Really, it would be much more consistent if we apply the clang documentation for fast-math “Operands to floating-point operations are not equal to NaN and Inf” literally, and not actually implement “Operands to floating-point operations
 are not equal to NaN and Inf, except in the case of isnan(), but only if the argument to isnan() is a value stored in a variable and not an expression”. As far as using isnan from the standard library compiled without fast-math vs a compiler builtin, I don’t
 think this is an issue. Really, enabling fast-math is basically telling the compiler “My code has no NaNs. I won’t try to do anything with them, and you should optimize assuming they aren’t there”. If a developer does their part, why should it matter to them
 that isnan() might work?<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal">Thanks,<u></u><u></u></p>
<p class="MsoNormal">   Chris Tetreault<u></u><u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<p class="MsoNormal"><u></u> <u></u></p>
<div>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(225,225,225);padding:3pt 0in 0in">
<p class="MsoNormal"><b>From:</b> Serge Pavlov <<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>> <br>
<b>Sent:</b> Thursday, September 9, 2021 11:27 AM<br>
<b>To:</b> Chris Tetreault <<a href="mailto:ctetreau@quicinc.com" target="_blank">ctetreau@quicinc.com</a>><br>
<b>Cc:</b> Krzysztof Parzyszek <<a href="mailto:kparzysz@quicinc.com" target="_blank">kparzysz@quicinc.com</a>>; <a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>; <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<b>Subject:</b> Re: [llvm-dev] [cfe-dev] Should isnan be optimized out in fast-math mode?<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"><u></u> <u></u></p>
<p align="center" style="text-align:center"><strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">WARNING:</span></strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">
 This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.</span><u></u><u></u></p>
<div>
<div>
<div>
<p class="MsoNormal">On Fri, Sep 10, 2021 at 1:03 AM Chris Tetreault <<a href="mailto:ctetreau@quicinc.com" target="_blank">ctetreau@quicinc.com</a>> wrote:<u></u><u></u></p>
</div>
<div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal">In this case, I think it’s perfectly reasonable to reinterpret_cast the floats to uint32_t, and then inspect the bit pattern. Since NaN is being used as a sentinel value, I assume
 it’s a known bit pattern, and not just any old NaN.<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">C standard defines a function to determine if a value is NaN. The fact that it does not work in this case demonstrates that the optimization is incorrect. Again, if isnan comes from libc implementation, it will work, but if it is provided
 by the compiler, it does not. Users expect consistent behavior.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">If NaNs are not prohibited at all in -ffinite-math-only mode, isnan must work as specified in the standard.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">I think it’s fine that fast-math renders isnan useless. As far as I know, the C++ standard wasn’t written to account for compilers providing fast-math flags. fast-math is itself
 a workaround for “IEEE floats do not behave like actual real numbers”, so working around a workaround seems reasonable to me.<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">I feel you are right with fast-math as a workaround, but the compiler is a practical tool and it must be convenient and suitable for a wide set of tasks. The situation when a user has to invent workarounds because some optimization changes
 semantics of a standard function is not good.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"><u></u> <u></u></p>
</div>
<div>
<p class="MsoNormal">As for ffinite-math-only, it is actually more or less a safe mode. When we use integer division, we know that the divisor must not be zero. The case of ffinite-math-only is similar. <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin-left:4.8pt;margin-right:0in">
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(225,225,225);padding:3pt 0in 0in">
<p class="MsoNormal"><b>From:</b> Serge Pavlov <<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>>
<br>
<b>Sent:</b> Thursday, September 9, 2021 10:34 AM<br>
<b>To:</b> Chris Tetreault <<a href="mailto:ctetreau@quicinc.com" target="_blank">ctetreau@quicinc.com</a>><br>
<b>Cc:</b> Krzysztof Parzyszek <<a href="mailto:kparzysz@quicinc.com" target="_blank">kparzysz@quicinc.com</a>>;
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>;
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<b>Subject:</b> Re: [llvm-dev] [cfe-dev] Should isnan be optimized out in fast-math mode?<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
<p align="center" style="text-align:center"><strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">WARNING:</span></strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">
 This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.</span><u></u><u></u></p>
<div>
<div>
<p class="MsoNormal">Let me describe a real life example.
<u></u><u></u></p>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">There is a realtime program that processes float values from a huge array. Calculations do not produce NaNs and do not expect them. Using -ffinite-math-only substantially speeds
 up the program, so it is highly desirable to use it. The problem is that the array contains NaNs, they mark elements that should not be processed.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">An obvious solution is to check an element for NaN, and if it is not, process it. Now there is no clean way to do so. Only workarounds, like using integer arithmetics. The function
 'isnan' became useless. And there are many cases when users complain of this optimization.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Thanks,<u></u><u></u></p>
</div>
<div>
<div>
<div>
<p class="MsoNormal">--Serge<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div>
<p class="MsoNormal">On Fri, Sep 10, 2021 at 12:09 AM Chris Tetreault <<a href="mailto:ctetreau@quicinc.com" target="_blank">ctetreau@quicinc.com</a>> wrote:<u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal">If the issue is that users want their asserts to fire, then they should be encouraged to only enable fast math in release builds.
<u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(225,225,225);padding:3pt 0in 0in">
<p class="MsoNormal"><b>From:</b> llvm-dev <<a href="mailto:llvm-dev-bounces@lists.llvm.org" target="_blank">llvm-dev-bounces@lists.llvm.org</a>>
<b>On Behalf Of </b>Serge Pavlov via llvm-dev<br>
<b>Sent:</b> Thursday, September 9, 2021 9:53 AM<br>
<b>To:</b> Krzysztof Parzyszek <<a href="mailto:kparzysz@quicinc.com" target="_blank">kparzysz@quicinc.com</a>><br>
<b>Cc:</b> LLVM Developers <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>;
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<b>Subject:</b> Re: [llvm-dev] [cfe-dev] Should isnan be optimized out in fast-math mode?<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
<p align="center" style="text-align:center"><strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">WARNING:</span></strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">
 This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.</span><u></u><u></u></p>
<div>
<div>
<div>
<p class="MsoNormal">On Thu, Sep 9, 2021 at 11:29 PM Krzysztof Parzyszek <<a href="mailto:kparzysz@quicinc.com" target="_blank">kparzysz@quicinc.com</a>> wrote:<u></u><u></u></p>
</div>
<div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal">This goes back to what these options actually imply.  The interpretation that I favor is “this code will never see a NaN”, or “the program can assume that no floating point expression
 will evaluate to a NaN”.  The benefit of that is that it’s intuitively clear.  In that case “isnan(x)” is false, because x cannot be a NaN.  There is no distinction between “isnan(x+x)” and “isnan(x)”.  If the user wants to preserve “isnan(x)”, they can apply
 some pragma (which clang may actually have already).<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">It is apparent simplicity. As the discussion in gcc mail list demonstrated (<a href="https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544641.html" target="_blank">https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544641.html</a>)
 this is actually an impromissing way. From a practical viewpoint it is also a bad solution as users cannot even check the assertions.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">To be honest, I’m not sure that I understand your argument.  Are you saying that under your interpretation we could optimize “isnan(x+x) -> false”, but not “isnan(x) -> false”?<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Argument of `isnan(x+x)` is a result of arithmetic operation. According to the meaning of -ffinite-math-only it cannot produce NaN. So this call can be optimized out. In the general
 case `isnan(x)` value may be, say, loaded from memory. Load is not an arithmetic operation, so nothing prevents from loading NaN. Optimizing the call out is dangerous in this case.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<p class="MsoNormal"><span style="font-size:9pt;font-family:Consolas">--
</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:Consolas">Krzysztof Parzyszek 
<a href="mailto:kparzysz@quicinc.com" target="_blank"><span style="color:rgb(5,99,193)">kparzysz@quicinc.com</span></a>   AI tools development</span><u></u><u></u></p>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(225,225,225);padding:3pt 0in 0in">
<p class="MsoNormal"><b>From:</b> Serge Pavlov <<a href="mailto:sepavloff@gmail.com" target="_blank">sepavloff@gmail.com</a>>
<br>
<b>Sent:</b> Thursday, September 9, 2021 11:10 AM<br>
<b>To:</b> Krzysztof Parzyszek <<a href="mailto:kparzysz@quicinc.com" target="_blank">kparzysz@quicinc.com</a>><br>
<b>Cc:</b> Chris Lattner <<a href="mailto:clattner@nondot.org" target="_blank">clattner@nondot.org</a>>; James Y Knight <<a href="mailto:jyknight@google.com" target="_blank">jyknight@google.com</a>>; LLVM Developers <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>;
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a><br>
<b>Subject:</b> Re: [cfe-dev] [llvm-dev] Should isnan be optimized out in fast-math mode?<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
<p align="center" style="text-align:center"><strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">WARNING:</span></strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">
 This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.</span><u></u><u></u></p>
<div>
<div>
<div>
<p class="MsoNormal">On Thu, Sep 9, 2021 at 8:30 PM Krzysztof Parzyszek via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<u></u><u></u></p>
</div>
<div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal">If we say that the fast-math flags are “enabling optimizations that the presence of nans otherwise prohibits”, then there is no reason for clang to keep calls to “isnan” around,
 or to keep checks like “fpclassify(x) == it’s_a_nan” unfolded.  These are exactly the types of optimizations that the presence of NaNs would prohibit.<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Transformation 'x * 0 -> 0' is an optimization allowed in the absence of nans as arguments, because it produces a program that behaves identically under the given restrictions.
 Replacement of `isnan(x + x)` is also an optimization under the same restrictions. Replacement of `isnan(x)` in general case is not, because we cannot assume that x cannot be a NaN.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal">I understand the need for having some NaN-handling preserved in an otherwise finite-math code.  We already have fast-math-related attributes attached to each function in the LLVM
 IR, so we could introduce a source-level attribute for enabling/disabling these flags per function.<u></u><u></u></p>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">GCC allows using `#pragma GCC optimize ("finite-math-only")` or `#pragma GCC optimize ("no-finite-math-only")` to enable/disable optimization per function basis. Clang could support
 this pragmf or maybe `#pragma clang fp` can be extended to support similar functionality.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<p class="MsoNormal"><span style="font-size:9pt;font-family:Consolas">--
</span><u></u><u></u></p>
<p class="MsoNormal"><span style="font-size:8pt;font-family:Consolas">Krzysztof Parzyszek 
<a href="mailto:kparzysz@quicinc.com" target="_blank"><span style="color:rgb(5,99,193)">kparzysz@quicinc.com</span></a>   AI tools development</span><u></u><u></u></p>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div style="border-right:none;border-bottom:none;border-left:none;border-top:1pt solid rgb(225,225,225);padding:3pt 0in 0in">
<p class="MsoNormal"><b>From:</b> cfe-dev <<a href="mailto:cfe-dev-bounces@lists.llvm.org" target="_blank">cfe-dev-bounces@lists.llvm.org</a>>
<b>On Behalf Of </b>Chris Lattner via cfe-dev<br>
<b>Sent:</b> Wednesday, September 8, 2021 5:51 PM<br>
<b>To:</b> James Y Knight <<a href="mailto:jyknight@google.com" target="_blank">jyknight@google.com</a>><br>
<b>Cc:</b> LLVM Developers <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>>; Clang Dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>><br>
<b>Subject:</b> Re: [cfe-dev] [llvm-dev] Should isnan be optimized out in fast-math mode?<u></u><u></u></p>
</div>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
<p align="center" style="text-align:center"><strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">WARNING:</span></strong><span style="font-size:10.5pt;font-family:Arial,sans-serif;color:black;background:yellow">
 This email originated from outside of Qualcomm. Please be wary of any links or attachments, and do not enable macros.</span><u></u><u></u></p>
<div>
<p class="MsoNormal">On Sep 8, 2021, at 3:27 PM, James Y Knight via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<u></u><u></u></p>
<div>
<blockquote style="margin-top:5pt;margin-bottom:5pt">
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div>
<p class="MsoNormal">I expressed my strong support for this on the previous thread, but I'll just repost the most important piece...
<u></u><u></u></p>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<div>
<p class="MsoNormal">I believe the proposed semantics from the Clang level ought to be:<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">  The -ffinite-math-only and -fno-signed-zeros options do not impact the ability to accurately load, store, copy, or pass or return such values from general function calls. They
 also do not impact any of the "non-computational" and "quiet-computational" IEEE-754 operations, which includes classification functions (fpclassify, signbit, isinf/isnan/etc), sign-modification (copysign, fabs, and negation `-(x)`), as well as the totalorder and
 totalordermag functions. Those correctly handle NaN, Inf, and signed zeros even when the flags are in effect. These flags <i>do</i> affect the behavior of other expressions and math standard-library calls, as well as comparison operations.<u></u><u></u></p>
</div>
</div>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">FWIW, I completely agree - these flags are about enabling optimizations that the presence of nans otherwise prohibits.  We shouldn’t take a literal interpretation of an old GCC
 manual, as that would not be useful.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">If we converge on this definition, I think it should be documented.  This is a source of confusion that comes up periodically.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">-Chris<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<p class="MsoNormal" style="margin-bottom:12pt"> <u></u><u></u></p>
<blockquote style="margin-top:5pt;margin-bottom:5pt">
<div>
<div>
<div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">I would not expect this to have an actual negative impact on the performance benefit of those flags, since the optimization benefits mainly arise from comparisons and the general
 computation instructions which are unchanged.<u></u><u></u></p>
</div>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">In further support of this position, I note that the previous thread uncovered at least one vendor -- Apple (<a href="https://opensource.apple.com/source/Libm/Libm-2026/Source/Intel/math.h.auto.html" target="_blank">https://opensource.apple.com/source/Libm/Libm-2026/Source/Intel/math.h.auto.html</a>)
 -- going out of their way to cause isnan and friends to function properly with -ffast-math enabled.<u></u><u></u></p>
</div>
</div>
</div>
</blockquote>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<p class="MsoNormal" style="margin-bottom:12pt"> <u></u><u></u></p>
<blockquote style="margin-top:5pt;margin-bottom:5pt">
<div>
<p class="MsoNormal"> <u></u><u></u></p>
<div>
<div>
<p class="MsoNormal">On Wed, Sep 8, 2021 at 1:02 PM Serge Pavlov via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<u></u><u></u></p>
</div>
<blockquote style="border-top:none;border-right:none;border-bottom:none;border-left:1pt solid rgb(204,204,204);padding:0in 0in 0in 6pt;margin:5pt 0in 5pt 4.8pt">
<div>
<div>
<p class="MsoNormal">Hi all,<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">One of the purposes of `llvm::isnan` was to help preserve the check made by `isnan` if fast-math mode is<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">specified (<a href="https://reviews.llvm.org/D104854" target="_blank">https://reviews.llvm.org/D104854</a>). I'd like to describe reason for that and propose to use the behavior<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">implemented in that patch.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<p class="MsoNormal">The option `-ffast-math` is often used when performance is important, as it allows a compiler to generate faster code.
<u></u><u></u></p>
<div>
<p class="MsoNormal">This option itself is a collection of different optimization techniques, each having its own option. For this topic only the<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">option `-ffinite-math-only` is of interest. With it the compiler treats floating point numbers as mathematical real numbers,<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">so transformations like `0 * x -> 0` become valid.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">In clang documentation (<a href="https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math" target="_blank">https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math</a>)
 this option is described as:<br>
<br>
    "Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf."<br>
<br>
GCC documentation (<a href="https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html" target="_blank">https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html</a>) is a bit more concrete:<br>
<br>
    "Allow optimizations for floating-point arithmetic that assume that arguments and results are not NaNs or +-Infs."<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">**What is the issue?**<br>
<br>
C standard defines a macro `isnan`, which can be mapped to an intrinsic function provided by the compiler. For both<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">clang and gcc it is `__builtin_isnan`. How should this function behave if `-ffinite-math-only` is specified? Should it make a<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">real check or the compiler can assume that it always returns false?<br>
<br>
GCC optimizes out `isnan`. It follows from the viewpoint that (<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724#c1" target="_blank">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724#c1</a>):<br>
<br>
    "With -ffinite-math-only you are telling that there are no NaNs and thus GCC optimizes isnan (x) to 0."<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">Such treatment of `-ffinite-math-only` has sufficient drawbacks. In particular it makes it impossible to check validity of<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">data: a user cannot write<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">assert(!isnan(x));<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">because the compiler replaces the actual function call with its expected value. There are many complaints in GCC bug<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">tracker (for instance
<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> or
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724" target="_blank">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724</a>)<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">as well as in forums (<a href="https://stackoverflow.com/questions/47703436/isnan-does-not-work-correctly-with-ofast-flags" target="_blank">https://stackoverflow.com/questions/47703436/isnan-does-not-work-correctly-with-ofast-flags</a>
 or <br>
<a href="https://stackoverflow.com/questions/22931147/stdisinf-does-not-work-with-ffast-math-how-to-check-for-infinity" target="_blank">https://stackoverflow.com/questions/22931147/stdisinf-does-not-work-with-ffast-math-how-to-check-for-infinity</a>). Proposed<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">solutions are using integer operations to make the check, to turn off `-ffinite-math-only` in some parts of the code or to<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">ensure that libc function is called. It clearly demonstrates that `isnan` in this case is useless, but users need its functionality<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">and do not have a proper tool to make required checks. The similar direction was criticized in llvm as well (<a href="https://reviews.llvm.org/D18513#387418" target="_blank">https://reviews.llvm.org/D18513#387418</a>).<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">**Why imposing restrictions on floating types is bad?**<br>
<br>
If `-ffinite-math-only` modifies properties of `double` type, several issues arise, for instance:<br>
- What should return `std::numeric_limits<double>::has_quiet_NaN()`?<br>
- What body should have this function if it is used in a program where some functions are compiled with `fast-math` and some without?<br>
- Should inlining of a function compiled with `fast-math` to a function compiled without it be prohibited in inliner?<br>
- Should `std::isnan(std::numeric_limits<float>::quiet_NaN())` be true?<br>
<br>
If the type `double` cannot have NaN value, it means that `double` and `double` under `-ffinite-math-only` are different types<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">(<a href="https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544641.html" target="_blank">https://gcc.gnu.org/pipermail/gcc-patches/2020-April/544641.html</a>). Such a way can
 solve these problems but it is so expensive<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">that hardly it has a chance to be realized.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">**The solution**<br>
<br>
Instead of modifying properties of floating point types, the effect of `-ffinite-math-only` can be expressed as a restriction on<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">operation usage.  Actually clang and gcc documentation already follows this way. Fast-math flags in llvm IR also are attributes<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">of instructions. The only question is whether `isnan` and similar functions are floating-point arithmetic.<br>
<br>
>From a practical viewpoint, treating non-computational functions as arithmetic does not add any advantage. If a code extensively<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">uses `isnan` (so could profit by their removal), it is likely it is not suitable for -ffinite-math-only. This interpretation however creates<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">the problems described above. So it is profitable to consider `isnan` and similar functions as non-arithmetical.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">**Why is it safe to leave `isnan`?**<br>
<br>
The probable concern of this solution is deviation from gcc behavior. There are several reasons why this is not an issue.<br>
<br>
1. -ffinite-math-only is an optimization option. A correct program compiled with -ffinite-math-only and without it should behave<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">   identically, if conditions for using -ffinite-math-only are fulfilled. So making the check cannot break functionality.<br>
2. `isnan` is implemented by libc, which can map it to a compiler builtin or use its own implementation, depending on<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">   configuration options. `isnan` implemented in libc obviously always does the real check.<br>
3. ICC and MSVC preserve `isnan` in fast-math mode.<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">The proposal is to not consider `isnan` and other such functions as arithmetic operations and do not optimize them out<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal">just because -ffinite-math-only is specified. Of course, there are cases when `isnan` may be optimized out, for instance,<u></u><u></u></p>
</div>
<div>
<p class="MsoNormal" style="margin-bottom:12pt">`isnan(a + b)` may be optimized if -ffinite-math-only is in effect due to the assumption (result of arithmetic operation is not NaN).<br>
<br>
What are your opinions?<u></u><u></u></p>
<div>
<div>
<p class="MsoNormal">Thanks,<br>
--Serge<u></u><u></u></p>
</div>
</div>
</div>
</div>
<p class="MsoNormal">_______________________________________________<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" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><u></u><u></u></p>
</blockquote>
</div>
<p class="MsoNormal">_______________________________________________<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" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><u></u><u></u></p>
</div>
</blockquote>
</div>
<p class="MsoNormal"> <u></u><u></u></p>
</div>
</div>
</div>
<p class="MsoNormal">_______________________________________________<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" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><u></u><u></u></p>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</div>
</div>
</div>
</blockquote>
</div>
</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></div>