OSDN Git Service

* regrename.h: New file.
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2011 17:26:26 +0000 (17:26 +0000)
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 19 Oct 2011 17:26:26 +0000 (17:26 +0000)
* regrename.c: Include it.  Also include "emit-rtl.h".
(struct du_head, struct du_chain, du_head_p DEF_VEC and
DEF_VEC_ALLOC_P): Move to regrename.h.
(do_replace): Remove declaration.
(insn_rr): New variable.
(cur_operand): New static variable.
(regrename_chain_from_id): Renamed from chain_from_id and no longer
static.  All callers changed.
(record_operand_use): New static function.
(scan_rtx_reg): Use it.
(find_best_rename_reg): New function, broken out of rename_chains.
(rename_chains): Use it.  Don't update chain regno and nregs here, ...
(regrename_do_replace): ... do it here instead.  Renamed from
do_replace, and no longer static.  All callers changed.
(regrename_analyze): No longer static.  New arg bb_mask.
All callers changed.  If bb_mask is nonzero, use it to limit the
number of basic blocks we analyze.  If we failed to analyze a block,
clear insn operand data.
(record_out_operands): New arg insn_info.  Update cur_operand if it is
nonnull.
(build_def_use): If insn_rr is nonnull, pass an insn_info to
record_out_operands, and update cur_operand here as well.
(regrename_init, regrename_finish): New functions.
(regrename_optimize): Use them.
* Makefile.in (regrename.o): Adjust dependencies.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@180198 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/Makefile.in
gcc/regrename.c
gcc/regrename.h [new file with mode: 0644]

index e4a45f4..1b69b06 100644 (file)
@@ -1,3 +1,32 @@
+2011-10-19  Bernd Schmidt  <bernds@codesourcery.com>
+
+       * regrename.h: New file.
+       * regrename.c: Include it.  Also include "emit-rtl.h".
+       (struct du_head, struct du_chain, du_head_p DEF_VEC and
+       DEF_VEC_ALLOC_P): Move to regrename.h.
+       (do_replace): Remove declaration.
+       (insn_rr): New variable.
+       (cur_operand): New static variable.
+       (regrename_chain_from_id): Renamed from chain_from_id and no longer
+       static.  All callers changed.
+       (record_operand_use): New static function.
+       (scan_rtx_reg): Use it.
+       (find_best_rename_reg): New function, broken out of rename_chains.
+       (rename_chains): Use it.  Don't update chain regno and nregs here, ...
+       (regrename_do_replace): ... do it here instead.  Renamed from
+       do_replace, and no longer static.  All callers changed.
+       (regrename_analyze): No longer static.  New arg bb_mask.
+       All callers changed.  If bb_mask is nonzero, use it to limit the
+       number of basic blocks we analyze.  If we failed to analyze a block,
+       clear insn operand data.
+       (record_out_operands): New arg insn_info.  Update cur_operand if it is
+       nonnull.
+       (build_def_use): If insn_rr is nonnull, pass an insn_info to
+       record_out_operands, and update cur_operand here as well.
+       (regrename_init, regrename_finish): New functions.
+       (regrename_optimize): Use them.
+       * Makefile.in (regrename.o): Adjust dependencies.
+
 2011-10-19  Tom de Vries  <tom@codesourcery.com>
 
        PR tree-optimization/50769
