Оптимальный код для создания этой маски с встроенными функциями? - PullRequest
2 голосов
/ 05 мая 2020

Это связано с этим вопросом, но отличается от него:

Как очистить верхние 128 бит значения __m256?

Позвольте мне начать с того, что я считается «правильным» внутренним кодом.

__m256i mask()
{
    return _mm256_zextsi128_si256(_mm_set1_epi8(-1));
}

Этот код устанавливает младшие 128 битов значения __m256i на -1 (все единицы) и старшие 128 бит на 0.

Вот сборка, которую я хочу увидеть:

vpcmpeqd %xmm0,%xmm0,%xmm0

По крайней мере, это то, что, как мне кажется, я хочу видеть, поскольку я считаю, что (а) правильно и ( б) оптимальная. Пожалуйста, поправьте меня, если я ошибаюсь.

Теперь, не важно, что G CC не имеет _mm256_zextsi128_si256 до G CC 10. Я не нашел способа убедить ни один из компиляторов, которые у меня есть попробовал (ствол Clang, ствол G CC, компилятор Intel 19), чтобы сгенерировать этот простой вывод one-insn. Попробуйте сами на godbolt. Clang, в частности, работает довольно плохо, так как он «вычисляет» константу и загружает ее из памяти. И не заставляйте меня начинать с MSV C ...

Выходы G CC и IC19 не так уж и плохи; у них просто есть один лишний vmov... от %xmm0 к себе. Но меня это все равно беспокоит. Хотя, может быть, это в основном бесплатно и не должно (?)

Единственный способ, который я нашел для создания этого единственного insn, выглядит так:

__m256i mask()
{
    __m256i result;
    __asm__ ("vpcmpeqd %%xmm0,%%xmm0,%%xmm0" : "=Yz" (result));
    return result;
}

Это делает то, что я хочу G CC и IC19, но на MSV C конечно не работает. И это дает ошибку компиляции на Clang ( godbolt снова ). Кроме того: должен ли я сообщать об этом как об ошибке Clang? регистра YMM. Поддержка встроенных функций в основных компиляторах не совсем подходит для этой задачи, и нет встроенного ограничения asm, означающего «регистр YMM, но названный как его аналог XMM».

Я что-то упустил?

(Обновление)

Я зарегистрировал ошибки 45806 и 45808 против Clang и 94962 против G CC.

...