regrename.c (struct du_head): Remove member terminated.
authorBernd Schmidt <bernds@codesourcery.com>
Thu, 25 Aug 2011 10:12:35 +0000 (10:12 +0000)
committerBernd Schmidt <bernds@gcc.gnu.org>
Thu, 25 Aug 2011 10:12:35 +0000 (10:12 +0000)
* regrename.c (struct du_head): Remove member terminated.
(create_new_chain): Don't initialize it.
(scan_rtx_reg): Don't set or test it, test the open_chains_set
bitmap instead.
(tick, this_tick): New global variables, moved out of
regrename_optimize.
(current_id, open_chains, closed_chains, open_chains_set,
live_in_chains, live_hard_regs): Reorder declarations.
(dump_def_use_chain): Move function earlier in the file.
(rename_chains): New static function, broken out of
regrename_optimize.
(regrename_optimize): Use it.  Remove #if 0'ed code.

From-SVN: r178057

gcc/ChangeLog
gcc/regrename.c

index 48e20a1874bdb55fadd539c366287d2de90e30dc..91e0d7c742b92f09beda0a2ba32d83a188a0575d 100644 (file)
@@ -1,3 +1,18 @@
+2011-08-25  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * regrename.c (struct du_head): Remove member terminated.
+       (create_new_chain): Don't initialize it.
+       (scan_rtx_reg): Don't set or test it, test the open_chains_set
+       bitmap instead.
+       (tick, this_tick): New global variables, moved out of
+       regrename_optimize.
+       (current_id, open_chains, closed_chains, open_chains_set,
+       live_in_chains, live_hard_regs): Reorder declarations.
+       (dump_def_use_chain): Move function earlier in the file.
+       (rename_chains): New static function, broken out of
+       regrename_optimize.
+       (regrename_optimize): Use it.  Remove #if 0'ed code.
+
 2011-08-25  Bernhard Reutner-Fischer  <aldot@gcc.gnu.org>
 
        * varasm.c: (default_binds_local_p_1): Commentary typo fix.
index b83c7258fb7fb956a0e7591be18fcbfafda162b1..830019cf053fe7882df3a0d6e5578243f04e31c8 100644 (file)
@@ -85,8 +85,6 @@ struct du_head
   /* Conflicts with untracked hard registers.  */
   HARD_REG_SET hard_conflicts;
 
-  /* Nonzero if the chain is finished; zero if it is still open.  */
-  unsigned int terminated:1;
   /* Nonzero if the chain crosses a call.  */
   unsigned int need_caller_save_reg:1;
   /* Nonzero if the register is used in a way that prevents renaming,
@@ -132,6 +130,11 @@ static const char * const scan_actions_name[] =
   "mark_access"
 };
 
+/* TICK and THIS_TICK are used to record the last time we saw each
+   register.  */
+static int tick[FIRST_PSEUDO_REGISTER];
+static int this_tick = 0;
+
 static struct obstack rename_obstack;
 
 static void do_replace (struct du_head *, int);
@@ -147,8 +150,49 @@ static void dump_def_use_chain (struct du_head *);
 typedef struct du_head *du_head_p;
 DEF_VEC_P (du_head_p);
 DEF_VEC_ALLOC_P (du_head_p, heap);
+
+/* The id to be given to the next opened chain.  */
+static unsigned current_id;
+
+/* A mapping of unique id numbers to chains.  */
 static VEC(du_head_p, heap) *id_to_chain;
 
+/* List of currently open chains, and closed chains that can be renamed.  */
+static struct du_head *open_chains;
+static struct du_head *closed_chains;
+
+/* Bitmap of open chains.  The bits set always match the list found in
+   open_chains.  */
+static bitmap_head open_chains_set;
+
+/* Record the registers being tracked in open_chains.  */
+static HARD_REG_SET live_in_chains;
+
+/* Record the registers that are live but not tracked.  The intersection
+   between this and live_in_chains is empty.  */
+static HARD_REG_SET live_hard_regs;
+
+/* Dump all def/use chains in CHAINS to DUMP_FILE.  */
+
+static void
+dump_def_use_chain (struct du_head *head)
+{
+  while (head)
+    {
+      struct du_chain *this_du = head->first;
+      fprintf (dump_file, "Register %s (%d):",
+              reg_names[head->regno], head->nregs);
+      while (this_du)
+       {
+         fprintf (dump_file, " %d [%s]", INSN_UID (this_du->insn),
+                  reg_class_names[this_du->cl]);
+         this_du = this_du->next_use;
+       }
+      fprintf (dump_file, "\n");
+      head = head->next_chain;
+    }
+}
+
 static void
 free_chain_data (void)
 {
@@ -225,13 +269,158 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
   return true;
 }
 
