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

    <tr>
        <th>Summary</th>
        <td>
            LLVM miscompiles passing/returning `half` on several backends by using lossy conversions
        </td>
    </tr>

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

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

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

<pre>
    Consider the following IR:
```llvm
define half @to_half(i16 %bits) {
    %f = bitcast i16 %bits to half
    ret half %f
}

define i16 @from_half(half %f) {
    %bits = bitcast half %f to i16
    ret i16 %bits
}
```
As the only operation involved is a bitcast (in particular, there are no floating point type conversions in the LLVM IR), the values returned from `to_half` and `from_half` should be bit-for-bit identical to the value passed to them as their only argument (just a different type). However, several targets pass/return `half` as a `float`. On these targets, LLVM will use the default float conversion builtins (such as `__gnu_h2f_ieee` and `__gnu_f2h_ieee`) to convert between `half` and `float`. The issue is that these builtins silence signalling NaNs which changes the NaN payload, meaning that the roundtrip of `half` -> `float` -> `half` is not lossless and causes the generated ASM to violate the semantics of LLVM IR. This miscompilation is similar to #66803.

By inspecting the assembly LLVM emits, I've discovered that at least the following backends appear to be affected (in brackets are a specific target triple that I've checked):

- Hexagon (`hexagon-unknown-linux-musl`)
- MIPS (`mips64el-unknown-linux-gnuabi64`)
- PowerPC (`powerpc64le-unknown-linux-gnu`)
- SPARC (`sparc64-unknown-linux-gnu`)
- WASM (`wasm32-unknown-wasi`): Already reported in #96438

As none of these target's ABI specifications (that I've been able to find) specify how `half` should be passed (nor does Clang support `_Float16` on any of these targets), and given that these targets are a subset of those affected by #97975, I'm filing this as a single issue as the ABI has probably been selected as an automatic default by LLVM rather than a deliberate choice by the backends. Ultimately there are two possible solutions: either fix LLVM to codegen lossless conversions between `half` and `float` when needed for the ABI (one way to do this would be with a new pair of builtins that don't silence signalling NaNs), or change the ABIs to pass/return `half` without converting it to `float` (probably using the same ABI as `i16`, but some targets might have better options).
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyEVl2P27gO_TXKC5HAURI7echD2t7BFtj2Drb343Eg27TNrSwZkhw3__6C8kc8vbsoMMjYskgeHh5SUt5TbRCv4vRBnD5tVB8a6645YnCIfpPb8nH9aI2nEh2EBqGyWtuBTA2f_xCHm0g-ieQm0mT80_rejkslVmQQGqUrEMck2Dd-FPJM-xSEPOUUvJAXENmH0QAAeL0CcfgEOYVC-QCrzRBs9Pbc7TBM_uVpWhbZp-lhDSJ6OSaVs-2M4mn3FxhiuDWMZTeDoH36HsM6o59QzLyMrzcfKbRGP8B26FQga4DM3eo7lkAe1BKSmTLQKReo6LVyQn5kY4egHIKxUGmrAtehs2QChEeHUFhzR-fJGg9kYrDff__PFy6VvEwe4K50j56R985gCUwLiHQpUZqAMiWvPAlLE_CN7XUJOTLEbWXdNqcAVKIJVCjNzCzeoVPeYzmttaBi4uTG1JWr-xZNzPHP3gdQUFJVocMpDyEvO_jNDnjHmLfnBw6hXI3BR-9CvowZMNAFNzPIwJkbkSY7-GdkweNsy-4iJQNpDT1_aBBKrFSvw8jpikXIe9KBjGeovi8ajiDS5O2tNv1bI6s3QsQVY-OHSjbzB5ZXsJPLADmGAfE95onrBfK_GgTyvudfCI0KUwYLFk8aTYHArau0Zg18VV89DA0VDRSNMjWOSvuqvkKnHtqqkhNvURnePTsFZ3tTBkcd2GqNaSsO_1iDWhbmDeTB2ADaeq_R-5hEoXo_xa3RsLqxhNu3L5z_naxWYSTbY6tYM56DTvLkrMlDS76wbUd66gzOtSWtHPsQ8pCm5-SwW3f4hweQ8R0WYUwMgZXX5voxusaWxqJ_FjK7I5Qc4Y6OxcksqAAaud_ez7ZcFd_RlB5U1-EYPkdQVYUFZzU2Z-54V_CxIxUwCqqomKQGzKvGMcwUvWiw-I4lN-MyOuPvFn7DH6q2hl0zz-PbtjffjR3MVpPpf2zb3utRU7PVl8-v3yaTljqfHlH_ZFObXuWUHt_bvdoB3evHybTjt65Ijxr_3_q94bfX2x-zme-UK9Ljr0z-yxoYLQbl24NcDAbladp7uMFNO1TlAxx21jHLxGwcLunxcF5zdWPtGWT1rFtbyMzD7cPnpQ5RQ7Fz1yXIuf1UzoWxUJHhYkwmD2jssFb5c-RN80zIs7EOSosePmplavB9x2hj779wt-xTtrQGlHn8DNFPU5i7paY7mnV7z8NtElOfewyjA-tX0ssfkZTskp1mWbdQkR7lz0cIz0BPptbzGBmnb-SmUR46Z3PFDRKp8KhHx2xnQPXBtipQsczEfOokp_j4YcSGBzZqymOPQ9FYKpD3cZS5c3bwbx2oVQH1Y3VwhcFCZ70nroC3uo9F4vIjRf8V_RjjxalZYo3mOWbW59uvRykMDRowiCWfctYtLAh5ZgEN6sFRSjsSN8zFHig0oMDgAJ3iQ6t6zt5YsNIaIbPwd4N4qrJ10yye48YrzN-eXRzV9vPpE8cZhTj3VhkJeV7K1_t55HnVjomNpxNFDTKEvA_gbfsUV0t1w9eZ2AghoAPbjRWQl92mvB7Ky-GiNnjdZzI5JtnxJDfNNTsm8qJknh_2l-M-yVK8oCzSNCvKBKvssKGrTOQxyZJzIk_ZYb8rE3lSpdxjWRa8Lo4Jtor0ji-IO-vqTZTm9ZJdzvuNVjlqH--gUjLt8aOQkq-k7so227yvvTgmmnzwTy-BgsZr1MtyduB4QSBTLzwzUSuqrVmuFMugz2dCWWyPtdI2vdPXJoSOZSrki5AvNYWmz3eFbYV8iXfe8d-2c_ZPLIKQLzEFrvSY4v0q_xcAAP___bfApQ">