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