Optimisation question

Iain Buclaw via D.gnu d.gnu at puremagic.com
Fri Apr 10 14:17:41 PDT 2015


On 10 April 2015 at 20:18, John Colvin via D.gnu <d.gnu at puremagic.com> wrote:
> void mul(float[] a, float v)
> {
>   if ((cast(size_t)a.ptr) % 32 == 0
>     && a.length == 16)
>   {
>     foreach (ref el; a)
>       el *= v;
>   }
> }
>
> with
> -Ofast -march=broadwell -frelease
> becomes
>
> void example.mul(float[], float):
>         movq    %rsi, %rax
>         andl    $31, %eax
>         jne     .L44
>         cmpq    $16, %rdi
>         jne     .L44
>         shrq    $2, %rax
>         negq    %rax
>         andl    $7, %eax
>         je      .L10
>         vmulss  (%rsi), %xmm0, %xmm1
>         vmovss  %xmm1, (%rsi)
>         cmpq    $1, %rax
>         je      .L11
>         vmulss  4(%rsi), %xmm0, %xmm1
>         vmovss  %xmm1, 4(%rsi)
>         cmpq    $2, %rax
>         je      .L12
>         vmulss  8(%rsi), %xmm0, %xmm1
>         vmovss  %xmm1, 8(%rsi)
>         cmpq    $3, %rax
>         je      .L13
>         vmulss  12(%rsi), %xmm0, %xmm1
>         vmovss  %xmm1, 12(%rsi)
>         cmpq    $4, %rax
>         je      .L14
>         vmulss  16(%rsi), %xmm0, %xmm1
>         vmovss  %xmm1, 16(%rsi)
>         cmpq    $5, %rax
>         je      .L15
>         vmulss  20(%rsi), %xmm0, %xmm1
>         vmovss  %xmm1, 20(%rsi)
>         cmpq    $6, %rax
>         je      .L16
>         vmulss  24(%rsi), %xmm0, %xmm1
>         movl    $9, %edx
>         movl    $7, %r9d
>         vmovss  %xmm1, 24(%rsi)
> .L5:
>         movl    $16, %edi
>         movl    $8, %r8d
>         movl    $1, %r10d
>         subq    %rax, %rdi
> .L4:
>         leaq    (%rsi,%rax,4), %rcx
>         vbroadcastss    %xmm0, %ymm1
>         vmulps  (%rcx), %ymm1, %ymm2
>         vmovaps %ymm2, (%rcx)
>         cmpq    $1, %r10
>         je      .L6
>         vmulps  32(%rcx), %ymm1, %ymm1
>         vmovaps %ymm1, 32(%rcx)
> .L6:
>         leaq    (%r9,%r8), %rax
>         subq    %r8, %rdx
>         cmpq    %r8, %rdi
>         je      .L43
>         leaq    (%rsi,%rax,4), %rcx
>         vmulss  (%rcx), %xmm0, %xmm1
>         vmovss  %xmm1, (%rcx)
>         leaq    1(%rax), %rcx
>         cmpq    $1, %rdx
>         je      .L43
>         leaq    (%rsi,%rcx,4), %rcx
>         vmulss  (%rcx), %xmm0, %xmm1
>         vmovss  %xmm1, (%rcx)
>         leaq    2(%rax), %rcx
>         cmpq    $2, %rdx
>         je      .L43
>         leaq    (%rsi,%rcx,4), %rcx
>         vmulss  (%rcx), %xmm0, %xmm1
>         vmovss  %xmm1, (%rcx)
>         leaq    3(%rax), %rcx
>         cmpq    $3, %rdx
>         je      .L43
>         leaq    (%rsi,%rcx,4), %rcx
>         vmulss  (%rcx), %xmm0, %xmm1
>         vmovss  %xmm1, (%rcx)
>         leaq    4(%rax), %rcx
>         cmpq    $4, %rdx
>         je      .L43
>         leaq    (%rsi,%rcx,4), %rcx
>         vmulss  (%rcx), %xmm0, %xmm1
>         vmovss  %xmm1, (%rcx)
>         leaq    5(%rax), %rcx
>         cmpq    $5, %rdx
>         je      .L43
>         leaq    (%rsi,%rcx,4), %rcx
>         addq    $6, %rax
>         vmulss  (%rcx), %xmm0, %xmm1
>         vmovss  %xmm1, (%rcx)
>         cmpq    $6, %rdx
>         je      .L43
>         leaq    (%rsi,%rax,4), %rax
>         vmulss  (%rax), %xmm0, %xmm0
>         vmovss  %xmm0, (%rax)
>         vzeroupper
>         ret
> .L43:
>         vzeroupper
> .L44:
>         ret
> .L10:
>         movl    $16, %r8d
>         movl    $2, %r10d
>         movl    $16, %edi
>         movl    $16, %edx
>         xorl    %r9d, %r9d
>         jmp     .L4
> .L11:
>         movl    $15, %edx
>         movl    $1, %r9d
>         jmp     .L5
> .L16:
>         movl    $10, %edx
>         movl    $6, %r9d
>         jmp     .L5
> .L15:
>         movl    $11, %edx
>         movl    $5, %r9d
>         jmp     .L5
> .L14:
>         movl    $12, %edx
>         movl    $4, %r9d
>         jmp     .L5
> .L13:
>         movl    $13, %edx
>         movl    $3, %r9d
>         jmp     .L5
> .L12:
>         movl    $14, %edx
>         movl    $2, %r9d
>         jmp     .L5
>
> Which seems like an awful lot of code, wouldn't you say?
>
> I was expecting something along the lines of this (untested):
>
> void example.mul(float[], float):
>         testb   $31, %sil
>         jne     .L44
>         cmpq    $16, %rdi
>         jne     .L44
>         vbroadcastss    xmm0, ymm2
>         vmulps  (%rsi), ymm2, ymm0
>         vmulps  32(%rsi), ymm2, ymm1
>         vmovaps ymm0, (%rsi)
>         vmovaps ymm1, 32(%rsi)
> .L44:
>         ret
>
> Am I being stupid, or is the optimiser making a complete hash of things?

I fear that I cannot reproduce on gcc-5, maybe is a problem specific
to your gcc version?

_D6nested3mulFAffZv:
        testb   $31, %sil
        jne     .L8
        cmpq    $16, %rdi
        jne     .L8
        vbroadcastss    %xmm0, %ymm0
        vmulps  (%rsi), %ymm0, %ymm1
        vmulps  32(%rsi), %ymm0, %ymm0
        vmovaps %ymm1, (%rsi)
        vmovaps %ymm0, 32(%rsi)
        vzeroupper
.L8:
        ret


Iain.


More information about the D.gnu mailing list