Обычно не стоит использовать SSE4.1 ptest xmm0,xmm0
для результата pcmpeqb
, особенно если вы не разветвляетесь.
pmovmskb
равен 1 моп, а cmp
или test
может слиться с макросом jnz
в другой моп на процессорах Intel и AMD. Всего 2 мопа для ветвления результата pcmpeqb с pmovmsk + test / j cc
Но ptest
- это 2 мопа, а его 2-й моп не может макро-предохранитель со следующей веткой. Всего 3 мопа для ветвления на вектор с ptest
+ j cc.
Это безубыточность, когда вы можете использовать ptest
напрямую, без необходимости pcmp
, например, проверка любых / всех битов во всем векторе (или с маской, несколько битов). И на самом деле выигрыш, если вы используете его для CMOV или установить cc вместо ветви. Это также выигрыш для размера кода, даже при том же количестве мопов.
Вы можете амортизировать проверку по нескольким векторам. например, por
некоторые векторы вместе, а затем проверить что все байты ноль. Или pminub
несколько векторов вместе и затем проверьте любые нули. (glib c строковые функции, такие как strlen и strchr, используют этот трюк для параллельной проверки всей строки кэша векторов, прежде чем выяснить, откуда она взялась после выхода из l oop.)
Вы можете объединить результаты pcmpeq вместо необработанных входных данных, например, для memchr. В этом случае вы можете использовать pand
вместо pminub
, чтобы получить ноль в элементе, где любой вход имеет ноль. Некоторые процессоры работают на pand
на большем количестве портов, чем pminub
, поэтому меньше конкуренции за вектор ALU.
Также обратите внимание, что pmovmskb ноль-расширяется в EAX; Вы можете test eax,eax
вместо того, чтобы тратить байт префикса, чтобы проверить только AX.