【问题标题】:Match all GNU C SIMD vector extension types in clang/gcc匹配 clang/gcc 中的所有 GNU C SIMD 矢量扩展类型
【发布时间】:2021-12-26 04:39:23
【问题描述】:

目标是编写具有以下签名的类型特征:

template<typename T>
struct is_vector : std::true_type / std::false_type

这样您就可以在 SFINAE 签名中使用is_vector&lt;T&gt;::value。如何正确检测 GCC/clang 中的类型是否为 __attribute__((__vector_size(&lt;some_vector_width&gt;)) &lt;some_built-in_type&gt;

我查看了the LLVM documentation,但没有看到任何内置插件可以检测到这一点。 GNU C documentation 同样仅将其记录为 C 扩展,并未提及 C++。

备份计划是为每个排列专门化模板,但这听起来确实不太好。

【问题讨论】:

  • 您可以编写部分专业化。不过,这方面可能存在已知的 gcc 错误。
  • 将所有此类类型包装在一个已知的模板类中,然后匹配它可能会更容易。

标签: c++ gcc clang simd sfinae


【解决方案1】:

您可以创建一个类型特征来检查它是否是这些向量类型之一。找到一种方法有点棘手,但使用一个对向量进行操作的内置函数似乎可以工作。

在这个 gcc 示例中,我使用 __builtin_convertvector 尝试将向量类型转换为相同的向量类型。如果不是向量类型,SFINAE 将选择返回false_typetest() 函数。如果它是向量类型之一,它将选择返回true_typetest() 函数。

#include <type_traits>

template<class T>
struct is_vector {
    static std::false_type test(...);

    template<class B>
    static auto test(B) ->
        decltype(__builtin_convertvector(std::declval<B>(), B), std::true_type{});

    static constexpr bool value = decltype(test(std::declval<T>()))::value;
};

template<class T>
static constexpr bool is_vector_v = is_vector<T>::value;

Demo

【讨论】:

  • 也可以在 Godbolt 上使用 clang:godbolt.org/z/Pje6qnd1W。很好,我不知道那个内置的。我正在考虑类似(__m128i)vec 的演员表,GCC 和clang 都不允许int 使用它,但它们也不允许来自不同宽度的向量。 (Clang 允许在不强制转换的情况下在不同类型的相同宽度向量之间进行转换,例如 __m128i(由 long long 制成)与 __m128(由 float 制成)。除非您使用 -flax-vector-conversions,这奇怪地使这更加严格。 )
  • @PeterCordes 谢谢!我之前什至不知道任何这些向量类型(我从来没有做过任何 SIMD 的东西)所以我花了很长时间试图获得一个模板匹配,其中向量大小是模板参数之一,但完全失败了。然后我纯属偶然注意到了这个功能,并认为我会试一试。 :-)
  • 这很完美,很棒的技巧!
  • @Shaggi 很高兴它成功了!不客气!
猜你喜欢
  • 1970-01-01
  • 2014-05-22
  • 2018-02-14
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-03
  • 1970-01-01
相关资源
最近更新 更多