ARM NEON: ¿Cuál es la diferencia entre vld4_f32 y vld4q_f32?
-
26-09-2019 - |
Pregunta
No estoy en condiciones de distinguir la diferencia entre vld4_f32
y vld4q_f32
en las instrucciones ARM NEON.
La confusión comenzó cuando alcé los niveles de codificación y empecé a buscar en las instrucciones de montaje en lugar de los intrínsecos menos informativos.
La razón por la que necesito para uso vld4 instrucción variante aquí es porque, me gustaría captura 4 float32_t
de de todos los cuarta posición de mi gran matriz.
Las funciones intrínsecas vld4_f32
y las correspondientes instrucciones de montaje se ven así ( A partir de este enlace )
float32x2x4_t vld4_f32 (const float32_t *)
Form of expected instruction(s): vld4.32 {d0, d1, d2, d3}, [r0]
Las funciones intrínsecas vld4q_f32
y sus correspondientes instrucciones de montaje es similar al siguiente
float32x4x4_t vld4q_f32 (const float32_t *)
Form of expected instruction(s): vld4.32 {d0, d1, d2, d3}, [r0]
Bueno, a nivel intrínsecos la diferencia que veo es el tipo de retorno , pero si miro a las instrucciones de montaje y el número de registros, ambos se ven como el mismo. ¿De qué manera el compilador o ensamblador saber la diferencia entre los dos?
¿Alguien puede aclarar más en esto y también a explicar la forma en que puedo lograr carga 4 float32_t Los valores que se sitúan en en cada ubicación de memoria cuarto en un solo registro?
Solución
Sí, descubrí la diferencia. Solía ??CodeSourcery para ver el contenido real de registro para todas las instrucciones de carga. El enlace que he publicado no da los detalles completos sobre la vld4q_f32.
Está bien, primero viene la vld4_f32
, este cargas 4 d registros (por ejemplo d16-19) cada d registro es de 64 bits de largo, por lo que esta instrucción se carga la primera 8 valores intercalan con un intervalo de 4 como se muestra en la figura siguiente.
En el segundo caso la vld4q_f32
, este cargas 8 d registros (por ejemplo d16-23) en lugar de cuatro. Para un lector de este enlace , no está del todo claro que se cargarán 8 registros. Cuando miraba el código dis-ensamblados para una vld4qf32
, se hace uso de 8 d registros.
Esta instrucción de hecho hacer lo que estaba esperando que haga es decir, para cargar 4 valores float32_t
que están en el intervalo de 4 como se muestra en la figura siguiente.
Otros consejos
He desmontado dos funciones intrínsecas, tal vez ayuda a alguien:
// 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]