regrename.h: New file.

* 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.

From-SVN: r180198
This commit is contained in:
Bernd Schmidt 2011-10-19 17:26:26 +00:00 committed by Bernd Schmidt
parent 40f73edd0c
commit 1f234b83b8
4 changed files with 300 additions and 127 deletions

View 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

View 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) \

View 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
@ -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, 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;
}
/* 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;
}

101
gcc/regrename.h Normal file
View File

@ -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