<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/123999>123999</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[AArch64] negate + exctract high half can be done with vsubhn
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
dzaima
</td>
</tr>
</table>
<pre>
https://godbolt.org/z/hbGc6M3K6
The following functions:
```c
uint8x8_t neg_narrow(uint16x8_t a) {
uint16x8_t b = vmvnq_u16(a);
return vshrn_n_u16(b, 8);
}
uint8x8_t neg_narrow_vsubhn(uint16x8_t a) {
uint16x8_t ones = vdupq_n_u16(0xffff);
return vsubhn_u16(ones, a);
}
```
produce:
```asm
mvn v0.16b, v0.16b
shrn v0.8b, v0.8h, #8
```
whereas they could produce:
```asm
mvni v31.4s, 0
subhn v0.8b, v31.8h, v0.8h
```
This is especially meaningful in a loop, where the constant can be initialized outside of the loop. (whether it's better or worse for a single use depends on architecture)
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyMlE2PpDgPxz-NuVhTCgEKOHCgn1Y9h9Xe5l5KwJCsUklNXqju_vSrUNUv09qVFiElcv62f7biiBD0aokGaJ6geS5Eisr5YX4T-iIK6ebXQcV4DVCNwE_AT6ubpTPx4PwK_PQG_KTk_6fjn9UfR2AjsPGnIlycMe6m7YpLslPUzu4B2AhHdv8nYGPSNnYv3TmipfVshffuBrzL5vK42wXwHqF9AjbiF7NEqJ5xu2z21zmVR-BdFkK169BTTN7iFpS3Z_sQSOD_w-5DBe3znfafGM5bSFLZf0f5yuIshTvOnK6_PvKxl2VZlk-qD6gc-aHJrhlLfMd6bxKw8erdnCb61j0RLjvH_btsFjd2KI97kY_d53HuQ143dujeFZ3KG-BV9y3fTZEnETAqesXJJTPjf0TQe46qPNR7UewrQS76N4KqfCDcWX5n-Kl0QB2QwpUmLYx5xQsJq-26JIPaokDj3DW777gZFidnQxQ24iQsSkJtddTC6Dea0aUY9Ezoll2anQ8IvLspioo86gi8DSgpRvLoPN6cD_kWexQYtF0NYQqEM13JzgGdReEnpSNNMXkC3hfzUM191YuChrKt2qbtWV8WamgX2cmalUtddbLv2mapS-IN649SCilZoQfOeMNKzjlryqo8yKpv-4ZR3VJd87aHmtFFaHMwZrvksSt0CImGkld93xdGSDJhH1_OLd1wPwXO8zT7ITv9kGkNUDOjQwyfYaKOZp_7cfSTOtbQPOchEJEQ-BPSyxS9mCIqvSpUwizvrZ2dJbzpqB7XuUjefH8ldFRJHiZ3AX7KGR_Lj6t3f9EUgZ92zgD89ChkG_jfAQAA___SuGEw">