如何在只有SSE2的m128i中的某个索引处设置int32值



是否有SSE2内部函数可以在m128i中设置单个int32值?

例如在已包含1,2,3,4的m128i的索引1处设置值1000?(导致11000-3,4(

如果SSE4可用,请使用

__m128i _mm_insert_epi32 (__m128i a, int i, const int imm8)

如果您仅限于SSE2,则需要将其拆分为的两个调用

__m128i _mm_insert_epi16 (__m128i a, int i, const int imm8)

return _mm_insert_epi16(_mm_insert_epi16(a, 1000, 2), 0, 3);

在CCD_ 3的通道1上设置1000。

有了SSE3,我认为移位/混洗序列会更有效:

a = _mm_shuffle_epi32(a, 0xe0);      // shuffle as 3 2 0 ?
__m128i b = _mm_cvtsi32_si128(value);
b = _mm_alignr_epi8(b, a, 4);        // value 3 2 0
return  _mm_shuffle_epi32(b, 0x5c);  // 3 2 value 0

如果value在64位寄存器中,则可以使用_mm_cvtsi64_si128

当SSE4启用时,Gcc能够将存储加载序列转换为pinsrd xmm0, eax, 1,但在没有-msse4的情况下会给出相当复杂的序列。

movd    eax, xmm0
movaps  XMMWORD PTR [rsp-24], xmm0
movabs  rdx, 4294967296000
or      rax, rdx
mov     QWORD PTR [rsp-24], rax
movdqa  xmm0, XMMWORD PTR [rsp-24]
ret 

OTOH clang尊重存储、修改堆栈、加载范式。

movaps  xmmword ptr [rsp - 24], xmm0
mov     dword ptr [rsp - 20], 1000
movaps  xmm0, xmmword ptr [rsp - 24]
ret

也许总的赢家是存储/修改/加载组合,它也有免费的可编程索引。所有其他的都需要硬编码的即时性,包括那些使用insert内部函数的即时性。

__m128i store_modify_load(__m128i a, int value, size_t index) {
alignas(16) int32_t tmp[4] = {};
_mm_store_si128(reinterpret_cast<__m128i*>(tmp), a);
tmp[index] = value;
return  _mm_load_si128(reinterpret_cast<__m128i*>(tmp));
}

参见导螺杆中生产的组件。

最新更新