2015-05-21 5 views
0

У меня есть код, который использует встроенную функцию ARM Neon vtbl2_u8 ARM. Когда я компилирую с armv7 или armv7s архитектурами, этот код правильно компилирует (и выполняет). Однако, когда я пытаюсь скомпилировать таргетинг arm64, я получаю ошибки:vtbl2 intrinsics на ARM64 отсутствует

simd.h: error: call to unavailable function 'vtbl2_u8' 

Мой Xcode версии 6.1, iPhone SDK 8.1. Рассматривая arm64_neon_internal.h, определение для vtbl2_u8 имеет номер __attribute__(unavailable). Определяется для vtbl2q_u8, но он принимает разные типы параметров. Есть ли прямая замена для vtbl2, присущей arm64?

ответ

2

Как указано в ссылке на 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, так что вы все еще можете видеть дополнительные инструкции перемещения за кулисами.

+0

Вы не можете индексировать 'a' с помощью индексов, вам нужно сделать' a.val [x] ', но в противном случае это решение обеспечивает правильное выполнение. Моя проблема в том, что теперь она добавляет дополнительную инструкцию каждый раз, когда я вызываю vtbl2. Это в критическом критическом коде (следовательно, сборке) и даже без профилирования, что делает меня неудобным. Он используется частью моей эмуляции shuffle, которая используется во всем моем SIMD-коде. – MuertoExcobito

+0

Я исправил ошибку, которую вы указали, спасибо. Что касается исправления проблемы с производительностью. По сути, 'uint8x8x2_t' живет в двух последовательных регистрах, что дает разный макет между AArch64 и AArch32 (где Q0 был D0: D1). Внутри' vtbl2_u8' intrinsic требуется 16-битная маска. Перенастройка производителя данных 'uint8x8x2_t' для создания' uint8x16_t' является единственным другим обходным решением для этого. Обратите внимание, что даже в компиляторах, которые предоставляют эту внутреннюю (соединительную линию GCC и LLVM), вставляется команда, выполняющая 'vcombine_u8'. С поддержкой компилятора ваша производительность будет по-прежнему присутствовать. –

+0

Итак, как оказалось, я могу идти дальше в функции и иметь комбинированную версию 'a', на которую вы намекали, что является лучшим решением для меня, потому что оно позволяет избежать vcombine.Тем не менее, я думаю, что это, вероятно, ответит на вопрос, который будет задан лучше всего. Кроме того, просто примечание: я недавно обновил XC 6.3, и похоже, что 'vtbl1q_u8' ->' vqtbl1_u8'. Благодаря! – MuertoExcobito