From ad15ddcbf450aec12191e0affeab9b1b0477881e Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Tue, 12 Jan 2021 09:55:46 +0000 Subject: [PATCH] recog: Fix a constrain_operands corner case [PR97144] aarch64's *add3_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. (cherry picked from commit eac8675225c4cdae347a11089f2b0a22ce920965) --- gcc/recog.c | 8 +++--- gcc/testsuite/gcc.c-torture/compile/pr97144.c | 24 +++++++++++++++++ .../gcc.target/aarch64/sve/pr97144.c | 26 +++++++++++++++++++ 3 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr97144.c create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr97144.c diff --git a/gcc/recog.c b/gcc/recog.c index 8c098cf5b0f..2720aaaac85 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -2547,10 +2547,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 { @@ -2570,6 +2567,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]; diff --git a/gcc/testsuite/gcc.c-torture/compile/pr97144.c b/gcc/testsuite/gcc.c-torture/compile/pr97144.c new file mode 100644 index 00000000000..380e5d4e887 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr97144.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/pr97144.c b/gcc/testsuite/gcc.target/aarch64/sve/pr97144.c new file mode 100644 index 00000000000..75245e2350b --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/pr97144.c @@ -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; +}