<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/60822>60822</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Clang vec_pack_to_short_fp32 implementation generates incorrect results
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
johnplatts
</td>
</tr>
</table>
<pre>
Here is the current Clang implementation of vec_pack_to_short_fp32:
https://github.com/llvm/llvm-project/blob/5f5cf6029852d703e850c5c16b386284d048dd91/clang/lib/Headers/altivec.h#L7518-L7527
Here is the corrected implementation of vec_pack_to_short_fp32:
```
static __inline__ vector unsigned short __ATTRS_o_ai
vec_pack_to_short_fp32(vector float __a, vector float __b) {
vector unsigned int __resa = (vector unsigned int)__builtin_vsx_xvcvsphp(__a);
vector unsigned int __resb = (vector unsigned int)__builtin_vsx_xvcvsphp(__b);
return vec_pack(__resa, __resb);
}
```
Here is a test program (which needs to be compiled with the -std=c11 -mcpu=power9 options) that can be used to check the results of the vec_pack_to_short_fp32 operation:
```
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdalign.h>
#pragma push_macro("vector")
#pragma push_macro("pixel")
#pragma push_macro("bool")
#undef vector
#undef pixel
#undef bool
#include <altivec.h>
#pragma pop_macro("vector")
#pragma pop_macro("pixel")
#pragma pop_macro("bool")
inline __attribute__((__always_inline__, __artificial__))
double Float16BitsToDouble(uint16_t f16_bits) {
double dbl_result;
__vector unsigned short f16_vect = vec_splats(f16_bits);
__asm__("xscvhpdp %x0,%x1"
: "=wa" (dbl_result)
: "wa" (f16_vect));
return dbl_result;
}
int main(int argc, char** argv) {
alignas(16) float input_vals[8];
alignas(16) uint16_t result_vals[8];
for(int i = 1; i < argc; ) {
input_vals[0] = strtof(argv[i++], NULL);
input_vals[1] = (i < argc) ? strtof(argv[i++], NULL) : 0.0f;
input_vals[2] = (i < argc) ? strtof(argv[i++], NULL) : 0.0f;
input_vals[3] = (i < argc) ? strtof(argv[i++], NULL) : 0.0f;
input_vals[4] = (i < argc) ? strtof(argv[i++], NULL) : 0.0f;
input_vals[5] = (i < argc) ? strtof(argv[i++], NULL) : 0.0f;
input_vals[6] = (i < argc) ? strtof(argv[i++], NULL) : 0.0f;
input_vals[7] = (i < argc) ? strtof(argv[i++], NULL) : 0.0f;
__vector float src_vect_a =
*((const __vector float*)input_vals);
__vector float src_vect_b =
*((const __vector float*)(input_vals + 4));
__vector unsigned short result_vect =
vec_pack_to_short_fp32(src_vect_a, src_vect_b);
*((__vector unsigned short*)result_vals) = result_vect;
for(int j = 0; j < 8; j++)
printf("Float32ToFloat16(%g) = %g\n",
input_vals[j], Float16BitsToDouble(result_vals[j]));
}
return 0;
}
```
Here are the results of running the above test program when compiled with GCC 12:
```
$ ./vsx_vec_pack_to_short_fp32_test_021623_gcc 1.518 2.4447 3.3932 6.4842 -1.4912 -3.3938 -7.532 6.6662
Float32ToFloat16(1.518) = 1.51758
Float32ToFloat16(2.4447) = 2.44531
Float32ToFloat16(3.3932) = 3.39258
Float32ToFloat16(6.4842) = 6.48438
Float32ToFloat16(-1.4912) = -1.49121
Float32ToFloat16(-3.3938) = -3.39453
Float32ToFloat16(-7.532) = -7.53125
Float32ToFloat16(6.6662) = 6.66797
```
Here are the results of running the above test program when compiled with Clang 15 or Clang 17:
```
$ ./vsx_vec_pack_to_short_fp32_test_021623_clang 1.518 2.4447 3.3932 6.4842 -1.4912 -3.3938 -7.532 6.6662
Float32ToFloat16(1.518) = 1.51758
Float32ToFloat16(2.4447) = 0
Float32ToFloat16(3.3932) = -1.49121
Float32ToFloat16(6.4842) = 0
Float32ToFloat16(-1.4912) = 3.39258
Float32ToFloat16(-3.3938) = 0
Float32ToFloat16(-7.532) = -7.53125
Float32ToFloat16(6.6662) = 0
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMWEtz6yYU_jV4w8QjQC8vvEjsuneR6aJN1xqEsEUuBg0gO_ffd0APW66Vm3vbZprxxAIO53znwXewqLXioDhfg-QJJNsFbV2tzfpV16qR1Dm7KHX1bf2FGw6Fha7mkLXGcOXgRlJ1gOLYSH7kylEntIJ6D0-cFQ1lXwunC1tr44p9QzAgjyDaguixdq6xfoR3AO8OwtVtuWT6CPBOytPw9dAY_cqZA3hXSl0CvEv2CdunEV7lCa6yiPA8iVjCUFqSPMV5XEVxXlUrBPCOeWRekfAbv3BacWMB3lHpxImzZQ0wec4SlD88ZwnOOlzd_4mj2hjOHK9-3EmQRv0nDK3fyGBRCCWF4kXh9zttYKtC-CsYdMCieHx5-f2PQhdUwG7rjCGc9xr2UlO_kQK8gTdzJcArCLKnXhX8m1WhvJjhlkJAtvCi9VoC4FVRlK2QTqjiZN-KtxM72aZuAM6D3RUgo4lZC-VPWyinFqDhrjVqzECQ8S74AHSmJhtAtr2bk2m-KXTcOtgYfTD06HGea8FqqDivLHQalr4ejo2QvIJn4epQIQ_WVYBsGULw4ciaFpBto8_crKBufKVYnwBXUwcZVV5Fa3nltbGas69BheG2lc76mvLD--mGuuEm1N5chQFMhGKyrTgEZGNdJZRb1oD8MrMsRfnestDvrVIpDupaYBBrDD0cKWxaWxdHyowGOAcYdykHGPvEfEe2EW9cfky01HoqOci3quL7vhRvJjv107mgZ6rhyt8Lacy6q5sPezsVfc_ZqeR9Xzs68affOSPK1vGiCPL-YMoz_WZHxulOBzVO7AUTVPqZ1aiu0m0pOdx54kDpk3D2RW_DHMB5K5RDaeHgHqVFKZztaWU4kP3mqpRFV82ADGtFcZ_ovCa_EkjB17z13cYCnF_ZuFZD7bF3Db9ZdqqbqoEAJ28RwBv_jXxwejzDHyCP0E-T7ZkCjP2hvsI4uD6IjTIDtj4-I4iBeO74eeGYPi0OHqlQAOf-kZoD8-FnNTUAPwL86KdON1EMh4r6EKDUL3UkLlTTuuJEpQXJUw6S7RWe2x1jnjp0M7v2vjYDLhGijzxV-sdNB9QT5wTZBEIEkm3YZp1xeg9wHlxJngTAT_6TbL2rv_35_DwNHpzqQYMej-Vi3Bsmu48pD4mLltF-3gr-FCvkU6zEn2Il-RQr6adYyf4rK5enkd-602oNCxNFuE9d81E4956YmVbW3ewLi6sr7DcnZ85K-RNWwtkfDEGAn2B8S3RzpD3QSs_blxvf_QvqJRg-oBfQt96NoGfsdrivOS3kZXuNZyY9F657DTsiz26voRTy8NjnfOwF4a8xQrl912xCRyT4RfetMcwmhwFCeE42KrTmzT3CfO0L6n5rnTJ1J3vTdcbeMjag6E7fmb3bUsNv75mmVUqoQ5impT7x6d33XHN1c9f9dbOBaPbXDcAxXAK88zf3-9VQeANFhFGKSXFgDKJlgnKIl3EcZ5AsyYpgmC7jPMbwAS3jFcLwIUzn8CFbJmE1TdO-xd9JSlA4ZMUPsiSfFe7sDtJ-lBA0K93BG6T9CL-ju_NikA4jMi_dOzuI98N5LH1QRnk_jBMyLx-CN4r7EcLJO-BDkEfwaZqtsk-psO5lAkqgNsNz9i_VG-vU_Y8qLvpgrX23HKbFNq_2psy-V8M3VfaO3n9SXtHd5C6qNalWZEUXfI3SLE2yLEdoUa9LVOVRGccZojFjqMrKJEYMI7bHrFzRaiHWOMIkJD2KCEHLPGU8RnTP4yiuEkpAHPEjFXIp5em41OawENa2fJ1GOcYLSUsubXgPhrHiZxgWPbEn24VZh5dSZXuwII6ksM5etDjhJF93VTvz-_3mBdKBK_97nlsoVP-WaTg-i9bI9Q-_IwtYLcC74MtfAQAA__9aubcQ">