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

    <tr>
        <th>Summary</th>
        <td>
            clang++ miscompiles vectorizable comparisons by effectively eliding checks for NaN when FP exceptions are enabled
        </td>
    </tr>

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

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

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

<pre>
    I have encountered a potential bug, in which `clang++-15` miscompiles C++ code that is written to _avoid_ invalid floating point operations (within the meaning in the IEEE-754 standard), such as `x < y` where either `x` or `y` is NaN:
```cpp
    if (std::isnan(lhs[i]) || std::isnan(rhs[i])) {
 result[i] = std::numeric_limits<int32_t>::min();
    } else {
 result[i] = lhs[i] < rhs[i];  // Would raise FE_INVALID if either operand is NaN
    }
```
This miscompilation is observable when the program [enables the invalid exception](https://www.gnu.org/software/libc/manual/html_node/Control-Functions.html) using `feenableexcept(FE_INVALID);`.

Concretely, `clang++` emits instructions such as `vcmpltpd` that raise floating point exceptions when a silent NaN (SNaN) operand is encountered; these cause the program to receive `SIGFPE` when traps for `FE_INVALID` are enabled.  

>From the `dis` command in `lldb-15`:
```
->  0x555555555620 <+1008>: vcmpltpd %ymm4, %ymm3, %ymm3
    0x555555555625 <+1013>: vextractf128 $0x1, %ymm3, %xmm4
    0x55555555562b <+1019>: vshufps $0x88, %xmm4, %xmm3, %xmm3 ; xmm3 = xmm3[0,2],xmm4[0,2] 
    0x555555555630 <+1024>: vandps %xmm1, %xmm3, %xmm1
    0x555555555634 <+1028>: vextractf128 $0x1, %ymm0, %xmm3
    0x55555555563a <+1034>: vpackssdw %xmm3, %xmm0, %xmm0
 0x55555555563e <+1038>: vblendvps %xmm0, %xmm2, %xmm1, %xmm0
 0x555555555644 <+1044>: vmovups %xmm0, 0x70(%rax)
```

The compiler ought to emit alternative instructions (such as `vcmplt_oqpd` or `vucomisd`?) that do not raise floating point exceptions on SNaN inputs.  

For background, GCC had similar bug reports in [#101634](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101634) and [#100778](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100778), although the examples in those reports appear to relate to divide-by-zero exceptions.

In the example below, the bug occurs with `-O2` and `-O3`, but not `-O1`.  The `-march=ivybridge` option is also required to reproduce the bug on my system.

I am not able to test with `clang++` versions 16 or 17 on my system, but the example below also triggers `SIGFPE` on the Compiler Explorer tool at godbolt.org with `clang 16.0.0` and `clang 17.0.1` for `x86_64`.

### Reproduction

```cpp
#include <span>
#include <vector>
#include <iostream>
#include <limits>
#include <cmath>
#include <cfenv>

void Less(std::span<int> result, std::span<const double> lhs, std::span<const double> rhs) {
  for (std::size_t i = 0; i < lhs.size(); ++i) {
    if (std::isnan(lhs[i]) || std::isnan(rhs[i])) {
      result[i] = std::numeric_limits<int32_t>::min();
    } else {
      result[i] = lhs[i] < rhs[i];
    }
  }
}

int main() {
 feenableexcept(FE_INVALID);

  std::size_t n = 32;  // Must be 32 or larger.

  constexpr double nan = std::numeric_limits<double>::quiet_NaN();
  std::vector<double> lhs(n, 0.0);
  lhs.at(n - 1) = nan;
  std::vector<double> rhs(n, 0.0); 

  std::vector<int> result(n);

  Less(std::span<int>(result), std::span<const double>{lhs}, std::span<const double>{rhs});

 std::cout << "element " << n - 1 << ": " << result.at(n-1) << std::endl;
}
```

Compilation command:
```
clang++-15 -O3 -march=ivybridge --std=c++20 -g ./clang15_repro.cpp
```

Output of `clang++-15 --version`:
```
Ubuntu clang version 15.0.7
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8WN2S2joSfhrNTReULfM3F1wEGE5N1dnk1J6zu5eULDdYG1lyJBmYPP1WyzYYhklysbupKSKkVqv19d8nhPfqYBCXbLpi082TaEJp3dJUjbdaGfuU2-Jt-QqlOCKgkbYxAR0WIKC2AU1QQkPeHBhfgzJwKpUsgc0SqYU5ML5ifDVKp2yWQKW8tFWtNHpYtysgbYEQShFAeTg5FQIaCBZ24mhVsQNljkKrAvbaiqDMAWqrTABboxNBWeOB8cVJhVIZCCVChcKQWPf19eXlZTSfTsAHYQrhCsafyVDfyBKEJzvPwLI1vJGBpxIdAqpQootLNGnjMK4rD5_FZ5Z9YsmGJZ_YLGn_ZF23MwAAak8m-VCQXPZJeSMM4wtdejZdKTbdMP4MbL5m8zW8k3JDqVZw1al26BsdulVg2ea62zQVOiV3WlUqeJatlQkZ3wWWvbQClSLlpDJbXS1l8w2g9vjDQ652R5wGBmYrAMa3jG_hX7bRBTihPML2Zff6-Z-ffn_dEBQdmNFfpugRHJpwh2X79a9S-Wu8RE_TXpt7dEeRayRftS6unT04UQGbrtDQko_TfeDgWWJN-yOmizKE2hMo0fDT6TQ-mGZs3YHxrbf7cBIOGd9qlUvGt5UwjdCMb8tQ6Z2xBa2trQnO6tG2MTKG4JhWyVmNp9Bjs2SPrSnt4YwvrqB0Tpgl4-7i8XNtjXQYUL9RdN5mD0UekmNBGR9c0x46DOGjrGod6oIkYy61nrjLmQsSvgVPgFcaTSCPUMj-SZ7hz0NfDdKd3B1K9AhSNB5voA8WHEpURyRr_nz9bfvHS5dPBoITtYd9m0YDHGYJCMq2CFQxBhjisXW2ikewWVIoT8LSVlU0y9Ck1kXelpX36dh-HbHsBSA5T_t_M55QCDO-SpNk0eYG9NAB49O3qppE-OMwGw4vAXujb3rRl2a9PjwHJ2TYp3wBjE-Sc_pe5ZkOeqwyv6p87lX6stnXvtW2WAx1XIYDzRmQq7rBJg7YdJUwvuYxBdZx53UGHluSXcHik94SYYpoCJ2TPjw9_UDb5Kpt8StQJUPtj1WKi8rsYmAt5Ffvi9N7w5LhsFV4ow2v2i4G5hpNcbzceKCCD2_8Q8WT680nFzMre2xu1SbneRJL9NSJM9WIRyHd10aEro86sM2hDJSAVCFA6IDOiECZeFMsqCPd14ud_daWjDY1j420lfJFTKktFYJYSgoLxv68olgDVD9AmboJ_j6brYNcyK8HZxtT0HV_W6-hFAV4VSktHPEHcFhbF6sc1XLGszRJZ9nkUd0-SDmo23lz-K60FlTCS3va5c1hLA-KZVtVsGzTqeHPQOWjV53M54v_guqopuUUQoeS3BHrFp5FVVMvikTEerxcT9Q1CtfWTC0C0qhQR1XgKH8bfUdnB7jeNIlXM1QNOWp7ooNpkgC0UjbOA7EhcujoC49Fli5N3zLyLF9D3oTo0jiZUicC-KsttaNKOFmybKOOb7lTxQFjfNR9_xXak9nfGkUEMF6hdrZoJF6NMFC9gX_zAatb60FU8dzYvoOFgD5cjL3rd0d0PsZVOqPwTOc3evtbvEOjNTA4dTig87fNyLborfvMeTnX2jokT1gNIsDBFrnVgTx_axaks3EyTgZgdtPzcTImAPvudl7MdrPJfW9nPGv_4O8dWpGODCXeEUnGM2WkbopYlnwtDJWOB0tHlMG6DxaV9cGhqD5Y7uniw0VZiVB-tLZHc7yuxU-i6_A7ej8kv63hREepGXfkkg94bycgrfFUappcI0kS6fwFMSKjNxy5dcTQAPUddwFUbIUJNUYVaawu_ZjWLqwY2thTd_r-d3Q-_vu_cPoPTvoRsX9A0Idc_TKIn9QJKtFbMzj45yx4oAXg3mkmmpnx4UPjb40PkCNknMqCFu6AbnyrJgYJnmvXBQoYYX4C7SWi2vVvjcKwi2z4Dt-Lij7t1ncxuzCxmY-T230UboIQMDCCNKKUbciwX9TtHuiGD9C7bL_LOtr-HvQfZixFcLf7-Rfykc1XBMJ882uyrpN9Z9Rlq7RNiOwpI4bFUWNF7xXGeT8b8RyIELsaLLfWd9CPOuDjyuUMNIW-GvDBc7R_pF0fo91r5KPHx-2PHzD6ksH73gqjUTRjI1tJnsDoAGPGt3F7Ot3F9jq-doVHVn1pQt0EsPv3P7rAaNQ10h-8k_6RNyY00La0ThzS6TgZzzu-SVkWCNm2v41qOdLKNOfRwTQ9JXUoCqhsgZoEa-vVuSctPgitsdgo13pn23hH1EqZO3ueimVWPGfP4gmX6Tx5TifZLJs8lUvJJ3y2eMZ9PlnMJ0mR7xMUqZCLdDqRs8X0SS15wicJ54t0kcyT5_FkJrOk4Gm2SPgimWVskmAllB5rfayowz8p7xtcLrIsTZ60yFH7_gcwtyShUd4cPJskWvngr9uCChqXA5hvftVqc099jxSHZoVTnmhM_ga436MkZq7fALUqiEbLEuXX9nFM5Dm-l7d_DHn14In81Di9vCOrKpRNPpa2YnxLNnb_jWpn_40yML6N9_SMb-NV_xMAAP__-g7OGg">