#c #intel #api-design #intrinsics #avx
#c #intel #api-дизайн #встроенные #avx
Вопрос:
GCC любезно сообщил мне, что последний аргумент встроенного SIMD _mm_permute_ps
должен быть 8-битным немедленным. Почему же тогда его последний аргумент объявлен ожидающим int
?
__m128 _mm_permute_ps(__m128 a, int imm8);
__m256d _mm256_permute_pd(__m256d a, int imm8);
Разве 8-разрядный параметр типа не предоставил бы более полезный интерфейс конечному пользователю?
Комментарии:
1. Виновата Intel. Они придумывают встроенные функции.
2. Если это должно быть немедленное значение, действительно ли это имеет какое-либо значение?
3. Существует школа мысли, которая гласит: «каждое целое число должно иметь тип
int
, если только нет чертовски веской причины для того, чтобы оно было какого-то другого типа». Основываясь на моем опыте, охватывающем три десятилетия, я склонен согласиться с этой философией дизайна. Как указывает @immibis, здесь, похоже, нет «чертовски веской причины».4. И, согласно документации, на самом деле это всего лишь 4 бита (для обеих функций).
5. @immibis: аппаратное обеспечение игнорирует биты
[7:4]
, но машинное кодирование использует целый байт дляimm8
. Вы, конечно, можете поместить туда все, что захотите. (Не то чтобы это имело значение; вы не пишете в asm, поэтому нет гарантии, что сгенерированный компилятором asm будет даже содержатьvpermilps
, не говоря уже о том, чтобы использовать ваши немедленные изменения. например, оптимизатор clang shuffle, вероятно, забывает об игнорируемых битах.)
Ответ №1:
Это согласуется со всеми другими встроенными функциями, принимающими вектор перетасовки или непосредственный аргумент. Вероятно, чтобы указать, что это целое число, а не символ, избегая зависимости от stdint.h для int8_t .
Более забавная часть с точки зрения C заключается в том, что это не constexpr, поэтому вы можете указать ему аргументы, не относящиеся к времени компиляции, что затем вызывает забавные вещи для компилятора. Однажды я попытался улучшить встроенные функции для gcc таким образом, чтобы предполагалось, что непосредственным аргументом было время компиляции, и это нарушило удивительно большой объем кода.
Комментарии:
1. Некоторые компиляторы отклонят его, если это не константа времени компиляции. ИМО, это правильное поведение, поскольку предполагается, что такие встроенные функции должны точно соответствовать инструкции, которую он представляет, а не абстрактному интерфейсу, который необходимо реализовать любыми необходимыми средствами.
2. GCC по-прежнему требует, чтобы встроенные аргументы, соответствующие немедленному, были константой времени компиляции после встраивания . Таким образом, для неоптимизированного кода определение
_mm_shuffle_epi32
в терминах__builtin_ia32_pshufd
является макросом, в то время как#ifdef __OPTIMIZE__
версия является встроенной функцией, объявленной с помощью__attribute__((__gnu_inline__, __always_inline__, __artificial__))
. Но даже этого недостаточно для того, чтобы он работал на-O0
, потому что этот уровень неоптимизации означает, что постоянное распространение не работает даже после принудительного встраивания.