ARMのNEONのSIMD命令をgccのオートベクタライズの最適化で使う方法 【再実行(浮動小数点演算)】
ここで使うクロスコンパイラは毎度お馴染みのこれ↓です。
$ arm-xilinx-linux-gnueabi-gcc --version
arm-xilinx-linux-gnueabi-gcc (Sourcery CodeBench Lite 2013.05-40) 4.7.3
$ arm-xilinx-linux-gnueabi-gcc --version
arm-xilinx-linux-gnueabi-gcc (Sourcery CodeBench Lite 2013.05-40) 4.7.3
float float_average(float* array, int size) { int i; float total = 0; if (size <= 0) { return 0; } for (i = 0; i < size; i++) { total += array[i]; } return total / size; }
-O2 オプションでコンパイルした結果です。冒頭・末尾のアセンブラ・ディレクティブは省略しています。
float_average: .fnstart @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. cmp r1, #0 ble .L4 add r3, r0, r1, asl #2 flds s15, .L7 .L3: fldmias r0!, {s14} cmp r0, r3 fadds s15, s15, s14 bne .L3 fmsr s13, r1 @ int fsitos s14, s13 fdivs s15, s15, s14 fmrs r0, s15 bx lr .L4: flds s15, .L7 fmrs r0, s15 bx lr
次が -Ofast の結果です。
float_average: .fnstart @ args = 0, pretend = 0, frame = 0 @ frame_needed = 0, uses_anonymous_args = 0 @ link register save eliminated. cmp r1, #0 stmfd sp!, {r4, r5, r6} .save {r4, r5, r6} ble .L11 sbfx ip, r0, #2, #1 and ip, ip, #3 cmp ip, r1 movcs ip, r1 cmp r1, #3 movls ip, r1 cmp ip, #0 beq .L12 sub r2, r0, #4 mov r3, #0 flds s15, .L20 .L5: add r3, r3, #1 add r2, r2, #4 cmp ip, r3 flds s14, [r2, #0] mov r4, r2 fadds s15, s15, s14 bhi .L5 cmp r1, ip beq .L6 .L4: rsb r6, ip, r1 mov r4, r6, lsr #2 movs r5, r4, asl #2 beq .L7 vmov.f32 q8, #0.0 @ v4sf add ip, r0, ip, asl #2 mov r2, #0 .L8: add r2, r2, #1 vldmia ip!, {d18-d19} cmp r2, r4 vadd.f32 q8, q8, q9 bcc .L8 vadd.f32 d16, d16, d17 cmp r6, r5 vmov.f32 q9, #0.0 @ v4sf add r3, r3, r5 vpadd.f32 d18, d16, d16 vmov.32 r2, d18[0] fmsr s14, r2 fadds s15, s15, s14 beq .L6 .L7: sub r2, r3, #1 add r0, r0, r2, asl #2 .L10: add r3, r3, #1 add r0, r0, #4 cmp r1, r3 flds s14, [r0, #0] mov r4, r0 fadds s15, s15, s14 bgt .L10 .L6: fmsr s13, r1 @ int fsitos s14, s13 fdivs s15, s15, s14 .L2: fmrs r0, s15 ldmfd sp!, {r4, r5, r6} bx lr .L11: flds s15, .L20 b .L2 .L12: mov r3, ip flds s15, .L20 b .L4
オプションに関して少し補足です。
・-O3 だけだと -O2と同じ結果でした。
・-O3 -Ofast としても -Ofast と同じでした。
・-O3 だけだと -O2と同じ結果でした。
・-O3 -Ofast としても -Ofast と同じでした。