應該寫什麼@ zx485是:
.data
mask11byte db 0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0ffh,0,0,0,0,0
.code
pxor xmm1, xmm2 ; equiv to psubb, but runs on all 3 vector execution ports
ptest xmm1, xmmword ptr [mask11byte] ; SSE 4.1
setz al ; AL=TRUE for equal
只要沒有什麼不好的事情發生(浮點異常),你不需要之前計算屏蔽掉你的操作數,即使他們持有垃圾。由於PTEST
作爲其操作的一部分進行按位AND操作,所以根本不需要單獨的PAND
。
有一段時間,我以爲我有一個版本,可以使用更少的空間和更少的微軟,但我最終需要一個額外的指令,因爲沒有pcmpneq
(所以我需要邏輯not
)。所以它的體積更小,uops的數量相同,但延遲明顯更差。
.code
PCMPEQB xmm1, xmm2 ; bytes of xmm1 = 0xFF on equal
PMOVMSKB eax, xmm1 ; ax = high bit of each byte of xmm1
NOT eax
TEST eax, 0x7FF ; zero flag set if all the low 11 bits are zero
SETZ al ; 17 bytes
; Or one fewer insn with BMI1's ANDN. One fewer uop if test can't macro-fuse
ANDN eax, eax, [mask11bits] ; only test the low 11 bits.
; ANDN version takes 20 bytes, plus 2B of data
.data
mask11bits dw 07ffh
test
可以宏觀保險絲jcc
,所以如果你使用這個作爲一個跳轉條件,而不是實際做setz
,你出人頭大小。 (因爲你不需要16B的面具常量。)
ptest
需要2個uops,所以ptest
版本總共是4個uops(包括jcc
或其他指令)。所述pmovmskb
版本也4個微指令具有test
/jcc
宏稠合分支,但5 cmovcc
/setcc
。 (4 andn
,與任何setcc
/cmovcc
/jcc
,因爲它不能宏觀fuse`。)
(昂納霧的桌子說:ptest
承擔的SandyBridge,2:1融合域UOP上的所有其它英特爾CPU,這些CPU支持它,但我不確定我是否相信。)
延遲上的Haswell(重要的,如果該分支不預測井):
pxor
:1 + ptest
:2 = 3個週期
pcmpeqb
:1 + pmovmskb
:3 + not
:1 + test
:1 = 6個週期
pcmpeqb
:1 + pmovmskb
:3 + andn
:1 = 5個週期(?但不是宏稠合的,所以有可能更多的循環等待時間的)
因此,ptest
版本具有顯着縮短的延遲:jcc
可以更快執行,以更快地檢測分支預測失誤。
Agner Fog的測試顯示ptest
在Nehalem上的延遲= 3,在SnB/IvB上是1,在Haswell上是2。
你可以使用'PCMPEQ'系列的任何整數比較,我沒有看到你的問題。 – Jester
這個結構本質上是打包的。你能假定永遠是真的嗎?它看起來像一個'memcmp(&s1,&s2,sizeof(struct s))'可能是最少的投資時間。利用'memcmp'提供的任何優化。 –
@JonathonReinhart是可以假設包裝。 – user997112