如你所知,我們有如下移位指令在SIMD SSE:PSLL
(W-d-Q)和PSRL
(W-d-Q)SSE/SIMD以單字節元素大小/粒度移位?
有沒有PSLLB
指令,所以我們怎麼能轉移的8位值(單字節)的引導?
如你所知,我們有如下移位指令在SIMD SSE:PSLL
(W-d-Q)和PSRL
(W-d-Q)SSE/SIMD以單字節元素大小/粒度移位?
有沒有PSLLB
指令,所以我們怎麼能轉移的8位值(單字節)的引導?
在左移的特殊情況下,您可以使用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個字節)在一個寄存器中也可以工作(對於移位端口,壓力要小得多),以便進行字節混合,如果必須在循環中執行此操作,則這是一個更好的選擇。
您可以移位並遮罩。 – Jester
你能給我一個簡單的例子嗎? – Falcon
'psrldq xmm0,1; pand xmm0,[mask];掩碼dd 0x7f7f7f7f,0x7f7f7f7f,0x7f7f7f7f,0x7f7f7f7f'。請注意,左移一位就是'paddb xmm0,xmm0'。對於較大的班次,適當調整面具。 – Jester