index a26b63b..6b28ef5 100644 (file)
@@ -3506,7 +3506,8 @@ regcprop.o : regcprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 regrename.o : regrename.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
    $(RTL_ERROR_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
    output.h $(RECOG_H) $(FUNCTION_H) $(OBSTACK_H) $(FLAGS_H) $(TM_P_H) \
-   addresses.h reload.h $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(TARGET_H)
+   addresses.h reload.h $(TIMEVAR_H) $(TREE_PASS_H) $(DF_H) $(TARGET_H) \
+   regrename.h $(EMIT_RTL_H)
 ifcvt.o : ifcvt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
    $(REGS_H) $(DIAGNOSTIC_CORE_H) $(FLAGS_H) insn-config.h $(FUNCTION_H) $(RECOG_H) \
    $(TARGET_H) $(BASIC_BLOCK_H) $(EXPR_H) output.h $(EXCEPT_H) $(TM_P_H) \
index bfff103..1823558 100644 (file)
@@ -39,6 +39,8 @@
 #include "tree-pass.h"
 #include "df.h"
 #include "target.h"
+#include "emit-rtl.h"
+#include "regrename.h"
 
 /* This file implements the RTL register renaming pass of the compiler.  It is
    a semi-local pass whose goal is to maximize the usage of the register file
 #error "Use a different bitmap implementation for untracked_operands."
 #endif
 
-/* We keep linked lists of DU_HEAD structures, each of which describes
-   a chain of occurrences of a reg.  */
-struct du_head
-{
-  /* The next chain.  */
-  struct du_head *next_chain;
-  /* The first and last elements of this chain.  */
-  struct du_chain *first, *last;
-  /* Describe the register being tracked, register number and count.  */
-  unsigned regno;
-  int nregs;
-
-  /* A unique id to be used as an index into the conflicts bitmaps.  */
-  unsigned id;
-  /* A bitmap to record conflicts with other chains.  */
-  bitmap_head conflicts;
-  /* Conflicts with untracked hard registers.  */
-  HARD_REG_SET hard_conflicts;
-
-  /* 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,
-     such as the SET_DEST of a CALL_INSN or an asm operand that used
-     to be a hard register.  */
-  unsigned int cannot_rename:1;
-};
-
-/* This struct describes a single occurrence of a register.  */
-struct du_chain
-{
-  /* Links to the next occurrence of the register.  */
-  struct du_chain *next_use;
-
-  /* The insn where the register appears.  */
-  rtx insn;
-  /* The location inside the insn.  */
-  rtx *loc;
-  /* The register class required by the insn at this location.  */
-  ENUM_BITFIELD(reg_class) cl : 16;
-};
-
 enum scan_actions
 {
   terminate_write,
@@ -144,15 +105,14 @@ static int this_tick = 0;
 
 static struct obstack rename_obstack;
 
-static void do_replace (struct du_head *, int);
+/* If nonnull, the code calling into the register renamer requested
+   information about insn operands, and we store it here.  */
+VEC(insn_rr_info, heap) *insn_rr;
+
 static void scan_rtx (rtx, rtx *, enum reg_class, enum scan_actions,
                      enum op_type);
 static bool build_def_use (basic_block);
 
-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;
 
@@ -173,10 +133,15 @@ static HARD_REG_SET live_in_chains;
    between this and live_in_chains is empty.  */
 static HARD_REG_SET live_hard_regs;
 
+/* Set while scanning RTL if INSN_RR is nonnull, i.e. if the current analysis
+   is for a caller that requires operand data.  Used in
+   record_operand_use.  */
+static operand_rr_info *cur_operand;
+
 /* Return the chain corresponding to id number ID.  Take into account that
    chains may have been merged.  */
-static du_head_p
-chain_from_id (unsigned int id)
+du_head_p
+regrename_chain_from_id (unsigned int id)
 {
   du_head_p first_chain = VEC_index (du_head_p, id_to_chain, id);
   du_head_p chain = first_chain;
@@ -237,6 +202,19 @@ mark_conflict (struct du_head *chains, unsigned id)
     }
 }
 
+/* Examine cur_operand, and if it is nonnull, record information about the
+   use THIS_DU which is part of the chain HEAD.  */
+
+static void
+record_operand_use (struct du_head *head, struct du_chain *this_du)
+{
+  if (cur_operand == NULL)
+    return;
+  gcc_assert (cur_operand->n_chains < MAX_REGS_PER_ADDRESS);
+  cur_operand->heads[cur_operand->n_chains] = head;
+  cur_operand->chains[cur_operand->n_chains++] = this_du;
+}
+
 /* Create a new chain for THIS_NREGS registers starting at THIS_REGNO,
    and record its occurrence in *LOC, which is being written to in INSN.
    This access requires a register of class CL.  */
@@ -299,6 +277,7 @@ create_new_chain (unsigned this_regno, unsigned this_nregs, rtx *loc,
   this_du->loc = loc;
   this_du->insn = insn;
   this_du->cl = cl;
+  record_operand_use (head, this_du);
   return head;
 }
 
@@ -313,7 +292,7 @@ merge_overlapping_regs (HARD_REG_SET *pset, struct du_head *head)
   IOR_HARD_REG_SET (*pset, head->hard_conflicts);
   EXECUTE_IF_SET_IN_BITMAP (&head->conflicts, 0, i, bi)
     {
-      du_head_p other = chain_from_id (i);
+      du_head_p other = regrename_chain_from_id (i);
       unsigned j = other->nregs;
       gcc_assert (other != head);
       while (j-- > 0)
@@ -368,6 +347,69 @@ check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
   return true;
 }
 
+/* For the chain THIS_HEAD, compute and return the best register to
+   rename to.  SUPER_CLASS is the superunion of register classes in
+   the chain.  UNAVAILABLE is a set of registers that cannot be used.
+   OLD_REG is the register currently used for the chain.  */
+
+int
+find_best_rename_reg (du_head_p this_head, enum reg_class super_class,
+                     HARD_REG_SET *unavailable, int old_reg)
+{
+  bool has_preferred_class;
+  enum reg_class preferred_class;
+  int pass;
+  int best_new_reg = old_reg;
+
+  /* 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 (*unavailable, call_used_reg_set);
+
+  /* Mark registers that overlap this chain's lifetime as unavailable.  */
+  merge_overlapping_regs (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++)
+    {
+      int new_reg;
+      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 (old_reg, new_reg, this_head,
+                              *unavailable)
+             && ((pass == 0
+                  && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
+                                         best_new_reg))
+                 || tick[best_new_reg] > tick[new_reg]))
+           best_new_reg = new_reg;
+       }
+      if (pass == 0 && best_new_reg != old_reg)
+       break;
+    }
+  return best_new_reg;
+}
+
 /* Perform register renaming on the current function.  */
 static void
 rename_chains (void)
