Как указано в ссылке на ARM NEON (http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf), vtbl2_u8
, ожидается, что компиляторы предоставят реализацию расширений языка ARM C для состояния AArch64 в ARMv8-A. Обратите внимание, что в том же документе предполагается, что vtbl2q_u8 является расширением Xcode, а не внутренним, которое, как ожидается, будет поддерживаться компиляторами ACLE.
Тогда ответ на ваш вопрос должен быть заменен на vtbl2_u8
, так как он должен быть предоставлен. Однако это не поможет вам с вашей реальной проблемой, так как вы можете использовать инструкцию с компилятором, который ее не предоставляет.
Глядя на то, что вы имеете в наличии в Xcode, и что vtbl2_u8
документирована на карту, я думаю, вы должны быть в состоянии эмулировать ожидаемое поведение с:
uint8x8_t vtbl2_u8 (uint8x8x2_t a, uint8x8_t b)
{
/* Build the 128-bit vector mask from the two 64-bit halves. */
uint8x16_t new_mask = vcombine_u8 (a.val[0], a.val[1]);
/* Use an Xcode specific intrinsic. */
return vtbl1q_u8 (new_mask, b);
}
Хотя я не имею в Xcode toolchain для тестирования, поэтому вам нужно будет подтвердить, что делает то, что вы ожидаете.
Если это отображается в критическом критическом коде, вы можете обнаружить, что vcombine_u8
является неприемлемой дополнительной инструкцией. В основном uint8x8x2_t
живет в двух последовательных регистрах, что дает разную компоновку между AArch64 и AArch32 (где Q0 был D0: D1). Внутренняя память vtbl2_u8
требует 16-битной маски.
Перенос производителя данных uint8x8x2_t
для получения uint8x16_t
является единственным другим способом обхода проблемы, и, вероятно, он может работать лучше всего. Обратите внимание, что даже в компиляторах, которые предоставляют внутренний код vtbl2_u8
(соединительная линия GCC и Clang в момент написания), вставляется инструкция, выполняющая vcombine_u8
, так что вы все еще можете видеть дополнительные инструкции перемещения за кулисами.
Вы не можете индексировать 'a' с помощью индексов, вам нужно сделать' a.val [x] ', но в противном случае это решение обеспечивает правильное выполнение. Моя проблема в том, что теперь она добавляет дополнительную инструкцию каждый раз, когда я вызываю vtbl2. Это в критическом критическом коде (следовательно, сборке) и даже без профилирования, что делает меня неудобным. Он используется частью моей эмуляции shuffle, которая используется во всем моем SIMD-коде. – MuertoExcobito
Я исправил ошибку, которую вы указали, спасибо. Что касается исправления проблемы с производительностью. По сути, 'uint8x8x2_t' живет в двух последовательных регистрах, что дает разный макет между AArch64 и AArch32 (где Q0 был D0: D1). Внутри' vtbl2_u8' intrinsic требуется 16-битная маска. Перенастройка производителя данных 'uint8x8x2_t' для создания' uint8x16_t' является единственным другим обходным решением для этого. Обратите внимание, что даже в компиляторах, которые предоставляют эту внутреннюю (соединительную линию GCC и LLVM), вставляется команда, выполняющая 'vcombine_u8'. С поддержкой компилятора ваша производительность будет по-прежнему присутствовать. –
Итак, как оказалось, я могу идти дальше в функции и иметь комбинированную версию 'a', на которую вы намекали, что является лучшим решением для меня, потому что оно позволяет избежать vcombine.Тем не менее, я думаю, что это, вероятно, ответит на вопрос, который будет задан лучше всего. Кроме того, просто примечание: я недавно обновил XC 6.3, и похоже, что 'vtbl1q_u8' ->' vqtbl1_u8'. Благодаря! – MuertoExcobito