[Bug rtl-optimization/67577] New: Trivial float-vectorization foiled by a loop
bisqwit at iki dot fi
gcc-bugzilla@gcc.gnu.org
Mon Sep 14 17:23:00 GMT 2015
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67577
Bug ID: 67577
Summary: Trivial float-vectorization foiled by a loop
Product: gcc
Version: 5.2.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: rtl-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: bisqwit at iki dot fi
Target Milestone: ---
This code is written as if tailored to be SIMD-optimized by GCC...
But GCC somehow blows it.
template<typename T, unsigned N>
struct vec
{
T d[N];
vec<T,N> operator* (const T& b)
{
vec<T,N> result;
for(unsigned n=0u; n<N; ++n) result.d[n] = d[n] * b;
return result;
}
vec<T,N> operator+ (const vec<T,N>& b)
{
vec<T,N> result;
for(unsigned n=0u; n<N; ++n) result.d[n] = d[n] + b.d[n];
return result;
}
vec<T,N> operator- (const vec<T,N>& b)
{
vec<T,N> result;
for(unsigned n=0u; n<N; ++n) result.d[n] = d[n] - b.d[n];
return result;
}
};
float scale;
vec<float,8> a, b, c;
void x()
{
for(int n=0; n<1; ++n)
{
vec<float,8> result = b + (a - b) * scale;
c = result;
}
}
Generated code (inner loop):
movss b+4(%rip), %xmm6
movss a+4(%rip), %xmm7
subss %xmm6, %xmm7
movss scale(%rip), %xmm0
movss b+8(%rip), %xmm5
movss b+12(%rip), %xmm4
movss b+16(%rip), %xmm3
mulss %xmm0, %xmm7
movss b+20(%rip), %xmm1
movss b+24(%rip), %xmm2
movss b+28(%rip), %xmm9
movss b(%rip), %xmm8
addss %xmm6, %xmm7
movss a+8(%rip), %xmm6
subss %xmm5, %xmm6
movss %xmm7, c+4(%rip)
mulss %xmm0, %xmm6
addss %xmm5, %xmm6
movss a+12(%rip), %xmm5
subss %xmm4, %xmm5
movss %xmm6, c+8(%rip)
mulss %xmm0, %xmm5
addss %xmm4, %xmm5
movss a+16(%rip), %xmm4
subss %xmm3, %xmm4
movss %xmm5, c+12(%rip)
mulss %xmm0, %xmm4
addss %xmm3, %xmm4
movss a+20(%rip), %xmm3
subss %xmm1, %xmm3
movss %xmm4, c+16(%rip)
mulss %xmm0, %xmm3
addss %xmm1, %xmm3
movss a+24(%rip), %xmm1
subss %xmm2, %xmm1
movss %xmm3, c+20(%rip)
mulss %xmm0, %xmm1
addss %xmm2, %xmm1
movss a+28(%rip), %xmm2
subss %xmm9, %xmm2
movss %xmm1, c+24(%rip)
mulss %xmm0, %xmm2
addss %xmm9, %xmm2
movss a(%rip), %xmm9
subss %xmm8, %xmm9
movss %xmm2, c+28(%rip)
mulss %xmm9, %xmm0
addss %xmm8, %xmm0
movss %xmm0, c(%rip)
Platform: amd64; GCC version 5.2.1.
If I comment away the dummy for-loop, or I change the float "scale" variable
into a function parameter, the inner loop changes into a much simpler code that
vectorizes like I meant to:
movaps b(%rip), %xmm3
movaps b+16(%rip), %xmm1
movaps a+16(%rip), %xmm0
movaps a(%rip), %xmm2
subps %xmm1, %xmm0
movss scale(%rip), %xmm4
subps %xmm3, %xmm2
shufps $0, %xmm4, %xmm4
mulps %xmm4, %xmm0
mulps %xmm4, %xmm2
addps %xmm1, %xmm0
addps %xmm3, %xmm2
movaps %xmm0, -24(%rsp)
movq -16(%rsp), %rax
movaps %xmm2, -40(%rsp)
movq %xmm2, c(%rip)
movq %xmm0, c+16(%rip)
movq -32(%rsp), %rdx
movq %rax, c+24(%rip)
movq %rdx, c+8(%rip)
Although there's still some glitch in the generated code causing dummy memory
transfers, at least it now did the calculations using packed registers.
If I change the global "scale" variable into a function parameter, the
following shorter code is generated instead (essentially the same what Clang
successfully produces for all three cases).
movaps b+16(%rip), %xmm2
shufps $0, %xmm0, %xmm0
movaps a+16(%rip), %xmm1
subps %xmm2, %xmm1
movaps b(%rip), %xmm3
mulps %xmm0, %xmm1
addps %xmm2, %xmm1
movaps a(%rip), %xmm2
subps %xmm3, %xmm2
movaps %xmm1, c+16(%rip)
mulps %xmm2, %xmm0
addps %xmm3, %xmm0
movaps %xmm0, c(%rip)
Something causes GCC's tree-vectorization to be really rickety and easily
foiled by trivial changes in code, and I'd like to see it fixed at least in
these particular cases.
More information about the Gcc-bugs
mailing list