Go не гарантирует выравнивание стека, чтобы вы могли использовать операнд источника памяти для minpd
?
Кроме того, я не знаком с Go;действительно ли это float
двоичный код IEEE64, который большинство языков (включая x86 asm) называют double
?Странно видеть float
в исходном коде и pd
(упакованные двойные) инструкции, используемые в asm.
Затраты на вызов автономной рукописной функции asm для этого будутбыть выше, чем позволить компилятору сделать это с помощью скаляра minsd
для одной пары.Особенно в соответствии с дрянным соглашением о вызовах Go, передачей аргументов в памяти и сохранением возвращаемого значения в памяти.
Оптимизирующий компилятор Go с внутренним LLVM или gcc должен выполнять работу со встроенным кодом с меньшей задержкой и меньшим временем ожидания.мера стоимости пропускной способности, чем вызов этой функции, даже с оптимизацией, приведенной ниже.Или, если вам повезет, компилятор будет использовать minpd
для вас.
Но для реальной проблемы после minpd x0, x1
вам понадобится горизонтальная сумма xmm1
. Самый быстрый способ сделать горизонтальную векторную сумму с плавающей запятой на x86 .
Вы должны использовать movaps
для копирования регистров xmm, даже если вы заботитесь только о младших 64 битах.movsd x1, x2
сливается с младшими 64 битами xmm2, создавая ложную зависимость от старого значения и стоя случайного шага.
minpd x0, x1
movhps x1, x0 // high 64 bits of xmm1 => low 64 of xmm0
addsd x1, x0
Вы можете movaps x1, x2
и unpckhpd x2,x2
, но это будет стоитьдополнительные movapd
или movaps
, которых можно избежать с помощью movhps
.
(movaps
/ movups
короче movapd
, меньшего размера кода и в остальном точно эквивалентны movapd
/ movupd
на всех процессорах для загрузки, хранения и reg-reg копий.)