ARM NEON: В чем разница между vld4_f32 и vld4q_f32? - PullRequest
5 голосов
/ 29 сентября 2010

Я не в состоянии разобрать разницу между vld4_f32 и vld4q_f32 в инструкциях ARM NEON.

Путаница началась, когда я поднял свои уровни кодирования и начал смотреть на инструкции по сборке, а не на менее информативную природу.

Причина, по которой мне нужно использовать vld4 вариантную инструкцию, заключается в том, что я хотел бы захватить 4 float32_t с каждой 4-й позиции из мой большой массив.

alt text

Встроенные компоненты 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-й ячейке памяти в один регистр?

Ответы [ 2 ]

7 голосов
/ 29 сентября 2010

Да, я обнаружил разницу. Я использовал CodeSourcery, чтобы увидеть фактическое содержимое регистра для всех инструкций загрузки. Ссылка, которую я разместил, не дает полной информации о vld4q_f32.

Хорошо, сначала идет vld4_f32, это загружает 4 d регистров (например, d16-19) каждый регистр d длиной 64 бита, поэтому эта инструкция загрузит первый 8 значений чередуются с интервалом 4, как показано на рисунке ниже. alt text

Во втором случае vld4q_f32, это загружает регистры 8 d (например, d16-23) вместо четырех. Для читателя этой ссылки совсем не ясно, будут ли загружены 8 регистров. Когда я посмотрел на дизассемблированный код для vld4qf32, он использовал регистры 8 d.

Эта инструкция действительно сделает то, что я надеялся сделать, то есть загрузить 4 float32_t значений, которые находятся в интервале 4, как показано на рисунке ниже. alt text

2 голосов
/ 23 апреля 2011

Я разобрал две встроенные функции, может, кому-то это поможет:

// 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]
...