沒有,除非我失去了巧妙的是,有兩個未知寄存器的ptest
通常對於檢查它們兩個的某些屬性是沒有用的。 (除了明顯的東西,你已經想要一個按位與AND,就像兩個位圖之間的交集)。
要測試兩個寄存器都爲零,或者將它們放在一起,並對它們自己進行PTEST測試。
ptest xmm0, xmm1
產生兩個結果:
- ZF =是
xmm0 & xmm1
全零?
- CF =是
(~xmm0) & xmm1
全零?
如果第二個矢量是全零,則標誌完全不依賴於第一個矢量中的位。
將「is-all-zero」檢查視爲AND和ANDNOT結果的NOT(bitwise horizontal-OR())
可能很有用。但可能不會,因爲這對於我的大腦輕鬆地進行思考來說太困難了。垂直AND和水平OR的順序可能會使得更容易理解爲什麼PTEST不會告訴你很多關於兩個未知寄存器的組合,就像整數TEST指令一樣。
下面是一個2位ptest a,mask
的真值表。希望這有助於考慮混合零和128b輸入的混合。
請注意,CF(a,mask) == ZF(~a,mask)
。
a mask ZF CF
00 00 1 1
01 00 1 1
10 00 1 1
11 00 1 1
00 01 1 0
01 01 0 1
10 01 1 0
11 01 0 1
00 10 1 0
01 10 1 0
10 10 0 1
11 10 0 1
00 11 1 0
01 11 0 0
10 11 0 0
11 11 0 1
Intel's intrinsics guide lists 2 interesting intrinsics for it。注意args的命名爲:a
和mask
是他們告訴你關於由已知的AND掩碼選擇的部分a
的線索。
_mm_test_mix_ones_zeros (__m128i a, __m128i mask)
:返回(ZF == 0 && CF == 0)
_mm_test_all_zeros (__m128i a, __m128i mask)
:返回ZF
另外還有一個更簡單地命名的版本:
int _mm_testc_si128 (__m128i a, __m128i b)
:返回CF
int _mm_testnzc_si128 (__m128i a, __m128i b)
:迴歸小號(ZF == 0 && CF == 0)
int _mm_testz_si128 (__m128i a, __m128i b)
:返回ZF
有AVX2 __m256i
版本的內部函數,但導向只列出all_zeros和mix_ones_zeros備用名稱版本__m128i
操作數。
如果你想測試從C或C++其他一些情況下,你應該使用testc
和testz
用相同的操作數,並希望你的編譯器實現,它只是需要做一個PTEST,甚至有望使用單一JCC ,SETCC或CMOVCC來實現你的邏輯。 (我建議你檢查了ASM,至少對於你最關心的編譯器。)
注意_mm_testz_si128(v, set1(0xff))
總是一樣_mm_testz_si128(v,v)
,因爲這是如何和作品。但是對於CF的結果並非如此。
您可以檢查矢量使用
bool is_all_ones = _mm_testc_si128(v, _mm_set1_epi8(0xff));
這可能是否定的速度更快,但更小的代碼尺寸,不是對所有的人,的載體的PCMPEQB則通常是全1 movemask + cmp。它不能避免需要一個向量常量。
PTEST確實具有不會破壞任一輸入操作數的優點,即使沒有AVX也是如此。