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

    <tr>
        <th>Summary</th>
        <td>
            arm_neon.h intrinsics should be target-gated, not preprocessor-gated
        </td>
    </tr>

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

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

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

<pre>
    Clang's intrinsics headers on Arm contain code like:

```
#if !defined(__ARM_NEON)
#error "NEON support not enabled"
#else
```
or:
```
#if __ARM_ARCH >= 8 && defined(__ARM_FEATURE_AES)
#ifdef __LITTLE_ENDIAN__
__ai uint8x16_t vaesdq_u8(uint8x16_t __p0, uint8x16_t __p1) {
...
```

(Generated by https://github.com/llvm/llvm-project/blob/main/clang/utils/TableGen/NeonEmitter.cpp.)

This means that one can only use Arm intrinsics in TUs that mark the feature as available for the entire intrinsic, e.g. via `-march` flags. In contrast, the x86 intrinsics are consistently defined, but tagged with `__attribute__((__target__("whatever")))`:
https://github.com/llvm/llvm-project/blob/main/clang/lib/Headers/avx2intrin.h#L18

The x86 variant is both easier to use, as it doesn't require messing with your project's build definition, and safer, since you can just write a `target("avx2")` function and then gate the unmarked -> marked transition on some suitable CPUID check. (Or perhaps even use [multi-versioning](https://gcc.gnu.org/onlinedocs/gcc/Function-Multiversioning.html), though I believe target attributes are usable even without that.)

In contrast, Clang's Arm story requires messing with build definitions and risks ODR violations. Suppose your NEON-enabled TU included some inline functions, where Clang happened to vectorize code and use NEON instructions. If that copy of the inline function won, the resulting binary would inadvertently require NEON, even if the overall target wasn't meant to require NEON.

GCC fixed their Arm intrinsics, back in 2015, to be target-gated instead. Arm intrinsics would be much more usable if Clang could get parity here.
https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=ae5e29239e28818f807cf11775c95c4243d9a256;hp=b8c7c62b2dbbdf355adb56d8250e68222ae0febb
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJytVl1v4jgU_TXwckWUBBLCAw8M0JlKs51Vp_OMHMdJPA02YzvQ7q_fY4cWivqy0koRcfxxP84595pSV6_LdcdUM0rnlqRyRioruaVWsEoYS1rRyuyJa-WYVHhXgjr5LEbT1SjejOK33zw-P8NnOpU1jdKkErVUohqlxW63evxr97D98TBKF--7hDHaYGPqF8j2h4M2jpR2JBQrO38yvWzurPjUnTaXcD4LZPC9elx_o9F0O5puqIDPHA_dBni3XT39etzuVtuf13HKGhth5_v909P37W77sLlfPex2w_puxyT1AK94SfKdoyMTtvqz6wtYvZre7Q7xKF3Tx6kEbmg0_zKYiqLo8zzOgRRfhRKGOVFR-UqtcwfrU0_v8DTStX0Zcb3HR9cd316Tg9G_BXf4LDtd4rUHlXjxgfi73snO4v3kEYcDDB-EVtu9dE6YiB8O0QWL8PvUSkt7wZQl1zIHlQjiTOHdvVJvRdDMlZqgnKdf5717Zp4xElQL5nojiFliRyY7751qyMEvCuUk1t5teOBE1ER0lIwAywRmeIsB1R1rbET3KojUMOv8Xm_jpcivg2Cwhy1WWgfrCPSd-zWVvSPHmga4ngCj9wBWHc5iRYDotAgSccw0wp2_0xPyEUdhvEgB0PCAsjcx_k_8dNJPfhsqEiN2fEmHvKIW2vyeFB-5GTI_MiOZcgSmSo2UBLNSAFztCfI5A3fpqNLCwtnckRF_eo_5XlgrVTMA8ap7Q-8BokeUveyqATrppFbBkqrIstoDsSac5cKfC4r43VtHJyMdePaoDgAO8Pk8ztB5HnvFvcFgDfQpaoBuILJXXjTgZoLypfMYVIPLcAKP1XuB_iFdUNH671_3G-Kt4M8RKr34gRyEadnBEvhSQaKj7Mu-75ycgEALK0h5lG2w-YY1zqNG9ZE2ngoI3EtGczss4ffuHPfkL2_tYixq3b4LmvBq1H3T0j2VopOIgAYY6F1hgzp7G6IPIXr0tVclNHZbfjdavzRwX3bWafP6Rqb9yOYteTaAbaR9tvRj84ji0h0LCxH99M3YikEBvj1Pzi0ZpYyy4l1fYRxwlwGVdwatD-rUCmQUQiMAf0Dfqrz4jhCSNvIfMdwl3r9nI_R_FKozPT8HcF8PDYPrwyvpOijhxhOdBgH6JSTrCYC7UioGCE66R7IYVyDlXPJvGh_uofUAtRxsa2xjXffGzYmd68L3OedDvz4cXfPxdb2mWr6IoFtpbrpf6C-MP_sumMZJFgLWkMLZ06QJ_dwnjxKPbnvnkAZ273ve0l5fdIK4B3x52OKDPqDoHS4GYB992oM-qBkdyU9P7w64E8MSJqZfGL7QpdD-K1nXmGgxwUQm0kU6XYi0KJKiLuI5r5NkPs_4IuOzdDatFizNcr_dmysLPud5WqZVWVb1NMtYVWZ5VaRZLPIiRfWLuBZlOa6WODldsLGTrhNLZvY7hdsnaq9BsO0bCteYeST9f4WDEWhRHErXZlgZ96Zb_uf2K63tha_sLJ8V8bhdZgmP53kdcz6r2GJe5AuWxzxJqoKVdTXLx7i08K9kiV6CRqbEiYIJ39SyzVgu0zhN43mSJItZFk-jLK6LapFXGUtqPi3ZaBYL9Pou8nF4TsZmGUIq-8ZiscNVZS-LDJXcKCGCO9hnPVqEWVbsKKtSqHHwvQyx_wt5QDfZ">