TL: DR: похоже, может быть, какая-то настройка на микроархитектуру для эта конкретная последовательность кода. В этом нет ничего «общего», который поможет в других случаях.
При дальнейшем рассмотрении я думаю, что теория @Iwillnotexist Idonotexist является наиболее вероятной: это было написано не экспертом, который думал, что это может помочь. Распределение регистров большой ключ: много REX префиксы можно было бы избежать, выбрав все повторно используемые регистры в младшем 8.
XORPS работает в «плавающее» домена, на некоторых процессорах Intel (Nehalem и позже), в то время как PXOR всегда работает в домене «ivec».
Поскольку проводка каждого выхода ALU на каждый вход ALU для непосредственных результатов пересылки была бы дорогостоящей, разработчики CPU разбивают их на домены. (Пересылка сохраняет латентность записи в файл регистра и повторное чтение). Пересечение домена может занять дополнительный 1 цикл латентности (семейство Intel SnB) или 2 цикла (Nehalem).
Дальнейшее чтение: мой ответ на What's the difference between logical SSE intrinsics?
две теории возникают мне:
Кто написал эту мысль, что PXOR и XORPS бы дать больше параллелизм, потому что они не конкурируют друг с другом. (Это неверно: PXOR может работать на всех портах ALU порта, но XORPS не может).
Это очень умный код, который специально создает задержку байпаса, чтобы избежать конфликтов ресурсов, которые могут задержать выполнение следующего PCLMULQDQ. (или, как предполагает EOF, размер кода/выравнивание может иметь какое-то отношение к нему).
Уведомление об авторских правах на код говорит «на 2011-2015 годы Intel», так что стоит рассмотреть возможность, что это как-то полезно для некоторых последних процессоров Intel, а не только на основе непонимания того, как Intel процессоров Работа. Nehalem был первым процессором, который вообще включил PCLMULQDQ, и это Intel, поэтому, если что-то будет настроено плохо на процессоры AMD. История кода не находится в git-репо, а только 6 мая, которая добавила текущую версию.
Intel whitepaper (from Dec 2009), что он основан на использовании только PXOR, а не XORPS, в его версии блока 2x pclmul/2x xor.
В таблице Agner Fog даже не отображается количество uops для PCLMULQDQ на Nehalem или какие порты они требуют. Это 12c латентность и одна на 8c пропускная способность, поэтому он может быть похож на реализацию 18-го июня Sandy/Ivybridge. Хасуэлл делает его впечатляющим 3 uops (2p0 p5), в то время как он работает только 1 uop на Broadwell (p0) и Skylake (p5).
XORPS может работать только на порту5 (до тех пор, пока Skylake не будет работать на всех трех портах ALU-порта). На Nehalem есть 2c байпасная задержка, когда один из его входов поступает от PXOR. На SnB семейства процессоров, Agner туман говорит:
В некоторых случаях, нет задержки обхода при использовании неправильного типа перетасовки или инструкции Boolean.
Так что я думаю, что нет фактически никакой дополнительной задержки байпаса для пересылки из PXOR -> XORPS на SnB, так что единственный эффект будет то, что он может работать только на порту 5. На Nehalem, это действительно может задержать XORPS до тех пор, пока не будут выполнены PSHUFB.
В основной развернутой петле есть PSHUFB после XOR, чтобы настроить входы для следующего PCLMUL. SnB/IvB может запускать целые перетасовки на p1/p5 (в отличие от Haswell, а позже, когда на p5 имеется только один блок перетасовки, но для AVX2 он имеет ширину 256b).
Поскольку конкурировать за порты, необходимые для настройки ввода для следующего PCLMUL, не кажется полезным, . Лучше всего предположить размер кода/выравнивание, если это изменение было выполнено при настройке для SnB.
На CPU, где PCLMULQDQ более 4 микрооперации, это microcoded. Это означает, что для каждого PCLMULQDQ требуется целая строка кэша uop для себя. Поскольку только 3 строки кэша uop могут сопоставляться с одним и тем же 32B-блоком инструкций x86, это означает, что большая часть кода не будет полностью входить в кеш-память на SnB/IvB. Каждая строка кэша uop может кэшировать только непрерывные инструкции. От оптимизации руководства Intel:
Все микрооперации в пути (моп строки кэша) представляют собой инструкции, которые являются статически смежными в коде и имеют свои EIPs в пределах одной и той же выровненной области 32 байт.
Это звучит как очень похожий вопрос к наличию целого числа DIV в цикле: Branch alignment for loops involving micro-coded instructions on Intel SnB-family CPUs. С правильным выравниванием, you can get it to run out of the uop cache (the DSB in Intel performance counter terminology). @Iwillnotexist Idonotexist сделал некоторое полезное тестирование на процессоре Haswell микрокодированных инструкций, показывая, что они предотвращают запуск из буфера loopback. (LSD в терминологии Intel).
На Haswell и позже, PCLMULQDQ не microcoded, так что он может идти в том же микрооперациях строки кэша с другими командами, до или после него.
Для предыдущих процессоров, возможно, стоит попытаться настроить код, чтобы нагрузить кэш uop в меньшем количестве мест. OTOH, переключение между кэшем uop и унаследованными декодерами может быть хуже, чем просто работает из декодеров.
Также IDK, если такой большой разворот действительно полезен. Вероятно, он сильно различается между SnB и Skylake, поскольку микрокодированные инструкции для конвейера очень разные, а SKL может даже не быть узким местом по пропускной способности PCLMUL.
'xorps' является трехбайтовой инструкцией, а' pxor' занимает четыре байта. Помимо этого, [таблицы инструкций] (http://www.agner.org/optimize/instruction_tables.pdf) и [руководства по микроархитектуре] (http://www.agner.org/optimize/microarchitecture.pdf) указывают, что что это не повредит AMD, поскольку «xorps» рассматривается как целочисленный домен.Это * может * повредить производительность на pre-skylake Intel, хотя, поскольку «xorps» не может использовать столько исполнительных блоков, и могут быть задержки байпаса. – EOF
@ EOF: Я предполагаю, что он настроен для Intel SnB/IvB, основанный на дате (и что он написан Intel). Выравнивание для кэша uop похоже на лучшее предположение, но, возможно, что-то происходит, избегая конфликта ресурсов, чтобы не задерживать следующий PCLMUL. –