SSE2 извлекает данные из упакованных данных в golang

Я пишу функцию сборки на Голанге. Для упрощения предположим, что я хочу сделать следующую функцию:

func sseSumOfMinimums (d1, d2 [2]float64) float64

Он вычислит минимум d1 [0], d2 [0] и минимум d1 [1] и d2 [1] и вычислит сумму

По сборке делаю:

TEXT ·sseSum(SB), $0-40
MOVUPD d1+0(FP), X0 // loading d1 to X0
MOVUPD d2+16(FP), X1 // loading d1 to X1
MINPD X0, X1 // compute pair minimums and store to X1
MOVSD X1, X2 // move first min to X2
// How do I move second float of X1 to X3?
ADDSD X2, X3
MOVSD X3, ret+32(FP)

Часть, которую мне не хватает, это как извлечь второй скаляр из X1 в X3

1 ответ

Решение

Go не гарантирует выравнивание стека, чтобы вы могли использовать операнд источника памяти для minpd?

Кроме того, я не знаком с Go; это его float действительно бинарный IEEE64, который большинство языков (включая x86 asm) называют double? Странно видеть float в источнике и pd (упакованный двойной) инструкции, используемые в ассемблере.


Затраты на вызов автономной рукописной 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 копий.)

Другие вопросы по тегам