gpt4 book ai didi

c++ - 通过索引获取 __m128 的成员?

转载 作者:IT老高 更新时间:2023-10-28 12:55:55 30 4
gpt4 key购买 nike

我有一些代码,最初是由与 MSVC 合作的人给我的,我正试图让它在 Clang 上工作。这是我遇到问题的功能:

float vectorGetByIndex( __m128 V, unsigned int i )
{
assert( i <= 3 );
return V.m128_f32[i];
}

我得到的错误如下:

Member reference has base type '__m128' is not a structure or union.

我环顾四周,发现 Clang(可能还有 GCC)在将 __m128 视为结构或 union 时存在问题。但是,我还没有找到关于如何取回这些值的直接答案。我尝试过使用下标运算符但无法做到这一点,而且我浏览了大量的 SSE 内在函数列表,但还没有找到合适的。

最佳答案

作为对 hirschhornsalz 解决方案的修改,如果 i是一个编译时常量,你可以通过使用 shuffle 完全避免 union 路径:

template<unsigned i>
float vectorGetByIndex( __m128 V)
{
// shuffle V so that the element that you want is moved to the least-
// significant element of the vector (V[0])
V = _mm_shuffle_ps(V, V, _MM_SHUFFLE(i, i, i, i));
// return the value in V[0]
return _mm_cvtss_f32(V);
}

标量 float 只是XMM寄存器的底部元素,高元素允许非零; _mm_cvtss_f32是免费的,将编译为零指令。这将作为一个 shufps 内联(或者对于 i==0 什么都没有)。

编译器足够聪明,可以优化 i==0 的随机播放(长期过时的 ICC13 除外)所以不需要 if (i) . https://godbolt.org/z/K154Pe . clang 的 shuffle 优化器将编译 vectorGetByIndex<2>进入 movhlps xmm0, xmm0shufps 短 1 个字节并产生相同的低元素。您可以使用 switch 手动执行此操作/case对于自 i 以来的其他编译器是一个编译时常量,但在手动矢量化时使用它的少数地方的 1 字节代码大小非常简单。


请注意,SSE4.1 _mm_extract_epi32(V, i);在这里不是一个有用的洗牌:extractps r/m32, xmm, imm只能将 FP 位模式提取到 integer 寄存器或内存 (https://www.felixcloutier.com/x86/extractps)。 (并且内在函数将其返回为 int ,因此它实际上会编译为 extractps + cvtsi2ss 以对 FP 位模式进行 int->float 转换,除非您在 C++ 代码中键入它。但是你会期望它编译为 extractps eax, xmm0, i/movd xmm0, eax,这与 shufps 相比很糟糕。)

extractps 的唯一情况如果编译器想要将此结果直接存储到内存中,并将存储折叠到提取指令中,这将很有用。 (对于 i!=0,否则它将使用 movss )。要将结果作为标量 float 保留在 XMM 寄存器中,shufps很好。

(SSE4.1 insertps 可以使用但没必要:它可以在获取任意源元素的同时将其他元素归零。)

关于c++ - 通过索引获取 __m128 的成员?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12624466/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com