llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.43k stars 12.16k forks source link

`target_clones` attribute does not support function templates #116501

Open Arastais opened 2 weeks ago

Arastais commented 2 weeks ago

Currently, clang does not support using the target_clones attribute when used with template functions, even though GCC has supported this since at least version 6.1. To clarify, neither GCC nor Clang currently support function multi-versioning with template functions when using the target attribute (unfortunately). However, GCC does support it when using the target_clones attribute, while clang does not.

Given the basic example:

template <typename T>
[[gnu::target_clones("default", "popcnt")]]
std::uint64_t pc(T const v) {
    return __builtin_popcountll(v);
}

int main() {
    for (std::uint64_t i = 0; i < 1'000'000'000; ++i)
        volatile std::uint64_t ret = pc(i);
}

GCC 7.2 compiles this correctly, while clang 20 complains:

<source>:5:15: error: attribute 'target_clones' multiversioned functions do not yet support function templates
    5 | std::uint64_t pc(T const v) {
      |               ^
<source>:11:38: error: no matching function for call to 'pc'
   11 |         volatile std::uint64_t ret = pc(i);
      |                  

Godbolt project: https://gcc.godbolt.org/z/aqbr79chj

llvmbot commented 2 weeks ago

@llvm/issue-subscribers-clang-frontend

Author: Artin Alavi (Arastais)

Currently, clang does not support using the `target_clones` attribute when used with template functions, **even though GCC has supported this since *at least* version 6.1**. To clarify, neither [GCC](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90260) nor [Clang](https://github.com/llvm/llvm-project/issues/40958) currently support function multi-versioning with template functions when using the `target` attribute (unfortunately). However, GCC does support it when using the `target_clones` attribute, while clang does not. Given the basic example: ```c++ template <typename T> [[gnu::target_clones("default", "popcnt")]] std::uint64_t pc(T const v) { return __builtin_popcountll(v); } int main() { for (std::uint64_t i = 0; i < 1'000'000'000; ++i) volatile std::uint64_t ret = pc(i); } ``` GCC 7.2 compiles this correctly, while clang 20 complains: ``` <source>:5:15: error: attribute 'target_clones' multiversioned functions do not yet support function templates 5 | std::uint64_t pc(T const v) { | ^ <source>:11:38: error: no matching function for call to 'pc' 11 | volatile std::uint64_t ret = pc(i); | ``` Godbolt project: https://gcc.godbolt.org/z/aqbr79chj