<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0in;
        margin-right:0in;
        margin-bottom:0in;
        margin-left:.5in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.EmailStyle20
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:1639677845;
        mso-list-type:hybrid;
        mso-list-template-ids:-9036414 67698705 67698713 67698715 67698703 67698713 67698715 67698703 67698713 67698715;}
@list l0:level1
        {mso-level-text:"%1\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;}
@list l0:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal">(tl;dr) I seem to have become embroiled in this argument again, and this is clearly going nowhere. Therefore, I propose:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<ol style="margin-top:0in" start="1" type="1">
<li class="MsoListParagraph" style="margin-left:0in;mso-list:l0 level1 lfo1">At a minimum, we should do nothing but (maybe) clarify the docs. I think the current behavior is acceptable for the vast majority of users, and there exists workarounds for users that
 really need them.<o:p></o:p></li><li class="MsoListParagraph" style="margin-left:0in;mso-list:l0 level1 lfo1">If interested users really want to be able to do isnan(x) with fast-math enabled without workarounds, they should implement the pragma. Such a pragma would be of great value to society,
 and surely users would thank us.<o:p></o:p></li><li class="MsoListParagraph" style="margin-left:0in;mso-list:l0 level1 lfo1">We should not create a special case for isnan(x). I have laid out many arguments why it’s not a good solution. It would reduce the value of fast-math for users such as the graphics
 programmers described below, and create portability issues if code begins to rely on this new special case (becoming non-portable to any other compiler or old versions of clang. And again, just because MSVC and ICC *<b>just happen to*</b>, as an implementation
 detail, work like this today doesn’t mean that they can be relied on to continue working like this, or that old versions worked like this).<o:p></o:p></li></ol>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">(my rebuttal to this last message)<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Many users of fast-math *<b>can</b>* actually ignore the existence of NaNs. For example, in a real time 3D renderer, the presence of NaN is typically a bug. In the hot render loop, you cannot afford to do any sort of error handling related
 to NaN, and getting a NaN in one your matrices or vertices will result in black triangles or a black screen. For these users, you must just be disciplined, and avoid creating NaNs.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">However, if such a user were to depend on a math lib (probably templated because graphics programmers overwhelmingly prefer C++, which means that they would be compiling it themselves, but can’t easily modify it) that contains isnan, it
 would be a shame if the compiler were forbidden to consider it an optimization candidate because they called a function that “uses” it for input validation or something. Such code would look something like:<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">```<o:p></o:p></p>
<p class="MsoNormal">template <typename T> T f(T x) {<o:p></o:p></p>
<p class="MsoNormal">   // some sort of branch based on isnan(x) here<o:p></o:p></p>
<p class="MsoNormal">```<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">… which meets the criteria you propose for not being eliminated, but is also absolutely undesirable. For users that do care about NaN, a pragma would be an elegant way for them to ensure that the isnan call they care about is not eliminated.
 For a graphics developer, an assert on isnan suddenly becomes useful if they had a pragma and could enable it selectively.<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<p class="MsoNormal">Thanks,<o:p></o:p></p>
<p class="MsoNormal">   Christopher Tetreault<o:p></o:p></p>
<p class="MsoNormal"><o:p> </o:p></p>
<div>
<div style="border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in">
<p class="MsoNormal"><b>From:</b> llvm-dev <llvm-dev-bounces@lists.llvm.org> <b>On Behalf Of
</b>Serge Pavlov via llvm-dev<br>
<b>Sent:</b> Tuesday, September 21, 2021 6:05 AM<br>
<b>To:</b> antlists <antlists@youngman.org.uk><br>
<b>Cc:</b> LLVM Developers <llvm-dev@lists.llvm.org><br>
<b>Subject:</b> Re: [llvm-dev] [cfe-dev] Should isnan be optimized out in fast-math mode?<o:p></o:p></p>
</div>
</div>
<p class="MsoNormal"><o:p> </o:p></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><o:p></o:p></p>
<div>
<div>
<div>
<p class="MsoNormal">On Tue, Sep 21, 2021 at 3:46 AM antlists via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<o:p></o:p></p>
</div>
<div>
<blockquote style="border:none;border-left:solid #CCCCCC 1.0pt;padding:0in 0in 0in 6.0pt;margin-left:4.8pt;margin-right:0in">
<p class="MsoNormal">I know I may be coming in at half cock, but what is the CORRECT
<br>
MATHEMATICAL behaviour?<o:p></o:p></p>
</blockquote>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">I'll use your question to make a summary.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal"> Now clang removes calls to `isnan` in -ffinite-math-only. The justification for such behavior comes from early GCC viewpoint (<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724#c1">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724#c1</a>):<o:p></o:p></p>
</div>
<p class="MsoNormal"><br>
"With -ffinite-math-only you are telling that there are no NaNs"<br>
<br>
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.<br>
<br>
Actually the existence of NaNs cannot be ignored even if no operations on NaNs take place. There are several reasons for that, at least:<br>
- Users need  to check the input data, for example to assert, or to choose a slower but general path.<br>
- NaN can be used as a sentinel. In this case it is actually not a number but some distinguishable bit pattern.<br>
- 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.<br>
- 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.<br>
<br>
The "correct behavior" depends on whether NaNs are allowed in the code compiled with -ffinite-math-only:<br>
- if no, we have the current behavior,<br>
- if yes, `isnan` cannot be optimized out.<br>
<br>
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:<br>
- <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50724</a><br>
- <a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84949</a><br>
as well as in forums:<br>
- <a href="https://stackoverflow.com/questions/38978951/can-ffast-math-be-safely-used-on-a-typical-project">
https://stackoverflow.com/questions/38978951/can-ffast-math-be-safely-used-on-a-typical-project</a><br>
- <a href="https://stackoverflow.com/questions/47703436/isnan-does-not-work-correctly-with-ofast-flags">
https://stackoverflow.com/questions/47703436/isnan-does-not-work-correctly-with-ofast-flags</a><br>
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.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">The proposal was to support the programming model, anticipated by many users. Advantages and risks were discussed in the thread previously.<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><o:p> </o:p></p>
</div>
<div>
<p class="MsoNormal">Thanks,<o:p></o:p></p>
</div>
<div>
<p class="MsoNormal">--Serge<o:p></o:p></p>
</div>
</div>
</div>
</div>
</body>
</html>