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

    <tr>
        <th>Summary</th>
        <td>
            Remove __attribute__((target_clones)) requirement in function prototype
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            c++,
            clang:codegen,
            missing-feature
      </td>
    </tr>

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

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

<pre>
    Let's say I have a library that I want to share with multiple targets
```c++
#include <array>
#include <cstdio>

using Vector = std::array<float, 2>;
using Matrix = std::array<float, 4>;

__attribute__((target_clones("default","arch=core2","arch=znver2")))
Vector multiply(const Matrix& m, const Vector& v) {
    Vector r;
    r[0] = v[0] * m[0] + v[1] * m[2];
    r[1] = v[0] * m[1] + v[1] * m[3];
 return r;
}
```
and I want to use that as below
```c++
#include <array>
#include <cstdio>

using Vector = std::array<float, 2>;
using Matrix = std::array<float, 4>;

Vector multiply(const Matrix& m, const Vector& v);

int main() {
    Matrix m{1,2,3,4};
    Vector v{1,2};
    Vector r = multiply(m,v);
 printf( "%f %f\n", r[0], r[1] );
}
```
Godbolt project: https://godbolt.org/z/3hd4MrzsG

GCC will be happy to compile and link the above two files together but clang++ will complain about undefined references. 
```
ld: CMakeFiles/example.dir/example.cpp.o: in function `main':
example.cpp:(.text+0x2a): undefined reference to `multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&)'
```
To make this work, I have to add all the targets in the prototype as well as in 
```
#include <array>
#include <cstdio>

using Vector = std::array<float, 2>;
using Matrix = std::array<float, 4>;

__attribute__((target_clones("default","arch=core2","arch=znver2")))
Vector multiply(const Matrix& m, const Vector& v);

int main() {
    Matrix m{1,2,3,4};
    Vector v{1,2};
    Vector r = multiply(m,v);
 printf( "%f %f\n", r[0], r[1] );
}
```
Looking at the object files generated, it seeems that the main difference is that GCC generates an indirect link for the naked prototype while clang generate an indirect link to .ifunc and that requires knowledge of the target attributes. 
```
$ diff nm.gcc nm.clang
3,4d2
<                 U _GLOBAL_OFFSET_TABLE_
<                 U __stack_chk_fail
6,13c4,11
< i multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&)
< t multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .arch_cascadelake.3]
< t _Z8multiplyRKSt5arrayIfLm4EERKS_IfLm2EE.arch_core2.0
< t multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .arch_haswell.2]
< t multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .arch_sandybridge.1]
< t _Z8multiplyRKSt5arrayIfLm4EERKS_IfLm2EE.arch_znver1.4
< t _Z8multiplyRKSt5arrayIfLm4EERKS_IfLm2EE.arch_znver2.5
< t multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .default.6]
---
> T multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .arch_cascadelake.3]
> T _Z8multiplyRKSt5arrayIfLm4EERKS_IfLm2EE.arch_core2.0
> T multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .arch_haswell.2]
> T multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .arch_sandybridge.1]
> T _Z8multiplyRKSt5arrayIfLm4EERKS_IfLm2EE.arch_znver1.4
> T _Z8multiplyRKSt5arrayIfLm4EERKS_IfLm2EE.arch_znver2.5
> T multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .default.6]
> i multiply(std::array<float, 4ul> const&, std::array<float, 2ul> const&) [clone .ifunc]
20d17
< r std::piecewise_construct
```
The request is that clang emits targets in a way that the target attributes won't be necessary in the function declaration/prototype.



