如何使用__m128i执行元素左移?

时间:2012-06-22 00:44:35

标签: c sse avx

我发现的SSE转换指令只能在所有元素上移动相同的数量:

  • _mm_sll_epi32()
  • _mm_slli_epi32()

These shift all elements, but by the same shift amount.

有没有办法对不同的元素应用不同的转换?像这样:

__m128i a,  __m128i b;  

r0:=    a0  <<  b0;
r1:=    a1  <<  b1;
r2:=    a2  <<  b2;
r3:=    a3  <<  b3;

3 个答案:

答案 0 :(得分:7)

存在_mm_shl_epi32()内在函数。

http://msdn.microsoft.com/en-us/library/gg445138.aspx

但是,它需要XOP instruction set 。只有AMD Bulldozer和Interlagos处理器或更高版本才有此指令。它不适用于任何英特尔处理器。

如果你想在没有XOP指令的情况下做到这一点,你将需要以艰难的方式去做:将它们拉出并逐一进行。

如果没有XOP指令,您可以使用以下内在函数对SSE4.1执行此操作:

  • _mm_insert_epi32()
  • _mm_extract_epi32()

http://software.intel.com/sites/products/documentation/studio/composer/en-us/2011/compiler_c/intref_cls/common/intref_sse41_reg_ins_ext.htm

这些将允许您将128位寄存器的部分提取到常规寄存器中以进行移位并将其放回。

如果你采用后一种方法,那将是非常低效的。这就是为什么_mm_shl_epi32()首先存在的原因。

答案 1 :(得分:2)

如果没有XOP,您的选择是有限的。如果你可以控制移位计数参数的格式,那么你可以使用_mm_mullo_pi16,因为乘以2的幂与移动该幂相同。

例如,如果要将SSE寄存器中的8个16位元素移位<0, 1, 2, 3, 4, 5, 6, 7>,则可以将2乘以上升到移位计数幂,即<0, 2, 4, 8, 16, 32, 64, 128>

答案 2 :(得分:0)

在某些情况下,这可以替代_mm_shl_epi32(a, b)

_mm_mullo_ps(a, 1 << b);

一般来说,这需要b具有常数值 - 我不知道使用较旧的SSE指令计算(1 << b)的有效方法。