Dovresti essere in grado di utilizzare l'unità VFP per tale compito. NEON e VFP condividono la stessa banca di registro, il che significa che non è necessario mescolare i registri per ottenere il vantaggio di una unità e possono anche avere viste differenti degli stessi bit di registro.
tuo float32x4_t
è a 128 bit, quindi deve sedere su un Quad (Q) registrarsi. Se si utilizza esclusivamente arm intrinsec non si sa quale si sta utilizzando. Problema c'è se è seduto sopra il 4, VFP non può vederlo come una singola precisione (per il lettore curioso: ho mantenuto questo semplice poiché ci sono differenze tra le versioni VFP e questo è il requisito minimo nullo). Quindi sarebbe meglio spostare il tuo float32x4_t
in un registro fisso come Q0
. Dopodiché puoi sommare registri come S0, S1, S2 con vadd.f32
e spostare il risultato su un registro ARM.
Alcune avvertenze ... VFP e NEON sono teoricamente diverse unità di esecuzione che condividono lo stesso banco di registri e pipeline. Non sono sicuro che questo approccio sia migliore di altri, non ho bisogno di dire ma, ancora una volta, dovresti fare un benchmark. Anche questo approccio non è ottimizzato con il neon intrinseco, quindi probabilmente avresti bisogno di creare il tuo codice con l'assembly inline.
ho fatto un semplice frammento di vedere come questo può essere simile e mi è venuta in mente questo:
#include "arm_neon.h"
float32_t sum3() {
register float32x4_t v asm ("q0");
float32_t ret;
asm volatile(
"vadd.f32 s0, s1\n"
"vadd.f32 s0, s2\n"
"vmov %[ret], s0\n"
: [ret] "=r" (ret)
:
:);
return ret;
}
objdump
di esso assomiglia (compilato con gcc -O3 -mfpu = neon -mfloat- abi = softfp)
00000000 <sum3>:
0: ee30 0a20 vadd.f32 s0, s0, s1
4: ee30 0a01 vadd.f32 s0, s0, s2
8: ee10 3a10 vmov r0, s0
c: 4770 bx lr
e: bf00 nop
mi piacerebbe davvero sentire le vostre impressioni se si dà a questo un andare!