diff mbox

[1/2] Make regrename callable from target reorg code

Message ID 4E85E980.4090407@codesourcery.com
State New
Headers show

Commit Message

Bernd Schmidt Sept. 30, 2011, 4:08 p.m. UTC
The main purpose of this patch is to move some declarations to a new
file, regrename.h, and make regrename_analyze and do_replace callable
from elsewhere. The second patch will add code to c6x.c to make use of
this from the modulo-scheduling code.

This also adds a small amount of new functionality: regrename can now
record data for each insn about which chains occur in the operands.

Now testing on c6x-elf; an i686-linux bootstrap with regrenaming enabled
at -O1 completed. The patch has also been in our 4.5 tree for a while
now. Ok?


Bernd
gcc/
	* 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.

Comments

Richard Henderson Sept. 30, 2011, 6:29 p.m. UTC | #1
On 09/30/2011 09:08 AM, Bernd Schmidt wrote:
> 	gcc/
> 	* 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.

Ok.


r~
diff mbox

Patch

Index: gcc/regrename.c
===================================================================
--- gcc/regrename.c	(revision 179379)
+++ gcc/regrename.c	(working copy)
@@ -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
@@ -73,47 +75,6 @@ 
 #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, u
     }
 }
 
+/* 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, u
   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 *ps
   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_UNUSE
   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 re
 
       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 r
 		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, r
 
 /* 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 earl
 	  || 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 earl
 	    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;
 }
 
+/* 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;
 }
Index: gcc/regrename.h
===================================================================
--- gcc/regrename.h	(revision 0)
+++ gcc/regrename.h	(revision 0)
@@ -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
Index: gcc/Makefile.in
===================================================================
--- gcc/Makefile.in	(revision 179379)
+++ gcc/Makefile.in	(working copy)
@@ -3505,7 +3505,8 @@  regcprop.o : regcprop.c $(CONFIG_H) $(SY
 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) \