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

    <tr>
        <th>Summary</th>
        <td>
            If `vmaxss` already handles NaN like `fmax`, why is `fmax` so complicated?
        </td>
    </tr>

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

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

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

<pre>
    This is a possible missed optimization in clang++. It's not a libc++ issue because `fmax` is just a thin wrapper around `__builtin_fmax`:
https://github.com/llvm/llvm-project/blob/1150e8ef7765f43a730575bd224eda18e916ac1e/libcxx/include/__math/min_max.h#L28-L30

## Code to reproduce

```cpp
#include <cmath>

float fmax_(float x, float y) {
    return std::fmax(x, y);
}
```

## Possibly suboptimal output

This compiles to (`clang++ -O3 -stdlib=libc++`) (https://godbolt.org/z/fn4v99sv8)

```asm
fmax_(float, float): # @fmax_(float, float)
        vmaxss  xmm2, xmm1, xmm0
        vcmpunordss     xmm0, xmm0, xmm0
        vblendvps xmm0, xmm2, xmm1, xmm0
        ret
```

Is this a missed optimization? The latter two instructions are solely dedicated to the handling of NaN. Namely `vcmpunordss` detects `isnan(x)` and `vblendvps` selects `y` or `max(x, y)` depending on the result. However, I don't believe this is necessary, given the documented behavior of `maxss`:

```c
MAX(SRC1, SRC2)
{
    IF ((SRC1 = 0.0) and (SRC2 = 0.0)) THEN DEST := SRC2;
        ELSE IF (SRC1 = NaN) THEN DEST := SRC2; FI;
        ELSE IF (SRC2 = NaN) THEN DEST := SRC2; FI;
 ELSE IF (SRC1 > SRC2) THEN DEST := SRC1;
        ELSE DEST := SRC2;
 FI;
}
```

\- https://www.felixcloutier.com/x86/maxss

To me it seems like the NaN-handling behavior of `vcmpunordss` and `vblendvps` is already covered by the first two `ELSE IF` branches. Am I missing something obvious, or is this a missed optimization?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVk-P4j4S_TTmUmqUOEDCgUN3QzRIs-xqug97Q05cEM86dmQ7_JlPvyqHphl-zIym1QJsP9efV_VsC-_V3iAu2PSFTZcj0YfGusVKeTRHccBRZeV58d4oD8qDgM56ryqN0CrvUYLtgmrVDxGUNaAM1FqYPeMvjL-MYR0Yzz0YG0CAVlU9LIDyvkeosBa9R2CzZNeKE5sl5OJ77wkdGmXg6ETXoQPhbG8kAbfbqlc6KLO9bGHZM0uWLHluQug8jXjJeLlXoemrcW1bxkutDx9fT52z37EOjJeVthXjZZpOEyxwl-ez6W6SiTxLpvm0kpxPUIq0wHk6E3WKZEBV9enEeKlMrXtJU9ttK0LDeNkqs23Fadwwnn3lxdPXLBniunzyjPEMXq1ECBYcds7KvsafMLNk-K-77rrr4gpY9lpHV9nqds9OWxGAuNgyXgyjE-OvMPw8Mz4Hlr8MYAAAh6F3BnyQxFX2HGnkRdxDaJZdwCxf3oX1IJ__DN1wBt9XsROEBtuHrg-34Ng9tW07pdFT-owXlOZnq8DTvzN48kFqVbFs-dkq5JZS4MVdfa2srA5j6_aMlz8YL3dmcpjP_aGgJB6xKnx74eyWrStXMfdnoKzYJPk15sok_R1acfIe4NS2nFCntk0v38kdsm673lgnCQ4wID6Qj3dUGo08dP4W8wcvDsNvirb2JCtS8QPxsqyE9wZBixDQQThaUMYH19e06kE4BG816jNIlKoWASXVMjQIjTBSK7MHu4ON2IxhI1oCsllykzcJXGLAOnhaUd4IM7TenJbEoPBr2jTnUX_AzzS2jn7et2y026GRMQQTQ3Loex3G8MUe8YCOsGuQ1jCeB6hQKzzgwIbyYLBG74U7E2yvDjjYkLbuWzSUaIWNOCjrKMMhgpjP9fS5V_Aw_tfzfxkv3r69xnK9fXvln815K8p1GSUxQIFlS0jGse8jJ3Ga30zTyvuX1QaWq7d3iDpeDtazl5_7YfX1bXWxfjW9EZvfGYBy_Qcz_K_N_DOM1QcbDw2kjyP4dbo3zv5wbk1fn-Dno-R4PI53qNWp1rYPCt3l1jgVMzrXY6VvDzMLLYIK4BFbD1r9D2OzbMTm6aqDu3a5E8GjTidZaodCnqG2B3TUc-doeKecD1GPbJZcmKQdlROmbtCP4bmFdZQ0ufa2Rbo892Crg7K9p9azjhz8VvwjucjkPJuLES7SPMlmc55O8lGzSOeVzHZ1OknTaoepxEIKOcWMz5I6naZ8pBY84VnKeZ5OJ_MkH8sizybZPJvSRTqbCzZJsBVKj-kGpiN7FB8Ai3w2mRQjLSrUPr4_ODd4HF4HjHN6jrhFvLWrfu_ZJNHKB_9pJaigcbEeKP6Q5JXGWAz0VJihSp_vDKLk2JyJk5vHh7fxktLD2UaU9E4v_vpdEcP3jJcxvf8HAAD__9hZwAI">