Как привести __m128i к __m256i при установке старших бит на ноль? - PullRequest
1 голос
/ 05 февраля 2020

Я хочу, чтобы VC ++ генерировал код, подобный следующему:

vpxor     ymm0, ymm0, ymm0
vmovdqa   xmm0, xmm7

На человеческом языке мне нужно 32-байтовое значение __m256i, где младшие 16 байтов берутся из другой переменной, а старшие 16 байтов равны нулю Эквивалент _mm256_castsi128_si256 intrinsi c, только мне нужно, чтобы старшие 128 бит были равны нулю, а не неопределенным.

Вот что я пробовал:

_mm256_setr_m128i( low, _mm_setzero_si128() )
_mm256_insertf128_si256( _mm256_setzero_si256(), low, 0 )

Оба строки выше компилируются в vinsertf128, относительно медленно, с задержкой 3-4 цикла, намного медленнее, чем vmovdqa. Любое решение для VC ++ 2017?

1 Ответ

1 голос
/ 05 февраля 2020

Во-первых, вам не нужно vpxor ymm0, ymm0, ymm0, потому что vmovdqa xmm0, xmm7 уже обнуляет старшие биты целевого регистра ymm / zmm. Это не похоже на унаследованную инструкцию movdqa, которую вы все равно не должны использовать в коде AVX.

Во-вторых, выбор конкретных инструкций является обязанностью компилятора. Если ваш компилятор генерирует неэффективный код, рассмотрите возможность сообщения об ошибке поставщику компилятора. Например, g cc распознает этот шаблон встроенных функций и генерирует оптимальный код .

Что касается MSV C, учитывая, что в x86-64 нет поддержки встроенного ассемблера В этом режиме нет надежного способа обеспечить выполнение конкретных инструкций, кроме как использовать отдельно скомпилированный источник ассемблера. Вы можете найти некоторую комбинацию встроенных функций, которые генерируют нужный код, но это будет ненадежно (и, возможно, вызовет неопределенное поведение) и может измениться с одной версии компилятора на другую.

...