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

    <tr>
        <th>Summary</th>
        <td>
            [clang++] functions marked vectorcall are compiled inconsistently across targets
        </td>
    </tr>

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

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

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

<pre>
    The clang docs for `vectorcall` describe the handling of vector parameters, and link to MSDN for more details. While clang does seem to correctly follow the limited description within it's own documentation, vectorcall is significantly more complex, and appears to be inconsistently followed, especially when return value placement is concerned, depending on the target used.

This example:
```cpp
#include <immintrin.h>

struct HVA4 {
   __m256i data[4];
};

HVA4 __vectorcall example(HVA4 x) {
    x.data[0] = _mm256_permute4x64_epi64(x.data[0], 0b11001001);
    x.data[2] = _mm256_permute4x64_epi64(x.data[2], 0b00111001);

   return x;
}
```
Is compiled down to
```asm
vpermq  ymm0, ymm0, 201
vpermq  ymm2, ymm2, 57
ret
```
by MSVC (`/O2 /GS- /arch:avx2`), and 
```asm
vpermpd ymm0, ymm0, 0xc9
vpermpd ymm2, ymm2, 0x39
ret
```
by clang (15.0.7 using `-O3 -mavx2 target=x86_64-w64-windows-gnu` on windows) as expected.

On linux (using clang 16.0.0 with `-O3 -mavx2 -Wall` on godbolt.org to test), however, the same code results in:
```asm
mov     rax, rcx
vpermpd ymm0, ymmword ptr [rdx], 201
vmovaps ymmword ptr [rdx], ymm0
vpermpd ymm0, ymmword ptr [rdx + 64], 57
vmovaps ymmword ptr [rdx + 64], ymm0
vmovaps ymm0, ymmword ptr [rdx + 32]
vmovaps ymm1, ymmword ptr [rdx + 96]
vmovaps ymmword ptr [rcx + 96], ymm1
vmovaps ymmword ptr [rcx + 32], ymm0
vmovaps ymm0, ymmword ptr [rdx + 64]
vmovaps ymmword ptr [rcx + 64], ymm0
vmovaps ymm0, ymmword ptr [rdx]
vmovaps ymmword ptr [rcx], ymm0
vzeroupper
ret
```
with the exact same result being generated on windows if the `vectorcall` attribute is removed (the windows result is of course expected). No warnings are generated.

It fares much better if the vectors are passed as seperate parameters instead of inside a struct, with all parameters being passed correctly in registers, but the return values still being passed in memory. Through many different tests, I have so far been unable to ever get clang on linux to pass multiple `__m256i` or higher in registers (I believe I tested `__m128i` as well and got the same result), as the MSDN docs for vectorcall specifically expects ("HVA results have each data element returned by value in registers XMM0:XMM3 or YMM0:YMM3").

I am unsure if vectorcall on SysV targets is actually intended to work like this, and the behavior is just poorly documented, or if this is an actual bug, but thought it would be a good idea to report either way.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycV0tz2zgS_jXQpcsqChRp6aCDHa13vFWaHJLKzJxUINAiMQEBLgDqsb9-q0HqZU8ymVTRpgT040OjH59ECLq2iCtWPLNiPRF9bJxf_ceFZracTyqnTqvPDYI0wtagnAywcx5Yme1RRuelMIaVGSgM0usKITYIjbDKaFuD28EgBp3wosWIPjD-AYRVYLT9CtHB5tP612SzdR5BYRTahCn81mhzdYsBAmJL8tJ5jzKaE-ycMe6QPBrd6ohqhNFF7SwcdGy0BR0ZfwzgDpbg9y3aKGifcFzPADoARULvtBSWrCc40rWdweMZs-g6FD4QjApBW-ls0CGivcJBRcIYOpRaGHOCQ4MWPMbeW9gL0yN0RkgkHORUOivR20FNYYdWpcjZdK4ofI0R-oBqyrI1y56G_58bHQCPgtCxfFxkZTY8suvGFZ5rK02vEFj-QbetttFrO21Y_q9bcyH6Xkb45cvTHNjj87AIANtty4tSgxJRsOJ5zoo1y8dt9njzOf1P6tvtTVDPCPki7R0ZX97Zh-N0NJ2xYg0sX8O2JZfbDn3bR5wfy_kWO13OGV_cCVO4smo2yzJ6GF9ewNzZ5f_ELr_YzbLZ7K3di_XxMo93obi_geHra0gJpA1lJiVgdG_kRGiHlT0B-y_AqW0zgnB-82z2ToCPAuldPA77HuNfYqhOsPn05QMwvqA1_vKRA-Mv__70QC_hZcPyJ7E_8rS7PGf6d3F26h3O7CiX7yTugGbHfPm3UId6Z3wxK6bZ9BH6QMXAyuzhYw4PLeEca4Ll6-Oi3JbzhwP9aavcITzUtqdulKo_rVDGCSqVDmV8U0QfLTWh_kj-BkeD-1k5zaZZ6h9vXD_8NrY7Z6F2qnImTp2vqR9EDHGMX-MOuEdPH6mGg2ipkSgEj6E3MYC272v2EuHW7SmDwYvUdrw8fjPyB-cVdNEDK569Oo7Ze02Z1u1FF74tmUz9oHFg_BnK-ah5zrpvu7iXv_F01fiepzzV4luN2Xc0luVfadxJylvJwdLfhEreovmZcwwR-BEfPxWrHzD-3ur_0Lu-69B_vxxT_lMC41HIOKTxkMFQIVVLjRa9oLF7rTfQu6TzjiCIGL2u-og09Dy2bo-KCo-Ez7qjdR2IOEjX-4CXymV8OYVfHRyEt9rWAYTHK4K7un6NsBMeA7S9bKDCGNGfcQ2gBu1OhICK2kPALtm5oSmgbYgoFEHRNmiFIGCYkxTOFBwacTcaQ1RGq1eaomn810QTBvJT9TFBueUEAULUxtyb0BZabJ0_TeFz411fN9AKewKldzv0xB-o6SSbr9CIPUJwdHKoEC30VlQGqTVRMwKiEUN7c-e2F13yBG1vou5MurRx4qce56HRdUOxuzkB3dkrVGg07hFeEwS6yaQ644ukKgIc0Jg0SWoXr21wuOHznAlpIxHAC7O8YQ-JQxEfIxo15EFyzzj_5cvTpZumk6OQTaIpgGbgVkN4UUF1GnnX3TF-32wylj_9vtnkdNI_hq9_bDY545yS7S6jQLTQ29B7pES6wegsfDqFL-NQCpS7QsY-QdY2olWoKNAH57-C0V-JIOsLB6bjV9iIvXaeVP_sQ4TOOW9OF7I6MEM3ZrAeXNjRC1R9fc0pSpEIOsLB9UYRRRVQO6dAKxSEwmPnfATUka71IE7TiVrlapkvxQRXs3Ixz_LlMi8nzWopyypH8VgtlZJzgTsxzxaLRS6yIucKlxO94hnPs2I2z-YFn5XTAh-xkAVWeZ4tdplg8wxboc3UmH1LY3KiQ-hxVfLHLJsYUaEJ6WcH5xYPkDYp9sV64lek81D1dWDzzOgQw9VK1NGk3yspnRl_pqdYw663koh9gFb4r6hur0mMXD5RsTe8XUjvQjjf4KT3ZtXE2AWa0fyF8Zdax6avptK1jL8QjPH10Hn3J1I_eEngA-Mv6XD_DwAA__-ylEI1">