2016-01-25 29 views
1

如你所知,我們有如下移位指令在SIMD SSE:PSLL(W-d-Q)和PSRL(W-d-Q)SSE/SIMD以單字節元素大小/粒度移位?

有沒有PSLLB指令,所以我們怎麼能轉移的8位值(單字節)的引導?

+2

您可以移位並遮罩。 – Jester

+0

你能給我一個簡單的例子嗎? – Falcon

+4

'psrldq xmm0,1; pand xmm0,[mask];掩碼dd 0x7f7f7f7f,0x7f7f7f7f,0x7f7f7f7f,0x7f7f7f7f'。請注意,左移一位就是'paddb xmm0,xmm0'。對於較大的班次,適當調整面具。 – Jester

回答

3

在左移的特殊情況下,您可以使用paddb xmm0, xmm0


如小丑在註釋中指出的那樣,最佳的選擇,以模擬不存在psllb(和右移當量)是使用更寬移位,然後屏蔽掉該交叉元件邊界的任何比特。

例如

psllw xmm0, 1  ; doesn't matter what size (w/d/q): performance is the same for all sizes on all CPUs 
    pand xmm0, [mask] 

section .rodata 
    ;; required mask depends on the shift count 
    mask1 dd 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f 

或廣播0x7f的提前進入一個環路的矢量寄存器某種其他方式,如從vpbroadcastb一個單字節或generate on the fly with a sequence likepcmpeqw xmm0,xmm0/psrlw xmm0, 9/packuswb xmm0,xmm0。通過正確的移位計數選擇,您可以生成任何模式,即1個字節(重複的零和重複的1個字節)。

mov r32, imm32/movd xmm, r32並且洗牌也是一種選擇,但與pcmpeqw/...序列相比,可能不會保存指令字節。 (請注意,VBROADCASTSS登記代碼版本是AVX2只,這並不重要,因爲在這裏256B整數轉變AVX2,僅是也。)


我沒有看到任何類似有效的方式來模仿算術右移(不存在PSRAB)。每個單詞的高字節由PSRAW正確處理。將每個單詞的低位字節移到高位將使另一個PSRAW根據需要多次複製它的符號位。

; input in xmm0. Using AVX to save on mov instructions 
VPSLLDQ xmm1, xmm0, 1  ; or VPSLLW xmm1, xmm0, 8, but this distributes one of the uops to the shuffle port 
VPSRAW xmm1, xmm1, 8+2 ; shift low bytes back to final destination 

VPSRAW xmm0, xmm0, 2  ; shift high bytes, leaving garbage in low bytes 
VPBLENDVB xmm0, xmm1, xmm0, xmm2 ; (where xmm2 holds a mask of alternating 0 and -1, which could be generated with pcmpeqw/psrlw 8). This insn is fairly slow 

由於一個立即字節只能編碼8個元素,所以沒有字節粒度的即時混合。


沒有VPBLENDVB(可能更好,即使它可用,如果它產生或加載一個恆定的速度很慢):

VPSLLDQ xmm1, xmm0, 1  ; or VPSLLW 8 
VPSRAW xmm1, xmm1, n  ; low bytes in the wrong place 

VPSRAW xmm0, xmm0, 8+n ; shift high bytes all the way to the bottom of the element 
VPSLLW xmm0, xmm0, 8  ; high bytes back in place, with zero in the low byte. (VPSLLDQ can't work: PSRAW 8+n leaves garbage we need to clear) 

VPSRLW xmm1, xmm1, 8  ; shift low bytes into place, leaving zero in the high byte. (VPSRLDQ 1 could do this, if we started with VPSLLW instead of VPSLLDQ) 
VPOR  xmm0, xmm0, xmm1 

使用PAND/PANDN/POR以恆定的(交變0/- 1個字節)在一個寄存器中也可以工作(對於移位端口,壓力要小得多),以便進行字節混合,如果必須在循環中執行此操作,則這是一個更好的選擇。

相關問題