@@ -390,22 +432,16 @@ rename_chains (void)
 
   FOR_EACH_VEC_ELT (du_head_p, id_to_chain, i, this_head)
     {
-      int new_reg, best_new_reg, best_nregs;
+      int best_new_reg;
       int n_uses;
       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;
 
       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)
@@ -437,56 +473,8 @@ rename_chains (void)
       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;
-       }
+      best_new_reg = find_best_rename_reg (this_head, super_class,
+                                          &this_unavailable, reg);
 
       if (dump_file)
        {
@@ -507,9 +495,7 @@ rename_chains (void)
       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;
+      regrename_do_replace (this_head, best_new_reg);
       tick[best_new_reg] = ++this_tick;
       df_set_regs_ever_live (best_new_reg, true);
     }
@@ -675,8 +661,8 @@ merge_chains (du_head_p c1, du_head_p c2)
 
 /* Analyze the current function and build chains for renaming.  */
 
-static void
-regrename_analyze (void)
+void
+regrename_analyze (bitmap bb_mask)
 {
   struct bb_rename_info *rename_info;
   int i;
@@ -694,7 +680,10 @@ regrename_analyze (void)
     {
       struct bb_rename_info *ri = rename_info + i;
       ri->bb = bb;
-      bb->aux = ri;
+      if (bb_mask != NULL && !bitmap_bit_p (bb_mask, bb->index))
+       bb->aux = NULL;
+      else
+       bb->aux = ri;
       i++;
     }
 
@@ -735,6 +724,16 @@ regrename_analyze (void)
          current_id = old_length;
          bitmap_clear (&this_info->incoming_open_chains_set);
          open_chains = NULL;
+         if (insn_rr != NULL)
+           {
+             rtx insn;
+             FOR_BB_INSNS (bb1, insn)
+               {
+                 insn_rr_info *p = VEC_index (insn_rr_info, insn_rr,
+                                              INSN_UID (insn));
+                 p->op_info = NULL;
+               }
+           }
          continue;
        }
 
