https://gcc.gnu.org/bugzilla/show_bug.cgi?id=126592

            Bug ID: 126592
           Summary: [13/14/15/16/17 Regression] Wrong code with compex mul
                    vectorisation and is_linear_load_p
           Product: gcc
           Version: 17.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ktkachov at gcc dot gnu.org
  Target Milestone: ---

/* PR: candidate tree-vect-slp-patterns.cc:158 - wrong code.

   is_linear_load_p decides PERM_EVENEVEN from the parity of each load
   permutation entry alone, so {0,2,2,2} is accepted exactly like the
   intended {0,0,2,2}.  complex_mul_pattern::build then feeds that node to
   vect_build_combine_node, whose contract (tree-vect-slp-patterns.cc:949-951)
   requires even[2k] == even[2k+1] because the combine permute keeps only
   even[2k] and odd[2k+1].  With {0,2,2,2} lane 1 of the EVENEVEN node is
   dropped, so .COMPLEX_MUL reads a[i+0] where the scalar code reads a[i+2].

   Target : aarch64 with TARGET_COMPLEX (FCMLA), i.e. -march=armv8.3-a or
            later.  Also fails with -march=armv9-a -msve-vector-bits=256.

   Test      : gcc -O3 -march=armv8.3-a t.c -o test    -> aborts
   Reference : gcc -O3 -march=armv8.3-a -fno-tree-vectorize \
                   -fno-tree-slp-vectorize t.c -o ref  -> exits 0
   Fails identically at -O2.

   Dump evidence (-fdump-tree-vect-details):
     t.c:15:21: note:  Found COMPLEX_MUL pattern in SLP tree
     t.c:15:21: note:  Target supports COMPLEX_MUL vectorization with mode
                       vector(2) double
   and the asm contains fcmla v0.2d, ..., #0 / #90.

   Observed: c[1] = 3, expected 5 (a[2]*b[1] + a[1]*b[0] = 3 + 2).  */

#define N 64

__attribute__((noipa))
void f (double * __restrict c, const double * __restrict a,
        const double * __restrict b, int n)
{
  for (int i = 0; i < n; i += 4)
    {
      c[i+0] = a[i+0]*b[i+0] - a[i+1]*b[i+1];
      c[i+1] = a[i+2]*b[i+1] + a[i+1]*b[i+0];   /* a[i+2], not a[i+0] */
      c[i+2] = a[i+2]*b[i+2] - a[i+3]*b[i+3];
      c[i+3] = a[i+2]*b[i+3] + a[i+3]*b[i+2];
    }
}

int
main (void)
{
  static double a[N], b[N], c[N];
  for (int i = 0; i < N; i++)
    {
      a[i] = i + 1;
      b[i] = 1.0;
    }

  f (c, a, b, N);

  /* With a[k] = k+1 and b[k] = 1 every value is a small exact integer:
       c[i+0] = (i+1) - (i+2)   = -1
       c[i+1] = (i+3) + (i+2)   = 2*i + 5
       c[i+2] = (i+3) - (i+4)   = -1
       c[i+3] = (i+3) + (i+4)   = 2*i + 7   */
  for (int i = 0; i < N; i += 4)
    if (c[i+0] != -1.0
        || c[i+1] != (double) (2*i + 5)
        || c[i+2] != -1.0
        || c[i+3] != (double) (2*i + 7))
      __builtin_abort ();

  return 0;
}

Aborts on aarch64 at -O3 -march=armv8.3-a

Reply via email to