]> gcc.gnu.org Git - gcc.git/commitdiff
recog: Fix a constrain_operands corner case [PR97144]
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 12 Jan 2021 09:55:46 +0000 (09:55 +0000)
committerRichard Sandiford <richard.sandiford@arm.com>
Tue, 12 Jan 2021 09:55:46 +0000 (09:55 +0000)
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.

(cherry picked from commit eac8675225c4cdae347a11089f2b0a22ce920965)

gcc/recog.c
gcc/testsuite/gcc.c-torture/compile/pr97144.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/pr97144.c [new file with mode: 0644]

index 8c098cf5b0fe8b4378a58ff6517b4b27998c0613..2720aaaac8595a723d2cf0efc4106e8860e3d405 100644 (file)
@@ -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 (file)
index 0000000..380e5d4
--- /dev/null
@@ -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 (file)
index 0000000..75245e2
--- /dev/null
@@ -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;
+}
This page took 0.078788 seconds and 5 git commands to generate.