Optimisation question
John Colvin via D.gnu
d.gnu at puremagic.com
Fri Apr 10 11:18:02 PDT 2015
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?
More information about the D.gnu
mailing list