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.

Reply via email to