</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzkWFuP4yoS_jXkpdSWjXN9yEOuvaPp0UgzvfuwLxaBcswGQxZwpzO_foXtJJ50ekZ7Wpo-c05k-QJUUXx8fBRhzsmtRpySwZwMlj1W-cLY6T_Wj5YJtL2NEcfpA3pCRw4cO8IHKNgTAgMlN5bZI_iCefgAB6Y9eAOuYBbhIH0BZaW83CsEz-wWvSPxksQzMoybixM6D1dTSlOpuaoEAkkXzFp2JOnqVh13XkhzqazvlZN6C_9C7o0Fki7BeUHSGUlnratFrgzzhC6ABtN03rX7xLyVzz-x63ftmnuWMe-t3FQes4zQMaHjZqgZV0ajq4uowJxVyhNKCV0QSpnlBUmX3Fik14Xf9BPapnTSXnVP7chaRI-EjrnRzreREzqEMsTYFDaNQ-EToRMgozZoADhBZM8jCYWWDOYxGSxrBJ7OH3QG5eVjXtck3RpKBssXjpJXHSWvOkq_c2TRV1Z3YiSj5RV3mk-mRYd5lcOGjMzBBpU5_OX49gYWXHmS2kPJpK4ZekWRNrqSjOYJoYtA0JTQRT_MQvqSSk_ndrfrG3w6MYcYvwsJ9lZqnxM6hpr5gxzCjQwWulkfZ4Ke3lvyTH7KkHsjNkZ52FvzH-SepDMovN-7gDldE7reNg0iY7eErr8Ruk4L0f9kv7n7Ll73iwUcpFKwQSjYfn8MhOOm3EuFEGiopN6BLxDYxjwh-IOBXCp04M0WfYEWNpUHrpjeNjRs3AUXikkdzCoPlRaYS40CLOZoUXN0EdwcmQq8gcUntsN16IjQNT6zcq8wEtJ2vvh-H5nQVmrIK829NBrIMG6mfxSQqB122tfojCOPz57QefxMWY317FZ8AYjg7TK_P6B0pUi6avhJ6DAU_WDdXDeehGhvQfFooGS7sPilg4Oxu2De7lPeABMCmFL17LQ7UcAifO6t8cYf9xg044BKhafUtxH_LSXjt9ii_qbi9GDMLswt8zUZzSZIVCsbW9RomUcRvEoPDhFL1-xvoXHAB4TMT6tQtnVBqE62DpgGqYW0wW-tULmxtblmOxQd-h-KIGS1PJ3NX1p7A5EMGlJLXt2fxf9W0qKDnTYHhWKLYPLOUoMz_V4TMkL79UBAl9GW8_BoZLKurSdX0LZpuoDr3z8hu3_4PJ89ZJ_X66-rx-xxNn9YZT80yJxnfJfxYpflTKqmbZCjJOX98Egu5hJ-ibSd-_O_pD8gg3ktABCFZZ1x5jgTqNgOozoZ68ST_Xt8CunLx69-ULv_kD-U_dXqy8evWXilq1XrKEhGFL_3eArmgpxH9Gos7xGLY1ocN1aKLUbJW7CtlTeJ-m9zQKPBOyLS7jTR8AzE3d3dKZ4VPP6p2B_ieQv732s8t9j_XrG8xv7_G9tr9v8xBx32vwMiL9kf2v6aLaYTRr2Hn0OgsUhGF0mwF697iRwP0mFW-7EV97cT8ALrRACdPyciTS6BpfSum3UzOLDjJY15kSTAwYRTiQ8HLY0cnWP2eErXz8cXgVwxy8I7oetzGhN1s8jm3hPTVEzSCevhNBmOxkky7if9XjHlo0kyFuMRo2POk1Hax-FwQkdc9PlgyGLRk1Ma0zRO42EyjOOkH40wxREOxslEYDrOU9KPsWRSRUo9leEA2ZPOVTgdJjSZ9BTboHL132qUnv56OKXSTYKTzrgRuEV9Li-lC9n-XY7MVxZD-WDZs9PQw92m2jrSj5V03l369NIrnH7BMhw7f57th3z9lLSVqP13p8IzkL3KqunVQVn6otpE3JSErkPv7ePudLSm63r44SBaI_C_AAAA__8kJxJX">