"Наилучший" означает наименьшее количество инструкций (или наименьшее количество мопов, если какие-либо инструкции декодируют более чем один моп). Размер машинного кода в байтах - это тай-брейк для равного количества insn.
Генерация констант по самой своей природе является началом новой цепочки зависимостей, поэтому латентность имеет значение. Также необычно генерировать константы внутри цикла, поэтому требования к пропускной способности и порту выполнения также в основном не имеют значения.
Генерация констант вместо их загрузки требует больше инструкций (за исключением всех нулей или всех единиц), поэтому она потребляет драгоценное пространство uop-cache. Это может быть даже более ограниченный ресурс, чем кеш данных.
Agner Fog отлично Руководство по оптимизации сборки освещает это в Section 13.4
. Таблица 13.10 содержит последовательности для генерации векторов, где каждый элемент представляет собой 0
, 1
, 2
, 3
, 4
, -1
или -2
, с размерами элементов от 8 до 64 бит. Таблица 13.11 содержит последовательности для генерации некоторых значений с плавающей запятой (0.0
, 0.5
, 1.0
, 1.5
, 2.0
, -2.0
и битовых масок для знакового бита.)
Последовательности Agner Fog используют только SSE2, либо по замыслу, либо потому, что некоторое время он не обновлялся.
Какие другие константы могут быть сгенерированы с помощью коротких неочевидных последовательностей инструкций? (Дальнейшие расширения с различным числом сдвигов очевидны и не "интересны".) Есть ли лучшие последовательности для генерации констант, которые перечисляет Agner Fog?
Как переместить 128-битные немедленные в регистры XMM иллюстрирует некоторые способы помещения произвольной константы 128b в поток инструкций, но это обычно не имеет смысла (это не экономит место и занимает много места в кэш-памяти uop). )