<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/92592>92592</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Unexpected behavior from std::fma when passing optimization flags
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          Rinzii
      </td>
    </tr>
</table>

<pre>
    I've noticed a strange discrepancy with std::fma when handling the following edge case

> If z is NaN, and x * y is not 0 * Inf or Inf * 0, then NaN is returned

When compiling with clang_trunk the following behavior is observed with the provided code below (consistent with both libstdc++ and libc++):

```cpp
#include <iostream>
#include <limits>
#include <cmath>

double foo() {
    return std::fma(0.0, std::numeric_limits<double>::infinity(), 0.0);
}

int main()
{
    std::cout << foo();
}
```

When you pass to clang the flag -O0 this example returns `-NaN` but when we pass clang the flag -O3 this example returns `+Nan`. This behavior is suprising! Normally clang rarely changes its return values when compiler flags are passed. Especially for such a common flag as -O{N}. This behavior even changes when passing something as -Og and that does not seem correct.

When instead compiling for GCC we observe that GCC always returns `-NaN` no matter what optimization level is specified as one would expect. Where as with clang it _changes_ its return value based on optimization flags and that in itself is unexpected!


The behavior can be observed here:

https://godbolt.org/z/K67j9K7Y4

Now even though this behavior is unexpected is it correct?

This is what IEEE-754 has to say on the behavior of NaN and its signbit:

> 6.3 The sign bit
When either an input or result is a NaN, this standard does not interpret the sign of a NaN. However,
operations on bit strings — copy, negate, abs, copySign — specify the sign bit of a NaN result, sometimes
based upon the sign bit of a NaN operand. The logical predicates totalOrder and isSignMinus are also
affected by the sign bit of a NaN operand. For all other operations, this standard does not specify the sign
bit of a NaN result, even when there is only one input NaN, or when the NaN is produced from an invalid
operation.

(Excerpt from IEEE-754 (2019)) 

So as far as IEEE-754 is concerned LLVM is technically correct as the sign of NaN does not matter when returning in FMA. Now this may be fine for IEEE-754 but what does the LLVM docs say about the matter?

> Return the same value as a corresponding libm ‘fma’ function but without trapping or setting errno.
When specified with the fast-math-flag ‘afn’, the result may be approximated using a less accurate calculation.

https://llvm.org/docs/LangRef.html#llvm-fma-intrinsic

There is no where in the docs where this behavior is specified and the behavior does not neccessarily appear in line with what the documentation says. Where with GCC using GlibC the value returned is consistent no matter the optimization flags this is not the case with clang. Thus, I am to believe this is the incorrect result ignoring the fact that the result is unexpected. I am asking for clarification on if this is the intended result. I'd also like clarification on if LLVM thinks that this behavior is correct? 

