https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125974
Bug ID: 125974
Summary: Missed optimisation: excessive use of vperm and vshuf
with complex type
Product: gcc
Version: 16.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: fortran
Assignee: unassigned at gcc dot gnu.org
Reporter: mjr19 at cam dot ac.uk
Target Milestone: ---
With gfortran-16.1 -Ofast -mavx2 -fopenmp-simd
subroutine foo(a,rep,ind1,ind2,zero)
complex (kind(1d0)) :: a(*),b2
integer ::rep,ind1,ind2,ii
real(kind(1d0))::zero
!$OMP SIMD
do ii=0,(rep-1)
b2=a(ind1+ii) !-a(ind2+ii)
b2=cmplx(zero-aimag(b2),zero+real(b2),kind(1d0))
a(ind2+ii)=b2
enddo
end subroutine foo
compiles to a loop containing one vpermilpd and one vaddsubpd acting
on ymm registers and advancing the loop by two iterations. I think
this is optimal.
Remove the comment character on the first line of the loop body, and
rather than adding one vsubpd, instead the loop gains a vaddpd,
vsubpd, vshufpd, and retains the vpermilpd, vaddsubpd, again advancing
the loop by two iterations.
I think the code is correct, but I cannot believe that it is
optimal. It seems that it avoids calculating b2, and instead
calculates
cmplx(zero,zero)+a(ind2+ii)
cmplx(zero,zero)-a(ind2+ii)
then shuffles and discards half the results to create
cmplx(zero+aimag(a(ind2+ii)),zero-real(a(ind2+ii)))
permutes a(ind1+ii) to give
cmplx(aimag(a(ind1+ii)),real(a(ind1+ii)))
and finally performs a vaddsubpd.
I present this as a fairly minimal example of excessive perms and
shufs with complex arithmetic.
Note that the compiler does not know that "zero" is probably 0, and
that this is a trick to avoid bug 114767. A trick which has exposed
another optimisation issue.