]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR rtl-optimization/55342 ([LRA,x86] Non-optimal code for simple loop with LRA)
authorVladimir Makarov <vmakarov@redhat.com>
Fri, 5 Jul 2013 20:56:13 +0000 (20:56 +0000)
committerVladimir Makarov <vmakarov@gcc.gnu.org>
Fri, 5 Jul 2013 20:56:13 +0000 (20:56 +0000)
2013-07-05  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/55342
* lra-int.h (lra_subreg_reload_pseudos): New.
* lra.c: Add undoing optional reloads to the block diagram.
(lra_subreg_reload_pseudos): New.
(lra_optional_reload_pseudos): Change comments.
(lra): Init and clear lra_subreg_reload_pseudos.  Clear
lra_optional_reload_pseudos after undo transformations.
* lra-assigns.c (pseudo_prefix_title): New.
(lra_setup_reg_renumber): Use it.
(spill_for): Ditto.  Check subreg reload pseudos too.
(assign_by_spills): Consider subreg reload pseudos too.
* lra-constraints.c (simplify_operand_subreg): Use
lra_subreg_reload_pseudos instead of lra_optional_reload_pseudos.
(curr_insn_transform): Recognize and do optional reloads.
(undo_optional_reloads): New.
(lra_undo_inheritance): Call undo_optional_reloads.

2013-07-05  Vladimir Makarov  <vmakarov@redhat.com>

PR rtl-optimization/55342
* gcc.target/i386/pr55342.c: New.

From-SVN: r200723

gcc/ChangeLog
gcc/lra-assigns.c
gcc/lra-constraints.c
gcc/lra-int.h
gcc/lra.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr55342.c [new file with mode: 0644]

index fef987619944bbd16881778f2c02505c8c72a163..176ecf446dec4afc1487f64b2e2119d254018ff2 100644 (file)
@@ -1,3 +1,22 @@
+2013-07-05  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/55342
+       * lra-int.h (lra_subreg_reload_pseudos): New.
+       * lra.c: Add undoing optional reloads to the block diagram.
+       (lra_subreg_reload_pseudos): New.
+       (lra_optional_reload_pseudos): Change comments.
+       (lra): Init and clear lra_subreg_reload_pseudos.  Clear
+       lra_optional_reload_pseudos after undo transformations.
+       * lra-assigns.c (pseudo_prefix_title): New.
+       (lra_setup_reg_renumber): Use it.
+       (spill_for): Ditto.  Check subreg reload pseudos too.
+       (assign_by_spills): Consider subreg reload pseudos too.
+       * lra-constraints.c (simplify_operand_subreg): Use
+       lra_subreg_reload_pseudos instead of lra_optional_reload_pseudos.
+       (curr_insn_transform): Recognize and do optional reloads.
+       (undo_optional_reloads): New.
+       (lra_undo_inheritance): Call undo_optional_reloads.
+
 2013-07-05  Thomas Quinot  <quinot@adacore.com>
 
        * tree-complex.c (expand_complex_operations_1): Fix typo.
index 9719f0dc9e70fa3a58fa58305d891c7027c2b21a..b5736268e693464fb83176fd4605b9271e4b1109 100644 (file)
@@ -672,6 +672,19 @@ update_hard_regno_preference (int regno, int hard_regno, int div)
     }
 }
 
+/* Return prefix title for pseudo REGNO.  */
+static const char *
+pseudo_prefix_title (int regno)
+{
+  return
+    (regno < lra_constraint_new_regno_start ? ""
+     : bitmap_bit_p (&lra_inheritance_pseudos, regno) ? "inheritance "
+     : bitmap_bit_p (&lra_split_regs, regno) ? "split "
+     : bitmap_bit_p (&lra_optional_reload_pseudos, regno) ? "optional reload "
+     : bitmap_bit_p (&lra_subreg_reload_pseudos, regno) ? "subreg reload "
+     : "reload ");
+}
+
 /* Update REG_RENUMBER and other pseudo preferences by assignment of
    HARD_REGNO to pseudo REGNO and print about it if PRINT_P.  */
 void
