やまものブログ

メモ書きブログです (^_^;A

ARMのNEONのSIMD命令をgccのオートベクタライズの最適化で使う方法 【再実行(浮動小数点演算)】

昨日に引き続き、京都マイクロコンピュータさんのブログ記事
ARMのNEONのSIMD命令をgccのオートベクタライズの最適化で使う方法
に掲載されていることを再実行してみました。


ここで使うクロスコンパイラは毎度お馴染みのこれ↓です。
$ arm-xilinx-linux-gnueabi-gcc --version
arm-xilinx-linux-gnueabi-gcc (Sourcery CodeBench Lite 2013.05-40) 4.7.3


今回は、「浮動小数点演算のベクタライズ」を試しました。
Cソースコード、オプションは全く同じで、同様の結果でした。

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 と同じでした。