]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR102842] Consider all outputs in generation of matching reloads
authorVladimir N. Makarov <vmakarov@redhat.com>
Tue, 26 Oct 2021 18:03:42 +0000 (14:03 -0400)
committerVladimir N. Makarov <vmakarov@redhat.com>
Wed, 3 Nov 2021 17:03:15 +0000 (13:03 -0400)
Without considering all output insn operands (not only processed
before), in rare cases LRA can use the same hard register for
different outputs of the insn on different assignment subpasses.  The
patch fixes the problem.

gcc/ChangeLog:

PR rtl-optimization/102842
* lra-constraints.c (match_reload): Ignore out in checking values
of outs.
(curr_insn_transform): Collect outputs before doing reloads of operands.

gcc/testsuite/ChangeLog:

PR rtl-optimization/102842
* g++.target/arm/pr102842.C: New test.

gcc/lra-constraints.c
gcc/testsuite/g++.target/arm/pr102842.C [new file with mode: 0644]

index aaacc4eabed4cb6540fdd2ee955bdb1aa839c464..da84466917d8466929e47fc948e42cfe55dcdc15 100644 (file)
@@ -1102,7 +1102,7 @@ match_reload (signed char out, signed char *ins, signed char *outs,
          for (i = 0; outs[i] >= 0; i++)
            {
              rtx other_out_rtx = *curr_id->operand_loc[outs[i]];
-             if (REG_P (other_out_rtx)
+             if (outs[i] != out && REG_P (other_out_rtx)
                  && (regno_val_use_in (REGNO (in_rtx), other_out_rtx)
                      != NULL_RTX))
                {
@@ -4388,7 +4388,10 @@ curr_insn_transform (bool check_only_p)
       }
 
   n_outputs = 0;
-  outputs[0] = -1;
+  for (i = 0; i < n_operands; i++)
+    if (curr_static_id->operand[i].type == OP_OUT)
+      outputs[n_outputs++] = i;
+  outputs[n_outputs] = -1;
   for (i = 0; i < n_operands; i++)
     {
       int regno;
@@ -4463,8 +4466,6 @@ curr_insn_transform (bool check_only_p)
                     lra-lives.c.  */
                  match_reload (i, goal_alt_matched[i], outputs, goal_alt[i], &before,
                                &after, TRUE);
-                 outputs[n_outputs++] = i;
-                 outputs[n_outputs] = -1;
                }
              continue;
            }
@@ -4642,14 +4643,6 @@ curr_insn_transform (bool check_only_p)
           process_alt_operands decides that it is possible.  */
        gcc_unreachable ();
 
-      /* Memorise processed outputs so that output remaining to be processed
-        can avoid using the same register value (see match_reload).  */
-      if (curr_static_id->operand[i].type == OP_OUT)
-       {
-         outputs[n_outputs++] = i;
-         outputs[n_outputs] = -1;
-       }
-
       if (optional_p)
        {
          rtx reg = op;
diff --git a/gcc/testsuite/g++.target/arm/pr102842.C b/gcc/testsuite/g++.target/arm/pr102842.C
new file mode 100644 (file)
index 0000000..a2bac66
--- /dev/null
@@ -0,0 +1,30 @@
+/* PR rtl-optimization/102842 */
+/* { dg-do compile } */
+/* { dg-options "-fPIC  -O2 -fno-omit-frame-pointer -mthumb -march=armv7-a+fp" } */
+
+struct Plane {
+  using T = float;
+  T *Row();
+};
+using ImageF = Plane;
+long long Mirror_x;
+struct EnsurePaddingInPlaceRowByRow {
+  void Process() {
+    switch (strategy_) {
+    case kSlow:
+      float *row = img_.Row();
+      long long xsize = x1_;
+      while (Mirror_x >= xsize)
+        if (Mirror_x)
+          Mirror_x = 2 * xsize - 1;
+      *row = Mirror_x;
+    }
+  }
+  ImageF img_;
+  unsigned x1_;
+  enum { kSlow } strategy_;
+};
+void FinalizeImageRect() {
+  EnsurePaddingInPlaceRowByRow ensure_padding;
+  ensure_padding.Process();
+}