@@ -692,13 +705,7 @@ lra_setup_reg_renumber (int regno, int hard_regno, bool print_p)
       lra_hard_reg_usage[hr + i] += lra_reg_info[regno].freq;
   if (print_p && lra_dump_file != NULL)
     fprintf (lra_dump_file, "     Assign %d to %sr%d (freq=%d)\n",
-            reg_renumber[regno],
-            regno < lra_constraint_new_regno_start
-            ? ""
-            : bitmap_bit_p (&lra_inheritance_pseudos, regno) ? "inheritance "
-            : bitmap_bit_p (&lra_split_regs, regno) ? "split "
-            : bitmap_bit_p (&lra_optional_reload_pseudos, regno)
-            ? "optional reload ": "reload ",
+            reg_renumber[regno], pseudo_prefix_title (regno),
             regno, lra_reg_info[regno].freq);
   if (hard_regno >= 0)
     {
@@ -844,6 +851,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
        if ((int) spill_regno >= lra_constraint_new_regno_start
            && ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno)
            && ! bitmap_bit_p (&lra_split_regs, spill_regno)
+           && ! bitmap_bit_p (&lra_subreg_reload_pseudos, spill_regno)
            && ! bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno))
          goto fail;
       insn_pseudos_num = 0;
@@ -953,14 +961,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
     {
       if (lra_dump_file != NULL)
        fprintf (lra_dump_file, "      Spill %sr%d(hr=%d, freq=%d) for r%d\n",
-                ((int) spill_regno < lra_constraint_new_regno_start
-                 ? ""
-                 : bitmap_bit_p (&lra_inheritance_pseudos, spill_regno)
-                 ? "inheritance "
-                 : bitmap_bit_p (&lra_split_regs, spill_regno)
-                 ? "split "
-                 : bitmap_bit_p (&lra_optional_reload_pseudos, spill_regno)
-                 ? "optional reload " : "reload "),
+                pseudo_prefix_title (spill_regno),
                 spill_regno, reg_renumber[spill_regno],
                 lra_reg_info[spill_regno].freq, regno);
       update_lives (spill_regno, true);
@@ -1176,6 +1177,7 @@ assign_by_spills (void)
   bitmap_initialize (&changed_insns, &reg_obstack);
   bitmap_initialize (&non_reload_pseudos, &reg_obstack);
   bitmap_ior (&non_reload_pseudos, &lra_inheritance_pseudos, &lra_split_regs);
+  bitmap_ior_into (&non_reload_pseudos, &lra_subreg_reload_pseudos);
   bitmap_ior_into (&non_reload_pseudos, &lra_optional_reload_pseudos);
   for (iter = 0; iter <= 1; iter++)
     {
@@ -1350,6 +1352,7 @@ assign_by_spills (void)
                 && lra_reg_info[i].restore_regno >= 0)
             || (bitmap_bit_p (&lra_split_regs, i)
                 && lra_reg_info[i].restore_regno >= 0)
+            || bitmap_bit_p (&lra_subreg_reload_pseudos, i)
             || bitmap_bit_p (&lra_optional_reload_pseudos, i))
            && reg_renumber[i] < 0 && lra_reg_info[i].nrefs != 0
            && regno_allocno_class_array[i] != NO_REGS)