If this is correct then consider this bug report for the documentation of LLVM.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJx8V1Fv4zgO_jXqC9HAkdMmecjDtNPuFbvTAWb3bnFPA1qmY-3IkiHJSTO__kDJTtKkc0BRxxJFUh_JjzSGoLeWaCPuHsTd5xscYuv85pu2P7W-qVx92LwIudwRWBe1ohoQQvRotwS1DspTj1YdYK9jCyHWovwkyk9Nh7BvyUKLtjbabiG2BI0zxu35jeotgcJAovgsik_j__IJXhr4CTrAK74K-Qhoa3gDIT_BgVeti1Ck1xfbgPPpwa8FC0c2-IqvLOkpDt5Sfa7_b95Xrut18ih5rAza7ffoB_vjwsWKWtxp51mbqwL5HdX5DMv13u10TTUoVxNUZNwehFwpZ4MOkWzMopWLLRhdhVgrIR-EfEhXMroaX4VcM2LnKNwX-U_1_bgiS22VGWoCUT5qF6In7ET59NG20Z2O4RebqsPYnvbS_9oNleGLOyFXQq5BLB_yDgCMOL4LrJCrYpYAP67aoSOv1ffJ-GNWypbSvraNtjoesgU-mjSsRTmaEsvP5z5pG6FDbUf5UeTMraNl5YbINxPl4-kKH6idQL3Kh4MboMcQILqcDDkNDG7h9msBsdUB6A273tAIRgBxX9xygt4XUA0xJ_qesporHeUvdQj58IpW3Bcz-ItFzjMuDL3XQdutkHN4db5DYw6jco-e-KXlIgyg45TusEMzUMgO5UQnn_wIgD47SPUMnkJPSieNjfMQBtUC8oHO2ew2Brj9KpYPr2L5-dI72rH20XgyxXq5ZILrKLb8K53fplyPLUaoHeXqDUQdKOc9qTi7Coa2IRLWZ0XK_v32-MjwjkWYFfIamj0ewkdRsQ46jJE87FnY9VF3-idG7SwY2pFJEDMIjWZGC-Aswd4NpgZ669k3-LslT7x14gnQEb6PN_9-hTtUGKgGZ9_bG-GfkNCWD5Jp2IXBZmtUCzl_RwLp_18tnWBXaKGiExWxexfU0cbYB16Tz0I-b11dORNnzm-FfP4p5PPv98t_1r8v_7s4P_Tq9jmksXXDts3Zep6KJyf5TccpfKJ8fu8s74aM-MvT09Pt8m4BLabKCnhgYOL5hVyTyJqRYSi5DVU6XrJh-QT3sxIYCpYAFjklDOnYkgfk1OmHyC3BUxhMZE9w6iLpSiGirdHXp1zUNpLvPcXkV9LumnxqBv9ye9qRF_Ixm3M9-RRQzhX2grugttsA4kmKVSHWC1CuP7A9S1uMlPpXFfjBG3-y_pNszr7DyTSrnMyPl0gcyzWlOwrZjZxjQz-CeX0y-WnrWULMuK1WaKD3VGuFkTgYEc1XXyfUOKLs1xdth0wRaILLlrBpctCrXzl5NPXsPKAx4FIwTkj9H-wvrz_e7mMMUnompompKLkjW3NIRZvjPgba-aPYNAj03tUDjy2Nd11OlB0aXV9E9R0XCbl6elPk-5hPHbNZyJUs5uvUw9ZwfuRPx1TRoOfHUV4HUM4q4kkE_vjjP194JZJqLYeFOTyXEh86z0H2_QjVkcnIjnzDxKgtPH_5NAMu34Rxhwfmh0ZbSqx5dCK3qImE2UzypHYqpLrEinsor2dLF3XNFfgt01xyETsa-Q5D6hreU-idrdkro6vumOQrHhbG32toBqsSISZ_NLNNhOix7_kgtyGKMc2G3ls3OyvyE1Efx68GQ7zlYeY2taujRWzs0eI4Ek6EMOKDfe_dm-6QU3tIbQvBUAiASg0eI8-lRg3mOi3e06sxu27kVoZSyOc_0G6_UTNrY2eELFngtunwVltmiqDVBbfnTLaOQ8u_M8ApLnnliorPWlbqJ2dsekwXS0pRCOi1OfBtCT2rNpwXCb-UC6OloSMbc58KeAhT10ty3GIzQL8ZXWUsc-Cn4XrM72niPXVdFv2gCcaxRbCbLMIfAGftlTlrSKTxAthx26jIaNrR8SAf0nYqmonpt9b54ycGqpgb7Vno3zWxWdaO4cc0XyiDXjfMj-yqs6CbC4uRLM_6Wd0M-IOoTlQJRv-gDxWkGuNh6EeY_LkI5qmNvmOSl5Px6aIxz3M26DqBy4qGLXjqnY_pCtfhdNmFMYFv6k1Zr8s13tBmvpzfrZfl4n55024KuZJ3i-UdNmWJ982iLivZrLBYzIuiWSwWN3ojC7ko7ubL-Xq-XCxn63KlFnK9urtfL2mOa7EoqENtZlNB3OgQBtqs5d1a3hisyIT0cSmlpT2kTSElf2v6TaqRatgGsSiMDjGctEQdDW3-fRo-jtglTr7-1Jym0OvEuxm82VwMRzq2QzVTrhtLeXzc9t79w1GRz8lTrut0k_8FAAD__909CD4">