Arm Neon: В чем разница между VLD4_F32 и VLD4Q_F32?
-
26-09-2019 - |
Вопрос
Я не в состоянии разобраться между vld4_f32
а также vld4q_f32
в руке неоновых инструкций.
Путаница началась, когда я поднял свой уровень кодирования и начал смотреть на инструкции по сборке, а не менее информативными внутрисинами.
Причина, по которой мне нужно использовать VLD4. Вариантная инструкция здесь, потому что я хотел бы захватить 4 float32_t
от каждого 4-е позиция моего большого массива.
То vld4_f32
Внутрисины и соответствующие инструкции по сборке выглядят так (Из этой ссылки)
float32x2x4_t vld4_f32 (const float32_t *)
Form of expected instruction(s): vld4.32 {d0, d1, d2, d3}, [r0]
То vld4q_f32
Внутрисины и его соответствующие инструкции по сборке выглядят так
float32x4x4_t vld4q_f32 (const float32_t *)
Form of expected instruction(s): vld4.32 {d0, d1, d2, d3}, [r0]
Ну, на внутреннем уровне Разница, которую я вижу, это тип возврата, Но если я посмотрю на инструкцию сборки и количество регистров, они оба выглядят так же. Как компилятор или ассемблер знают разницу между двумя?
Может кто-нибудь уточнить больше об этом, а также объяснить, как я могу добиться загрузки 4 float32_t. Значения, которые расположены в каждом 4-м месте памяти в один регистр?
Решение
Да, я узнал разницу. Я использовал Codesourcery, чтобы увидеть фактическое содержимое регистра для всех инструкций нагрузки. Ссылка, которую я опубликовал, не дает полных деталей на VLD4Q_F32.
Хорошо, сначала приходит vld4_f32
, это нагрузки 4 д Регистры (например, D16-19) каждый подразделение Регистр длиной 64 бит, поэтому эта инструкция загрузит первые 8 значений, променных с интервалом 4, как показано на рисунке ниже.
Во втором случае vld4q_f32
, это нагрузки 8 D. Регистры (например, D16-23) вместо четырех. Для читателя этого связь, совсем не ясно, что 8 регистров будут загружены. Когда я посмотрел на рассмотренный код для vld4qf32
, Это использовало 8 D регистров.
Эта инструкция действительно сделает то, что я надеялся, чтобы это сделать, то есть нагрузку 4 float32_t
значения, которые находятся в интервале 4, как показано на рисунке ниже.
Другие советы
Я разобрал два внутренних, может быть, это помогает кому-то:
// C++
uint32x4x4_t r = vld4q_u32( ( uint32_t *) output );
// assembly
VLD4.32 {D16,D18,D20,D22}, [R0]!
VLD4.32 {D17,D19,D21,D23}, [R0]
// C++
uint32x2x4_t r = vld4_u32( ( uint32_t *) output );
// assembly
VLD4.32 {D20-D23}, [R0]