index f667512337f695c966ba252310105b5864255a25..a9a673469019c009b00509b0bd8af0d1d60217be 100644 (file)
@@ -1228,7 +1228,7 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode)
       if (get_reload_reg (curr_static_id->operand[nop].type, reg_mode, reg,
                          rclass, "subreg reg", &new_reg))
        {
-         bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (new_reg));
+         bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
          if (type != OP_OUT
              || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode))
            {
@@ -3183,6 +3183,8 @@ curr_insn_transform (void)
 
   for (i = 0; i < n_operands; i++)
     {
+      int regno;
+      bool optional_p = false;
       rtx old, new_reg;
       rtx op = *curr_id->operand_loc[i];
 
@@ -3205,7 +3207,22 @@ curr_insn_transform (void)
                   current one.  */
                reg_renumber[regno] = -1;
            }
-         continue;
+         /* We can do an optional reload.  If the pseudo got a hard
+            reg, we might improve the code through inheritance.  If
+            it does not get a hard register we coalesce memory/memory
+            moves later.  Ignore move insns to avoid cycling.  */
+         if (! lra_simple_p
+             && lra_undo_inheritance_iter < LRA_MAX_INHERITANCE_PASSES
+             && goal_alt[i] != NO_REGS && REG_P (op)
+             && (regno = REGNO (op)) >= FIRST_PSEUDO_REGISTER
+             && reg_renumber[regno] < 0
+             && (curr_insn_set == NULL_RTX
+                 || !(REG_P (SET_SRC (curr_insn_set))
+                      || MEM_P (SET_SRC (curr_insn_set))
+                      || GET_CODE (SET_SRC (curr_insn_set)) == SUBREG)))
+           optional_p = true;
+         else
+           continue;
        }
 
       /* Operands that match previous ones have already been handled.  */
@@ -3328,6 +3345,21 @@ curr_insn_transform (void)
        /* We must generate code in any case when function
           process_alt_operands decides that it is possible.  */
        gcc_unreachable ();
+      if (optional_p)
+       {
+         lra_assert (REG_P (op));
+         regno = REGNO (op);
+         op = *curr_id->operand_loc[i]; /* Substitution.  */
+         if (GET_CODE (op) == SUBREG)
+           op = SUBREG_REG (op);
+         gcc_assert (REG_P (op) && (int) REGNO (op) >= new_regno_start);
+         bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (op));
+         lra_reg_info[REGNO (op)].restore_regno = regno;
+         if (lra_dump_file != NULL)
+           fprintf (lra_dump_file,
+                    "      Making reload reg %d for reg %d optional\n",
+                    REGNO (op), regno);
+       }
     }
   if (before != NULL_RTX || after != NULL_RTX
       || max_regno_before != max_reg_num ())
@@ -5273,6 +5305,100 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
   return change_p;
 }
 