@@ -798,7 +797,7 @@ regrename_analyze (void)
        {
          edge e;
          edge_iterator ei;
-         struct du_head *chain = chain_from_id (j);
+         struct du_head *chain = regrename_chain_from_id (j);
          int n_preds_used = 0, n_preds_joined = 0;
 
          FOR_EACH_EDGE (e, ei, bb->preds)
@@ -825,7 +824,7 @@ regrename_analyze (void)
              EXECUTE_IF_SET_IN_BITMAP (&src_ri->open_chains_set,
                                        0, k, bi2)
                {
-                 struct du_head *outgoing_chain = chain_from_id (k);
+                 struct du_head *outgoing_chain = regrename_chain_from_id (k);
 
                  if (outgoing_chain->regno == chain->regno
                      && outgoing_chain->nregs == chain->nregs)
@@ -863,7 +862,7 @@ regrename_analyze (void)
        {
          edge e;
          edge_iterator ei;
-         struct du_head *chain = chain_from_id (j);
+         struct du_head *chain = regrename_chain_from_id (j);
          int n_succs_used = 0, n_succs_joined = 0;
 
          FOR_EACH_EDGE (e, ei, bb->succs)
@@ -888,7 +887,7 @@ regrename_analyze (void)
              EXECUTE_IF_SET_IN_BITMAP (&dest_ri->incoming_open_chains_set,
                                        0, k, bi2)
                {
-                 struct du_head *incoming_chain = chain_from_id (k);
+                 struct du_head *incoming_chain = regrename_chain_from_id (k);
 
                  if (incoming_chain->regno == chain->regno
                      && incoming_chain->nregs == chain->nregs)
@@ -928,11 +927,12 @@ regrename_analyze (void)
     bb->aux = NULL;
 }
 
-static void
-do_replace (struct du_head *head, int reg)
+void
+regrename_do_replace (struct du_head *head, int reg)
 {
   struct du_chain *chain;
   unsigned int base_regno = head->regno;
+  enum machine_mode mode;
 
   for (chain = head->first; chain; chain = chain->next_use)
     {
@@ -953,6 +953,10 @@ do_replace (struct du_head *head, int reg)
 
       df_insn_rescan (chain->insn);
     }
+
+  mode = GET_MODE (*head->first->loc);
+  head->regno = reg;
+  head->nregs = hard_regno_nregs[reg][mode];
 }
 
 
@@ -1106,6 +1110,7 @@ scan_rtx_reg (rtx insn, rtx *loc, enum reg_class cl, enum scan_actions action,
                head->first = this_du;
              else
                head->last->next_use = this_du;
+             record_operand_use (head, this_du);
              head->last = this_du;
            }
          /* Avoid adding the same location in a DEBUG_INSN multiple times,
@@ -1468,10 +1473,11 @@ restore_operands (rtx insn, int n_ops, rtx *old_operands, rtx *old_dups)
 
 /* For each output operand of INSN, call scan_rtx to create a new
    open chain.  Do this only for normal or earlyclobber outputs,
-   depending on EARLYCLOBBER.  */
+   depending on EARLYCLOBBER.  If INSN_INFO is nonnull, use it to
+   record information about the operands in the insn.  */
 
 static void
-record_out_operands (rtx insn, bool earlyclobber)
+record_out_operands (rtx insn, bool earlyclobber, insn_rr_info *insn_info)
 {
   int n_ops = recog_data.n_operands;
   int alt = which_alternative;
@@ -1493,6 +1499,9 @@ record_out_operands (rtx insn, bool earlyclobber)
          || recog_op_alt[opn][alt].earlyclobber != earlyclobber)
        continue;
 
+      if (insn_info)
+       cur_operand = insn_info->op_info + i;
+
       prev_open = open_chains;
       scan_rtx (insn, loc, cl, mark_write, OP_OUT);
 
@@ -1510,6 +1519,7 @@ record_out_operands (rtx insn, bool earlyclobber)
            open_chains->cannot_rename = 1;
        }
     }
+  cur_operand = NULL;
 }
 
 /* Build def/use chain.  */
@@ -1535,6 +1545,7 @@ build_def_use (basic_block bb)
          int predicated;
          enum rtx_code set_code = SET;
          enum rtx_code clobber_code = CLOBBER;
+         insn_rr_info *insn_info = NULL;
 
          /* Process the insn, determining its effect on the def-use
             chains and live hard registers.  We perform the following
@@ -1567,6 +1578,15 @@ build_def_use (basic_block bb)
          n_ops = recog_data.n_operands;
          untracked_operands = 0;
 
+         if (insn_rr != NULL)
+           {
+             insn_info = VEC_index (insn_rr_info, insn_rr, INSN_UID (insn));
+             insn_info->op_info = XOBNEWVEC (&rename_obstack, operand_rr_info,
+                                             recog_data.n_operands);
+             memset (insn_info->op_info, 0,
+                     sizeof (operand_rr_info) * recog_data.n_operands);
+           }
+
          /* Simplify the code below by rewriting things to reflect
             matching constraints.  Also promote OP_OUT to OP_INOUT in
             predicated instructions, but only for register operands
@@ -1625,7 +1645,7 @@ build_def_use (basic_block bb)
 
          /* Step 1b: Begin new chains for earlyclobbered writes inside
             operands.  */
-         record_out_operands (insn, true);
+         record_out_operands (insn, true, insn_info);
 
          /* Step 2: Mark chains for which we have reads outside operands
             as unrenamable.
@@ -1674,11 +1694,14 @@ build_def_use (basic_block bb)
                  || untracked_operands & (1 << opn))
                continue;
 
+             if (insn_info)
+               cur_operand = i == opn ? insn_info->op_info + i : NULL;
              if (recog_op_alt[opn][alt].is_address)
                scan_rtx_address (insn, loc, cl, mark_read, VOIDmode);
              else
                scan_rtx (insn, loc, cl, mark_read, type);
            }
+         cur_operand = NULL;
 
          /* Step 3B: Record updates for regs in REG_INC notes, and
             source regs in REG_FRAME_RELATED_EXPR notes.  */