+/* Process the closed chains starting with ALL_CHAINS and rename
+   registers if possible.  */
+static void
+rename_chains (du_head_p all_chains)
+{
+  HARD_REG_SET unavailable;
+
+  CLEAR_HARD_REG_SET (unavailable);
+  /* Don't clobber traceback for noreturn functions.  */
+  if (frame_pointer_needed)
+    {
+      add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM);
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
+      add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM);
+#endif
+    }
+
+  while (all_chains)
+    {
+      int new_reg, best_new_reg, best_nregs;
+      int n_uses;
+      struct du_head *this_head = all_chains;
+      struct du_chain *tmp;
+      HARD_REG_SET this_unavailable;
+      int reg = this_head->regno;
+      int pass;
+      enum reg_class super_class = NO_REGS;
+      enum reg_class preferred_class;
+      bool has_preferred_class;
+
+      all_chains = this_head->next_chain;
+
+      if (this_head->cannot_rename)
+       continue;
+
+      best_new_reg = reg;
+      best_nregs = this_head->nregs;
+
+      if (fixed_regs[reg] || global_regs[reg]
+#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
+         || (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM)
+#else
+         || (frame_pointer_needed && reg == FRAME_POINTER_REGNUM)
+#endif
+         )
+       continue;
+
+      COPY_HARD_REG_SET (this_unavailable, unavailable);
+
+      /* Iterate over elements in the chain in order to:
+        1. Count number of uses, and narrow the set of registers we can
+           use for renaming.
+        2. Compute the superunion of register classes in this chain.  */
+      n_uses = 0;
+      super_class = NO_REGS;
+      for (tmp = this_head->first; tmp; tmp = tmp->next_use)
+       {
+         if (DEBUG_INSN_P (tmp->insn))
+           continue;
+         n_uses++;
+         IOR_COMPL_HARD_REG_SET (this_unavailable,
+                                 reg_class_contents[tmp->cl]);
+         super_class
+           = reg_class_superunion[(int) super_class][(int) tmp->cl];
+       }
+
+      if (n_uses < 2)
+       continue;
+
+      /* Further narrow the set of registers we can use for renaming.
+        If the chain needs a call-saved register, mark the call-used
+        registers as unavailable.  */
+      if (this_head->need_caller_save_reg)
+       IOR_HARD_REG_SET (this_unavailable, call_used_reg_set);
+
+      /* And mark registers that overlap its lifetime as unavailable.  */
+      merge_overlapping_regs (&this_unavailable, this_head);
+
+      /* Compute preferred rename class of super union of all the classes
+        in the chain.  */
+      preferred_class
+       = (enum reg_class) targetm.preferred_rename_class (super_class);
+
+      /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
+        over registers that belong to PREFERRED_CLASS and try to find the
+        best register within the class.  If that failed, we iterate in
+        the second pass over registers that don't belong to the class.
+        If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
+        ascending order without any preference.  */
+      has_preferred_class = (preferred_class != NO_REGS);
+      for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
+       {
+         for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
+           {
+             if (has_preferred_class
+                 && ((pass == 0) != TEST_HARD_REG_BIT
+                     (reg_class_contents[preferred_class], new_reg)))
+               continue;
+
+             /* In the first pass, we force the renaming of registers that
+                don't belong to PREFERRED_CLASS to registers that do, even
+                though the latters were used not very long ago.  */
+             if (check_new_reg_p (reg, new_reg, this_head,
+                                  this_unavailable)
+                 && ((pass == 0
+                      && (!TEST_HARD_REG_BIT
+                          (reg_class_contents[preferred_class],
+                           best_new_reg)))
+                     || tick[best_new_reg] > tick[new_reg]))
+               {
+                 enum machine_mode mode
+                   = GET_MODE (*this_head->first->loc);
+                 best_new_reg = new_reg;
+                 best_nregs = hard_regno_nregs[new_reg][mode];
+               }
+           }
+         if (pass == 0 && best_new_reg != reg)
+           break;
+       }
+
+      if (dump_file)
+       {
+         fprintf (dump_file, "Register %s in insn %d",
+                  reg_names[reg], INSN_UID (this_head->first->insn));
+         if (this_head->need_caller_save_reg)
+           fprintf (dump_file, " crosses a call");
+       }
+
+      if (best_new_reg == reg)
+       {
+         tick[reg] = ++this_tick;
+         if (dump_file)
+           fprintf (dump_file, "; no available better choice\n");
+         continue;
+       }
+
+      if (dump_file)
+       fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
+
+      do_replace (this_head, best_new_reg);
+      this_head->regno = best_new_reg;
+      this_head->nregs = best_nregs;
+      tick[best_new_reg] = ++this_tick;
+      df_set_regs_ever_live (best_new_reg, true);
+    }
+}
+
 /* Perform register renaming on the current function.  */
 
 static unsigned int
 regrename_optimize (void)
 {
-  int tick[FIRST_PSEUDO_REGISTER];
-  int this_tick = 0;
   basic_block bb;
   char *first_obj;
 
@@ -248,16 +437,9 @@ regrename_optimize (void)
   FOR_EACH_BB (bb)
     {
       struct du_head *all_chains = 0;
-      HARD_REG_SET unavailable;
-#if 0
-      HARD_REG_SET regs_seen;
-      CLEAR_HARD_REG_SET (regs_seen);
-#endif
 
       id_to_chain = VEC_alloc (du_head_p, heap, 0);
 
-      CLEAR_HARD_REG_SET (unavailable);
-
       if (dump_file)
        fprintf (dump_file, "\nBasic block %d:\n", bb->index);
 
@@ -266,154 +448,7 @@ regrename_optimize (void)
       if (dump_file)
        dump_def_use_chain (all_chains);
 
-      CLEAR_HARD_REG_SET (unavailable);
-      /* Don't clobber traceback for noreturn functions.  */
-      if (frame_pointer_needed)
-       {
-         add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM);
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
-         add_to_hard_reg_set (&unavailable, Pmode, HARD_FRAME_POINTER_REGNUM);
-#endif
-       }
-
-      while (all_chains)
-       {
-         int new_reg, best_new_reg, best_nregs;
-         int n_uses;
-         struct du_head *this_head = all_chains;
-         struct du_chain *tmp;
-         HARD_REG_SET this_unavailable;
-         int reg = this_head->regno;
-         int pass;
-         enum reg_class super_class = NO_REGS;
-         enum reg_class preferred_class;
-         bool has_preferred_class;
-
-         all_chains = this_head->next_chain;
-
-         if (this_head->cannot_rename)
-           continue;
-
-         best_new_reg = reg;
-         best_nregs = this_head->nregs;
-
-#if 0 /* This just disables optimization opportunities.  */
-         /* Only rename once we've seen the reg more than once.  */
-         if (! TEST_HARD_REG_BIT (regs_seen, reg))
-           {
-             SET_HARD_REG_BIT (regs_seen, reg);
-             continue;
-           }
-#endif
-
-         if (fixed_regs[reg] || global_regs[reg]
-#if !HARD_FRAME_POINTER_IS_FRAME_POINTER
-             || (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM)
-#else
-             || (frame_pointer_needed && reg == FRAME_POINTER_REGNUM)
-#endif
-             )
-           continue;
-
-         COPY_HARD_REG_SET (this_unavailable, unavailable);
-
-         /* Iterate over elements in the chain in order to:
-            1. Count number of uses, and narrow the set of registers we can
-               use for renaming.
-            2. Compute the superunion of register classes in this chain.  */
-         n_uses = 0;
-         super_class = NO_REGS;
-         for (tmp = this_head->first; tmp; tmp = tmp->next_use)
-           {
-             if (DEBUG_INSN_P (tmp->insn))
-               continue;
-             n_uses++;
-             IOR_COMPL_HARD_REG_SET (this_unavailable,
-                                     reg_class_contents[tmp->cl]);
-             super_class
-               = reg_class_superunion[(int) super_class][(int) tmp->cl];
-           }
-
-         if (n_uses < 2)
-           continue;
-
-         /* Further narrow the set of registers we can use for renaming.
-            If the chain needs a call-saved register, mark the call-used
-            registers as unavailable.  */
-         if (this_head->need_caller_save_reg)
-           IOR_HARD_REG_SET (this_unavailable, call_used_reg_set);
-
-         /* And mark registers that overlap its lifetime as unavailable.  */
-         merge_overlapping_regs (&this_unavailable, this_head);
-
-         /* Compute preferred rename class of super union of all the classes
-            in the chain.  */
-         preferred_class
-           = (enum reg_class) targetm.preferred_rename_class (super_class);
-
-         /* If PREFERRED_CLASS is not NO_REGS, we iterate in the first pass
-            over registers that belong to PREFERRED_CLASS and try to find the
-            best register within the class.  If that failed, we iterate in
-            the second pass over registers that don't belong to the class.
-            If PREFERRED_CLASS is NO_REGS, we iterate over all registers in
-            ascending order without any preference.  */
-         has_preferred_class = (preferred_class != NO_REGS);
-         for (pass = (has_preferred_class ? 0 : 1); pass < 2; pass++)
-           {
-             for (new_reg = 0; new_reg < FIRST_PSEUDO_REGISTER; new_reg++)
-               {
-                 if (has_preferred_class
-                     && (pass == 0)
-                        != TEST_HARD_REG_BIT
-                           (reg_class_contents[preferred_class], new_reg))
-                   continue;
-
-                 /* In the first pass, we force the renaming of registers that
-                    don't belong to PREFERRED_CLASS to registers that do, even
-                    though the latters were used not very long ago.  */
-                 if (check_new_reg_p (reg, new_reg, this_head,
-                                      this_unavailable)
-                     && ((pass == 0
-                          && !TEST_HARD_REG_BIT
-                              (reg_class_contents[preferred_class],
-                               best_new_reg))
-                         || tick[best_new_reg] > tick[new_reg]))
-                   {
-                     enum machine_mode mode
-                       = GET_MODE (*this_head->first->loc);
-                     best_new_reg = new_reg;
-                     best_nregs = hard_regno_nregs[new_reg][mode];
-                   }
-               }
-             if (pass == 0 && best_new_reg != reg)
-               break;
-           }
-
-         if (dump_file)
-           {
-             fprintf (dump_file, "Register %s in insn %d",
-                      reg_names[reg], INSN_UID (this_head->first->insn));
-             if (this_head->need_caller_save_reg)
-               fprintf (dump_file, " crosses a call");
-           }
-
-         if (best_new_reg == reg)
-           {
-             tick[reg] = ++this_tick;
-             if (dump_file)
-               fprintf (dump_file, "; no available better choice\n");
-             continue;
-           }
-
-         if (dump_file)
-           fprintf (dump_file, ", renamed as %s\n", reg_names[best_new_reg]);
-
-         do_replace (this_head, best_new_reg);
-         this_head->regno = best_new_reg;
-         this_head->nregs = best_nregs;
-         tick[best_new_reg] = ++this_tick;
-         df_set_regs_ever_live (best_new_reg, true);
-       }
+      rename_chains (all_chains);
 
       free_chain_data ();
       obstack_free (&rename_obstack, first_obj);
@@ -475,24 +510,6 @@ mark_conflict (struct du_head *chains, unsigned id)
    without renaming.  */
 static bool fail_current_block;
 
-/* The id to be given to the next opened chain.  */
-static unsigned current_id;
-
-/* List of currently open chains, and closed chains that can be renamed.  */
-static struct du_head *open_chains;
-static struct du_head *closed_chains;
-
-/* Bitmap of open chains.  The bits set always match the list found in
-   open_chains.  */
-static bitmap_head open_chains_set;
-
-/* Record the registers being tracked in open_chains.  */
-static HARD_REG_SET live_in_chains;
-
-/* Record the registers that are live but not tracked.  The intersection
-   between this and live_in_chains is empty.  */
-static HARD_REG_SET live_hard_regs;
-
 /* Return true if OP is a reg for which all bits are set in PSET, false
    if all bits are clear.
    In other cases, set fail_current_block and return false.  */
@@ -571,7 +588,6 @@ create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
   head->nregs = this_nregs;
   head->need_caller_save_reg = 0;
   head->cannot_rename = 0;
-  head->terminated = 0;
 
   VEC_safe_push (du_head_p, heap, id_to_chain, head);
   head->id = current_id++;
@@ -650,7 +666,7 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
       int subset = (this_regno >= head->regno
                      && this_regno + this_nregs <= head->regno + head->nregs);
 
-      if (head->terminated
+      if (!bitmap_bit_p (&open_chains_set, head->id)
          || head->regno + head->nregs <= this_regno
          || this_regno + this_nregs <= head->regno)
        {
@@ -725,7 +741,6 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
        {
          unsigned nregs;
 
-         head->terminated = 1;
          if (subset && !superset)
            head->cannot_rename = 1;
          head->next_chain = closed_chains;
@@ -1384,29 +1399,6 @@ build_def_use (basic_block bb)
      is still open lives past the basic block, so it can't be renamed.  */
   return closed_chains;
 }
-
-/* Dump all def/use chains in CHAINS to DUMP_FILE.  They are
-   printed in reverse order as that's how we build them.  */
-
-static void
-dump_def_use_chain (struct du_head *head)
-{
-  while (head)
-    {
-      struct du_chain *this_du = head->first;
-      fprintf (dump_file, "Register %s (%d):",
-              reg_names[head->regno], head->nregs);
-      while (this_du)
-       {
-         fprintf (dump_file, " %d [%s]", INSN_UID (this_du->insn),
-                  reg_class_names[this_du->cl]);
-         this_du = this_du->next_use;
-       }
-      fprintf (dump_file, "\n");
-      head = head->next_chain;
-    }
-}
-
 \f
 static bool
 gate_handle_regrename (void)