Преобразование из упакованного двойного в упакованное плавание доступно только в сужающейся форме, а не в версии, которая принимает 2 вектора двойного и упаковывает в 1 вектор плавания.Так что да, встроенные функции для [v]cvtpd2ps
- ваш единственный выбор.Эти инструкции декодируют до 2 мопов на современном Intel;один для порта (ов) FMA и один для порта в случайном порядке.(https://agner.org/optimize/)
Сохранение результата не вызывает затруднений, вам нужна некоторая форма _mm_store/storeu
.
Для 128-битных векторов (в результате 2x float
= 64битов), у вас нет целого 128-битного вектора результатов. Вы можете перетасовать два вместе в 128-битный вектор, но с пропускной способностью FP, равной 1 за такт на Intel, начиная с Sandybridge, вероятно, лучше всего хранитьони оба по отдельности.
Вы хотите, чтобы movlps
вместо movsd
сохранял младшие 64 бита вектора float
; он сохраняет один байт инструкции, а для встроенной функции C требуется меньше приведения.к сожалению, требуется __m64*
вместо float*
, поэтому вам все еще нужен один приведение:
_mm_storel_pi((__m64*)dst, _mm_cvtpd_ps(xmm) );
Но для загрузки вам определенно нужно movsd
, чтобы избежать ложной зависимости от старогозначение. movlps
загружает слияние в регистр; movsd
загружает нулевое расширение. На самом деле, cvtps2pd xmm, qword [mem]
позаботится об этом за вас, если вы можете заставить компилятор выдавать его из встроенных функций.
Itможет быть трудно сделать это безопасно, для аналогичныхПричины pmovzxbw xmm, qword [mem]
: компиляторам не удается сложить загрузку qword в операнд памяти для pmovzx / sx: ( Загрузка 8 символов из памяти в переменную __m256 в виде упакованных плавающих одинарной точности )