@@ -1729,7 +1752,7 @@ build_def_use (basic_block bb)
          restore_operands (insn, n_ops, old_operands, old_dups);
 
          /* Step 6b: Begin new chains for writes inside operands.  */
-         record_out_operands (insn, false);
+         record_out_operands (insn, false, insn_info);
 
          /* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR
             notes for update.  */
@@ -1766,6 +1789,26 @@ build_def_use (basic_block bb)
   return true;
 }
 \f
+/* Initialize the register renamer.  If INSN_INFO is true, ensure that
+   insn_rr is nonnull.  */
+void
+regrename_init (bool insn_info)
+{
+  gcc_obstack_init (&rename_obstack);
+  insn_rr = NULL;
+  if (insn_info)
+    VEC_safe_grow_cleared (insn_rr_info, heap, insn_rr, get_max_uid ());
+}
+
+/* Free all global data used by the register renamer.  */
+void
+regrename_finish (void)
+{
+  VEC_free (insn_rr_info, heap, insn_rr);
+  free_chain_data ();
+  obstack_free (&rename_obstack, NULL);
+}
+
 /* Perform register renaming on the current function.  */
 
 static unsigned int
@@ -1776,14 +1819,13 @@ regrename_optimize (void)
   df_analyze ();
   df_set_flags (DF_DEFER_INSN_RESCAN);
 
-  gcc_obstack_init (&rename_obstack);
+  regrename_init (false);
 
-  regrename_analyze ();
+  regrename_analyze (NULL);
 
   rename_chains ();
 
-  free_chain_data ();
-  obstack_free (&rename_obstack, NULL);
+  regrename_finish ();
 
   return 0;
 }
diff --git a/gcc/regrename.h b/gcc/regrename.h
new file mode 100644 (file)
index 0000000..f3969a1
--- /dev/null
@@ -0,0 +1,101 @@
+/* This file contains definitions for the register renamer.
+   Copyright (C) 2011
+   Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_REGRENAME_H
+#define GCC_REGRENAME_H
+
+/* We keep linked lists of DU_HEAD structures, each of which describes
+   a chain of occurrences of a reg.  */
+struct du_head
+{
+  /* The next chain.  */
+  struct du_head *next_chain;
+  /* The first and last elements of this chain.  */
+  struct du_chain *first, *last;
+  /* Describes the register being tracked.  */
+  unsigned regno;
+  int nregs;
+
+  /* A unique id to be used as an index into the conflicts bitmaps.  */
+  unsigned id;
+  /* A bitmap to record conflicts with other chains.  */
+  bitmap_head conflicts;
+  /* Conflicts with untracked hard registers.  */
+  HARD_REG_SET hard_conflicts;
+
+  /* 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,
+     such as the SET_DEST of a CALL_INSN or an asm operand that used
+     to be a hard register.  */
+  unsigned int cannot_rename:1;
+};
+
+typedef struct du_head *du_head_p;
+DEF_VEC_P (du_head_p);
+DEF_VEC_ALLOC_P (du_head_p, heap);
+
+/* This struct describes a single occurrence of a register.  */
+struct du_chain
+{
+  /* Links to the next occurrence of the register.  */
+  struct du_chain *next_use;
+
+  /* The insn where the register appears.  */
+  rtx insn;
+  /* The location inside the insn.  */
+  rtx *loc;
+  /* The register class required by the insn at this location.  */
+  ENUM_BITFIELD(reg_class) cl : 16;
+};
+
+/* This struct describes data gathered during regrename_analyze about
+   a single operand of an insn.  */
+typedef struct
+{
+  /* The number of chains recorded for this operand.  */
+  int n_chains;
+  /* Holds either the chain for the operand itself, or for the registers in
+     a memory operand.  */
+  struct du_chain *chains[MAX_REGS_PER_ADDRESS];
+  struct du_head *heads[MAX_REGS_PER_ADDRESS];
+} operand_rr_info;
+
+/* A struct to hold a vector of operand_rr_info structures describing the
+   operands of an insn.  */
+typedef struct
+{
+  operand_rr_info *op_info;
+} insn_rr_info;
+
+DEF_VEC_O (insn_rr_info);
+DEF_VEC_ALLOC_O (insn_rr_info, heap);
+
+extern VEC(insn_rr_info, heap) *insn_rr;
+
+extern void regrename_init (bool);
+extern void regrename_finish (void);
+extern void regrename_analyze (bitmap);
+extern du_head_p regrename_chain_from_id (unsigned int);
+extern int find_best_rename_reg (du_head_p, enum reg_class, HARD_REG_SET *,
+                                int);
+extern void regrename_do_replace (du_head_p, int);
+
+#endif