+/* If optional reload pseudos failed to get a hard register or was not
+   inherited, it is better to remove optional reloads.  We do this
+   transformation after undoing inheritance to figure out necessity to
+   remove optional reloads easier.  Return true if we do any
+   change.  */
+static bool
+undo_optional_reloads (void)
+{
+  bool change_p;
+  unsigned int regno, uid;
+  bitmap_iterator bi, bi2;
+  rtx insn, set, src, dest;
+  bitmap_head removed_optional_reload_pseudos, insn_bitmap;
+
+  bitmap_initialize (&removed_optional_reload_pseudos, &reg_obstack);
+  bitmap_copy (&removed_optional_reload_pseudos, &lra_optional_reload_pseudos);
+  EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi)
+    if (reg_renumber[regno] >= 0)
+      EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi2)
+       {
+         insn = lra_insn_recog_data[uid]->insn;
+         if ((set = single_set (insn)) == NULL_RTX)
+           continue;
+         src = SET_SRC (set);
+         dest = SET_DEST (set);
+         if (! REG_P (src) || ! REG_P (dest))
+           continue;
+         if ((REGNO (src) == regno
+              && lra_reg_info[regno].restore_regno != (int) REGNO (dest))
+             || (REGNO (dest) == regno
+                 && lra_reg_info[regno].restore_regno != (int) REGNO (src)))
+           {
+             /* Optional reload was inherited.  Keep it.  */
+             bitmap_clear_bit (&removed_optional_reload_pseudos, regno);
+             if (lra_dump_file != NULL)
+               fprintf (lra_dump_file, "Keep optional reload reg %d\n", regno);
+           }
+       }
+  change_p = ! bitmap_empty_p (&removed_optional_reload_pseudos);
+  bitmap_initialize (&insn_bitmap, &reg_obstack);
+  EXECUTE_IF_SET_IN_BITMAP (&removed_optional_reload_pseudos, 0, regno, bi)
+    {
+      if (lra_dump_file != NULL)
+       fprintf (lra_dump_file, "Remove optional reload reg %d\n", regno);
+      bitmap_copy (&insn_bitmap, &lra_reg_info[regno].insn_bitmap);
+      EXECUTE_IF_SET_IN_BITMAP (&insn_bitmap, 0, uid, bi2)
+       {
+         insn = lra_insn_recog_data[uid]->insn;
+         if ((set = single_set (insn)) != NULL_RTX)
+           {
+             src = SET_SRC (set);
+             dest = SET_DEST (set);
+             if (REG_P (src) && REG_P (dest)
+                 && ((REGNO (src) == regno
+                      && (lra_reg_info[regno].restore_regno
+                          == (int) REGNO (dest)))
+                     || (REGNO (dest) == regno
+                         && (lra_reg_info[regno].restore_regno
+                             == (int) REGNO (src)))))
+               {
+                 if (lra_dump_file != NULL)
+                   {
+                     fprintf (lra_dump_file, "  Deleting move %u\n",
+                              INSN_UID (insn));
+                     dump_insn_slim (lra_dump_file, insn);
+                   }
+                 lra_set_insn_deleted (insn);
+                 continue;
+               }
+             /* We should not worry about generation memory-memory
+                moves here as if the corresponding inheritance did
+                not work (inheritance pseudo did not get a hard reg),
+                we remove the inheritance pseudo and the optional
+                reload.  */
+           }
+         substitute_pseudo (&insn, regno,
+                            regno_reg_rtx[lra_reg_info[regno].restore_regno]);
+         lra_update_insn_regno_info (insn);
+         if (lra_dump_file != NULL)
+           {
+             fprintf (lra_dump_file,
+                      "  Restoring original insn:\n");
+             dump_insn_slim (lra_dump_file, insn);
+           }
+       }
+    }
+  /* Clear restore_regnos.  */
+  EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi)
+    lra_reg_info[regno].restore_regno = -1;
+  bitmap_clear (&insn_bitmap);
+  bitmap_clear (&removed_optional_reload_pseudos);
+  return change_p;
+}
+
 /* Entry function for undoing inheritance/split transformation.         Return true
    if we did any RTL change in this pass.  */
 bool
@@ -5335,5 +5461,6 @@ lra_undo_inheritance (void)
     lra_reg_info[regno].restore_regno = -1;
   EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi)
     lra_reg_info[regno].restore_regno = -1;
+  change_p = undo_optional_reloads () || change_p;
   return change_p;
 }
index 3d7ecb35e093908ad7731acffa76999ca687e3ea..cb45c65d13af6b6fa141f2a408dd2b374c09e4b6 100644 (file)
@@ -321,6 +321,7 @@ extern int lra_new_regno_start;
 extern int lra_constraint_new_regno_start;
 extern bitmap_head lra_inheritance_pseudos;
 extern bitmap_head lra_split_regs;
+extern bitmap_head lra_subreg_reload_pseudos;
 extern bitmap_head lra_optional_reload_pseudos;
 extern int lra_constraint_new_insn_uid_start;
 
index 6b505c508c37c273471b6847961b864c4b05f9ae..30b7c0a3dd57ae77d13d24785a52b670cd3adeb5 100644 (file)
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -43,13 +43,13 @@ along with GCC; see the file COPYING3.      If not see
 
    Here is block diagram of LRA passes:
 
