recog: Fix a constrain_operands corner case [PR97144]

aarch64's *add<mode>3_poly_1 has a pattern with the constraints:

  "=...,r,&r"
  "...,0,rk"
  "...,Uai,Uat"

i.e. the penultimate alternative requires operands 0 and 1 to match,
but the final alternative does not allow them to match.

The register allocators dealt with this correctly, and so used
different input and output registers for instructions with Uat
operands.  However, constrain_operands carried the penultimate
alternative's matching rule over to the final alternative,
so it would essentially ignore the earlyclobber.  This in turn
allowed postreload to convert a correct Uat pairing into an
incorrect one.

The fix is simple: recompute the matching information for each
alternative.

gcc/
	PR rtl-optimization/97144
	* recog.c (constrain_operands): Initialize matching_operand
	for each alternative, rather than only doing it once.

gcc/testsuite/
	PR rtl-optimization/97144
	* gcc.c-torture/compile/pr97144.c: New test.
	* gcc.target/aarch64/sve/pr97144.c: Likewise.
This commit is contained in:
Richard Sandiford 2021-01-05 11:18:48 +00:00
parent 8a25be517f
commit eac8675225
3 changed files with 54 additions and 4 deletions

View File

@ -3022,10 +3022,7 @@ constrain_operands (int strict, alternative_mask alternatives)
return 1;
for (c = 0; c < recog_data.n_operands; c++)
{
constraints[c] = recog_data.constraints[c];
matching_operands[c] = -1;
}
constraints[c] = recog_data.constraints[c];
do
{
@ -3045,6 +3042,9 @@ constrain_operands (int strict, alternative_mask alternatives)
continue;
}
for (opno = 0; opno < recog_data.n_operands; opno++)
matching_operands[opno] = -1;
for (opno = 0; opno < recog_data.n_operands; opno++)
{
rtx op = recog_data.operand[opno];

View File

@ -0,0 +1,24 @@
int a, b = 5, c = 3;
char d;
char e[1];
int f[] = {0, 0, 1};
short g;
char *h = e;
void i(void) { b = a; }
static void j(void) {
h = e;
if (f[2])
k:
for (;;) {
for (c = 0; c <= 4; c++) {
for (g = 0; g <= 4; g++)
f[g + 4] &= 2;
}
if (d)
goto k;
}
}
void l(void) {
j();
c = 0;
}

View File

@ -0,0 +1,26 @@
/* { dg-options "-O2 -ftree-vectorize" } */
int a, b = 5, c = 3;
char d;
char e[1];
int f[] = {0, 0, 1};
short g;
char *h = e;
void i(void) { b = a; }
static void j(void) {
h = e;
if (f[2])
k:
for (;;) {
for (c = 0; c <= 4; c++) {
for (g = 0; g <= 4; g++)
f[g + 4] &= 2;
}
if (d)
goto k;
}
}
void l(void) {
j();
c = 0;
}