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.

Tested on aarch64-linux-gnu, aarch64_be-elf and x86_64-linux-gnu.
OK to install?

Richard


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.target/aarch64/sve/pr97144.c: New test.
---
 gcc/recog.c                                   |  8 +++---
 .../gcc.target/aarch64/sve/pr97144.c          | 26 +++++++++++++++++++
 2 files changed, 30 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/pr97144.c

diff --git a/gcc/recog.c b/gcc/recog.c
index e9aa1ba253d..29d6c491e15 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -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];
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;
+}

Reply via email to