Почему последний аргумент _mm_permute_ps является int?

#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 , потому что этот уровень неоптимизации означает, что постоянное распространение не работает даже после принудительного встраивания.