使用 constexpr 函数(而不是文字)构建 GCC SIMD 向量常量

Building GCC SIMD vector constants using constexpr functions (rather than literals)

我正在使用 GCC's vector extensions (__attribute__((vector_size(x)))) 编写一段代码,需要几个常量掩码。这些掩码非常简单,可以按顺序填写,但将它们添加为向量文字既乏味又容易出错,更不用说限制向量大小的潜在变化了。

是否可以使用 constexpr 函数生成常量?

我试过生成这样的值:

using u8v = uint8_t __attribute__((vector_size(64)));

auto generate_mask = []() constexpr {
    u8v ret;
    for (size_t i = 0; i < sizeof(u8v); ++i) {
        ret[i] = i & 0xff;
    }
    return ret;
};
constexpr auto mask = generate_mask();

但是 GCC 说 u8v 的修改不是常量表达式。

使用具有 C++20 功能的 G++ 是否有一些解决方法?

技术上可行,但复杂到无法使用的地步。 与 SIMD 无关。

不过,变通办法还不错。

SIMD 向量无论如何都不能嵌入到指令流中。不管你的代码说 constexpr auto mask,实际上编译器会生成完整的向量,将数据放在二进制文件的只读段中,并根据需要从那里加载。

例外情况是您的向量生成速度快于 RAM 加载速度。可以使用 vpxor 在没有 RAM 访问的情况下生成全零向量,可以使用 vpcmpeqd 生成所有位设置的向量,并且可以使用广播指令生成所有通道中具有相同值的向量。任何其他内容都会导致从二进制文件加载全向量。

这意味着您可以将 constexpr 替换为 const,二进制文件将相同。如果该代码在头文件中,理想情况下,在使用 VC++ 构建时,您还需要 __declspec(selectany),或者在您的情况下,GCC 的等价物是 __attribute__((weak))