-                                ---------------------
-           ---------------     | Undo inheritance    |     ---------------
-          | Memory-memory |    | for spilled pseudos)|    | New (and old) |
-          | move coalesce |<---| and splits (for     |<-- |   pseudos     |
-           ---------------     | pseudos got the     |    |  assignment   |
-  Start           |            |  same  hard regs)   |     ---------------
-    |             |             ---------------------               ^
+                                ------------------------
+           ---------------     | Undo inheritance for   |     ---------------
+          | Memory-memory |    | spilled pseudos,       |    | New (and old) |
+          | move coalesce |<---| splits for pseudos got |<-- |   pseudos     |
+           ---------------     | the same hard regs,    |    |  assignment   |
+  Start           |            | and optional reloads   |     ---------------
+    |             |             ------------------------            ^
     V             |              ----------------                   |
  -----------      V             | Update virtual |                  |
 |  Remove   |----> ------------>|    register    |                  |
@@ -2187,10 +2187,16 @@ bitmap_head lra_inheritance_pseudos;
 /* Split regnos before the new spill pass.  */
 bitmap_head lra_split_regs;
 
-/* Reload pseudo regnos before the new assign pass which still can be
-   spilled after the assinment pass.  */
+/* Reload pseudo regnos before the new assignmnet pass which still can
+   be spilled after the assinment pass as memory is also accepted in
+   insns for the reload pseudos.  */
 bitmap_head lra_optional_reload_pseudos;
 
+/* Pseudo regnos used for subreg reloads before the new assignment
+   pass.  Such pseudos still can be spilled after the assinment
+   pass.  */
+bitmap_head lra_subreg_reload_pseudos;
+
 /* First UID of insns generated before a new spill pass.  */
 int lra_constraint_new_insn_uid_start;
 
@@ -2296,6 +2302,7 @@ lra (FILE *f)
   bitmap_initialize (&lra_inheritance_pseudos, &reg_obstack);
   bitmap_initialize (&lra_split_regs, &reg_obstack);
   bitmap_initialize (&lra_optional_reload_pseudos, &reg_obstack);
+  bitmap_initialize (&lra_subreg_reload_pseudos, &reg_obstack);
   live_p = false;
   if (get_frame_size () != 0 && crtl->stack_alignment_needed)
     /* If we have a stack frame, we must align it now.  The stack size
@@ -2356,8 +2363,9 @@ lra (FILE *f)
              if (! live_p)
                lra_clear_live_ranges ();
            }
+         bitmap_clear (&lra_optional_reload_pseudos);
        }
-      bitmap_clear (&lra_optional_reload_pseudos);
+      bitmap_clear (&lra_subreg_reload_pseudos);
       bitmap_clear (&lra_inheritance_pseudos);
       bitmap_clear (&lra_split_regs);
       if (! lra_need_for_spills_p ())
index b37d8d58bc5e8dcae32b6e2b27053678eae2fd33..b84de4bc7d0f21ae4f5d7ce3c8ed476c4e17c9b4 100644 (file)
@@ -1,3 +1,8 @@
+2013-07-05  Vladimir Makarov  <vmakarov@redhat.com>
+
+       PR rtl-optimization/55342
+       * gcc.target/i386/pr55342.c: New.
+
 2013-07-05  Marcus Shawcroft  <marcus.shawcroft@arm.com>
 
        * gcc.dg/pr57518.c: Adjust scan-rtl-dump-not pattern.
diff --git a/gcc/testsuite/gcc.target/i386/pr55342.c b/gcc/testsuite/gcc.target/i386/pr55342.c
new file mode 100644 (file)
index 0000000..0d9e6c6
--- /dev/null
@@ -0,0 +1,28 @@
+/* PR rtl-optimization/55342 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "notb" } } */
+
+
+void convert_image(unsigned char *in, unsigned char *out, int size) {
+    int i;
+    unsigned char * read = in,
+     * write = out;
+    for(i = 0; i < size; i++) {
+        unsigned char r = *read++;
+        unsigned char g = *read++;
+        unsigned char b = *read++;
+        unsigned char c, m, y, k, tmp;
+        c = 255 - r;
+        m = 255 - g;
+        y = 255 - b;
+       if (c < m)
+         k = ((c) > (y)?(y):(c));
+       else
+          k = ((m) > (y)?(y):(m));
+        *write++ = c - k;
+        *write++ = m - k;
+        *write++ = y - k;
+        *write++ = k;
+    }
+}