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

    <tr>
        <th>Summary</th>
        <td>
            [clang] `-O2` requires `-ftrapping-math` or  `-ffast-math` on amd64 to avoid false positives with `feenableexcept(FE_DIVBYZERO)`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

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

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

<pre>
    Hi, using this sample code:

```c++
#include <cfenv>
#include <cstdio>

struct bc_t
{
        float minDist, maxDist;
        float hudSize;
        float a1, a2, a3 = 0.0f;
        float minSize;
        float b1, b2, b3 = 0.0f;
        float maxSize;
        float c1, c2, c3 = 0.0f;
};

int main(int, char**)
{
        feenableexcept(FE_DIVBYZERO);
        bc_t bc;
        sscanf("1 1 1", "%f %f %f", &bc.hudSize, &bc.minSize, &bc.maxSize);
        bc.minDist = bc.hudSize / bc.maxSize;
        bc.maxDist = bc.hudSize / bc.minSize;
        printf("%f\n", bc.minDist);
        return 0;
}
```

By compiling it with `-O2`, the compiled code raises some `division by zero` exception when executed:

```
Process 3247973 stopped
* thread #1, name = 'a.out', stop reason = signal SIGFPE: floating point divide by zero
    frame #0: 0x00005555555551c5 a.out`main + 101
a.out`main:
->  0x5555555551c5 <+101>: divps  %xmm2, %xmm0
    0x5555555551c8 <+104>: movlps %xmm0, (%rsp)
    0x5555555551cc <+108>: cvtss2sd %xmm0, %xmm0
    0x5555555551d0 <+112>: leaq   0xe3c(%rip), %rdi

Process 3249378 stopped
* thread #1, name = 'a.out', stop reason = signal SIGFPE: floating point divide by zero
    frame #0: 0x00005555555551c5 a.out`main((null)=<unavailable>, (null)=<unavailable>) at a.cpp:20:26
   17           feenableexcept(FE_DIVBYZERO);
   18           bc_t bc;
   19           sscanf("1 1 1", "%f %f %f", &bc.hudSize, &bc.maxSize, &bc.minSize);
-> 20                bc.minDist = bc.hudSize / bc.maxSize;
   21           bc.maxDist = bc.hudSize / bc.minSize;
   22           printf("%f\n", bc.minDist);
   23           return 0;
```

My guess is that the SSE optimized code raises division by zero errors from unused fields of the xmm registers, despite we discard those results.

The requirement of `-O2` requiring either `-ftrapping-math` or `-ffast-math` is curious since `-ffast-math` sets `-fno-trapping-math`.

Also, I thought `-ftrapping-math` was the default, and that `-fno-trapping-math` is part of `-ffast-math`, but just using `-O2` behaves like if  `-fno-trapping-math` is used, so it behaves like if part of `-ffast-math` was enabled anyway… But maybe `-ffast-math` just modifies other behaviors that make `-ftrapping-math` or `-fno-trapping-math` irrelevant.

Using the Godbolt's compiler explorer (here Clang 19.1.0), it only works with `-O2 -ffast-math` (or depreacted `-Ofast`):

|compiler flags|status|
|-|-|
||✅️|
|`-O0`|✅️|
|`-Os`|❌️|
|`-Os -fno-trapping-math`|❌️|
|`-Os -ftrapping-math`|✅️|
|`-O1`|✅️|
|`-O2`|❌️|
|`-O2 -fno-trapping-math`|❌️|
|`-O2 -ftrapping-math`|✅️|
|`-ffast-math`|✅️|
|`-O2 -ffast-math`|✅️|
|`-O2 -ffast-math -ftrapping-math`|✅️|
|`-O2 -ffast-math -fno-trapping-math`|✅️|
|`-Ofast`|✅️|

See: https://godbolt.org/z/395c8nMef
And (with `-ftrapping-math` added): https://godbolt.org/z/czbGTjs6E
And (with `-fno-trapping-math` added): https://godbolt.org/z/zYr5Pba3W

With 32-bit i686 I reproduce the bug when using SSE but get no bug when not using SSE.

|compiler flags|`-m32 -msse`|`-m32 -mno-sse`|
|-|-|-|
||✅️|✅️|
|`-Os`|❌️|✅️|
|`-O1`|✅️|✅️|
|`-O2`|❌️|✅️|
|`-ffast-math`|✅️|✅️|
|`-O2 -ffast-math`|✅️|✅️|

See 32-bit i686 with SSE I get the same failure: https://godbolt.org/z/199eqhzGh
And 32-bit i686 build without SSE I get no failure: https://godbolt.org/z/sfd9TsTj4

On my end on Ubuntu 24.04 with amd64, I get same results with clang 19.1.5.

On Ubuntu 24.04 with amd64 and different versions of the clang compiler, I only get it working with clang 13 and 14, every later version breaks it:

||`-O0`|`-O1`|`-O2`|`-O2 -ftrapping-math`|`-ffast-math`|`-O2 -ffast-math`|
|-|-|-|-|-|-|-|
|clang 13.0.1|✅️|✅️|✅️|✅️|✅️|✅️|
|clang 14.0.6|✅️|✅️|✅️|✅️|✅️|✅️|
|clang 15.0.7|✅️|✅️|❌️|✅️|✅️|✅️|
|clang 16.0.6|✅️|✅️|❌️|✅️|✅️|✅️|
|clang 17.0.6|✅️|✅️|❌️|✅️|✅️|✅️|
|clang 18.1.3|✅️|✅️|❌️|✅️|✅️|✅️|
|clang 19.1.5|✅️|✅️|❌️|✅️|✅️|✅️|

On GCC 14.02 I get none of those issues (no one false positive `division by zero` error is raised whatever the compiler flags being used: https://godbolt.org/z/rxMWM68Mc

___

_Note:_ Disabling SSE on amd64 just produces garbage computation (`1.0/1.0` gives `0.0`), but I don't know if that makes sense to disable SSE on amd64. GCC produces the same garbage (`1.0/1.0` giving `0.0`). Though I'm surprised to not get a warning if that's not legit to do, also I'm surprised the generated code runs if that's not legit to do. See: https://godbolt.org/z/77PYGTc5b (Clang) and: https://godbolt.org/z/cvW4Er3Kd (GCC).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUWUtv4zgS_jXMpRCBomxJPuTgOHE2WPROYzuzjdlLQEklix2J1JCU8_j1C1Ky_Eiccbp7gN5AcWSyHl8Vq4pFhhsjVhLxgkwvyfTqjHe2UvpC1PWjwPzh5SxTxfPFPwRhC-iMkCuwlTBgeNPWCLkqkERzQv0T0_7JCbt0D50TFgmZ112BQKJFXqJck-j69YSxhVDDDJ0bq7vcQpbfWzeQeEl0VtaKW2iEvBLGOjwNf_Kv0R5B1RVfxAsejPLQcXDmPyMg0RXQgJYHVI2Qb_BmnjfzvNlxXv70Bm_ueXPPm7_iTa425HMhnQghCUuF9OblFdeEzf0z23MEouRZjfiUY2sJS5fX91e3_7n847_X__7N0W4gOA9Clo_fjcm5LAlLCWMhhBAS5oH5P9MSxo9xPM7yYOPQcWDjpe3AYPqe6mBYKW_zVgwQtoQdnl2Gfj2PMRysTauFtIMxHvN0IQfcW-W7kDTaTkugW9_vxGy_CJfPkKumFbULdGHhUdgKSEzPf2OOhi3AVjiQYOHDHzQXBg0Y1aAjLcRaGKEkZM_wglqRmEK_UG7wsUIJ-IR5Z7F4nTmEzj9rlaMxELFJMksiMFa1LRY-Z-ZgK428AMIiH1eSO6XRFRCW8EB1lrDEjTsm0MiNkn7a5Tiv4cvtzfLzNYnm4IPTGdkqF3gOdIEjZDoHACi1l84i6jjoE6WUTjc_YT6FXmNMXdgCYZcQ0pDQ-e5wb-I5ia4B6NMeN4kWhF06lshDKsS6NeDC76lphvBzr3SAs8eejuyTgb1R67o1I49nTwmbatP26fNKRj7KSAcZ-doaw0yxL-UYiIJuBIRsEFAj_9NTYZQP6oVX3wvShegXfGeRZ1GS_r8ssjcplV1d-7y6ItGik3zNRe3KkfNB7_Z3KWbgynGQty2J5sypZXEPJkwACJ2dXOEcS7ph2at1bma2mflZVW9T5F6VwQGOj3JGt4A-UgEBgIW7rKfXQsfKNqwfq4qONdqwHtTH_cr46RlWnQtZYcBW3PpC-OXLNajWika8HFTDwyoIqLXSBkqtGuhkZ7CAUmBdGFCll_XUNKBxJYxFbRzcAk0rLMIjQiFMznUBtlIGQaPpamuCHthd5Ub-7ITGBqV14saCPUy4FEBhK9R-qrSat62Qq_OG28qRqWGi5MaOg8JA3mmhOgNGyBzfIDFoTT8s1fmh1AHfvDbKmXPr0Heryh7B8MiN90OBJe9q3wBwWfS-PqbCYWy5Ho3eQ-eXvLPwrTN2aN22jsmw4ms0UIsHBFHCuyrcavmCo9yeeMh6FIA3qc_jArh8fuTP5JqRlJJ5DJeda3ees7fc6hE3qhClQAPKL5zXKlwIeY80_AH_YjHfNEZrrHHNpR1W5_ehpUW4UUWmnN8Ts9ngNeBTWyvt4oalFWqERc3lCsJZEAZ0qOvCgpL1Mzwq_WB2OwY4MIuwVGkosNXIc4tFT-ZI_GrNtu1AshgRlDVfGZIsjOW2cy_9_Pnw239zzzUjswVJp-R6SS5Tki63s06Nz-S_JjM7ZFckXRwjgzf9eyLnMbZ3cIWnkbHTQLDvhs--C_5-Xp5gBvwYy_f5-FDEOx56R8omnt-hpPMv6I6NUFnbGhf2bEnYctVnYKD0irDlC2HLaDbNU_kJS1dHpeuI0jG_Xic-LwpXp2anSM5fspu7bya-fkvyW5XjI8Jf_tDTzxmPvvbGfnWCI3aeCQsiTmO4BY2tVkWXoy89WbfqDwZ9lXa7qivcK7Qg1XZWKrulCI6XCmdDEzE4b4zBYSnGIanOt6N7peSEcvIjxeNHEvxHsv5nZObPStd3E2IvRHwwukC49WHgosS4Rr3kou70SckTzmb4Z_VyUw0hvis-60RdeCWqszt6pPqIBlMWsztz923S2_CbhOYZUBagJPyeddJ2wCYBnfTW8KaIJ30n5FR5c4ZWrifIt3vrNBhFHhHkm6NClCVq1_WtUbt2c-wme1mb1Oi1-l3aqXYHe6UfXCbtKo68zNBjxDXqZ6i5Rb2RDZlG_mBA2N2N-nB_3Y3l3dh8b_N4Kw6PxdWrlD38HYrCYFJAg_Bj4fh3DO5CmgQ0iH8tSNOABsnHZZ5War4PUvx9Xvo7ISW_HqQ0CIPo14Lkq9cvAclXz5vFwqccGwu8xL5GupO0MKZD429sFLiZktcGoVVGWLE-fp3pzvLuYOgP-wU8Vty6grl7OTq0I5ChK7P-BHnCjqKfPn39FKef8t6A-_v74eVfyrot6R6uhOFZvWmTlBx2A39kHHoqAyuuM77qsXSW-5tXwlISU39sW7rPmMJKuHMsiSn134fznGu9bqFQkrDEwoNUj-6UO546DRiUBsEqKDwW3EMSeJePSMaNewPpbRjD4XzEEcCdvyyAW8KSBkynW-1dbZVvA91ScnjkWvqL6h6eP7q62RpXwnqA_uaB10a9FlQhrFCi5na8uumkeU9WACe27Uny-Y-bu3yaOWv9idnf-smTQiBff51c6-ifvie_WSycN86Ki6iYRTN-hhdhEkUhY2k4O6suomRC83AWxukkzuNwkkwzTIs4pLNokmXl9ExcMMomIaOMJpSGScCSlPIimURTTLOSFmRCseGiDup63TgYZz4pLsIwZfH0rOYZ1sb_c4yxvDeFkenVmb5wDOdZtzJkQmthrNmKsMLW_j9qPcf06tWVFJrjtxdv3IiMcW4V8LUSxUGmbu8d_vLmNKZnna4vDpZB2KrLglw1hC2dGcOf81arb5hbwpZ9rXBR23tmfcH-FwAA__9L09p3">