Makefile.in (stupid.o): Update dependencies.

* Makefile.in (stupid.o): Update dependencies.
	(global.o): Likewise.
	* global.c: Include reload.h
	(reg_becomes_live): New function.
	(reg_dies): New function.
	(build_insn_chain): New function.
	(global_alloc): Call build_insn_chain before calling reload.
	* reload.h (struct needs): New structure definition.
	(struct insn_chain): Likewise.
	(reload_insn_chain): Declare variable.
	(new_insn_chain): Declare function.
	* reload1.c (reload_startobj): New variable.
	(reload_insn_chain): New variable.
	(unused_insn_chains): New variable.
	(new_insn_chain): New function.
	(init_reload): Initialize reload_startobj, not reload_firstobj.
	(reload): Initialize reload_firstobj.
	Before returning, free everything on the reload_obstack.
	* stupid.c: Include insn-config.h, reload.h and basic-block.h.
	(reg_where_dead_chain, reg_where_born_exact, reg_where_born_clobber,
	current_chain): New variables.
	(reg_where_born): Delete variable.
	(REG_WHERE_BORN): New macro.
	(find_clobbered_regs): New function.
	(stupid_life_analysis): Don't allocate/free reg_where_born.
	Allocate and free reg_where_born_exact, reg_where_born_clobber,
	reg_where_dead_chain.
	Use REG_WHERE_BORN instead of reg_where_born.
	While processing the insns, build the reload_insn_chain with
	information about register lifetimes.
	(stupid_reg_compare): Use REG_WHERE_BORN instead of reg_where_born.
	(stupid_mark_refs): Replace arg INSN with arg CHAIN.  All callers
	changed.
	Compute and information about birth and death of pseudo registers in
	reg_where_dead_chain, reg_where_born_exact and reg_where_born_clobber.
	Delete code to set elements of reg_where_born.

From-SVN: r22862
This commit is contained in:
Bernd Schmidt 1998-10-05 18:39:23 -06:00 committed by Jeff Law
parent 0eaae86cab
commit cad6f7d050
6 changed files with 455 additions and 28 deletions

View File

@ -1,3 +1,47 @@
Tue Oct 6 01:36:00 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
* Makefile.in (stupid.o): Update dependencies.
(global.o): Likewise.
* global.c: Include reload.h
(reg_becomes_live): New function.
(reg_dies): New function.
(build_insn_chain): New function.
(global_alloc): Call build_insn_chain before calling reload.
* reload.h (struct needs): New structure definition.
(struct insn_chain): Likewise.
(reload_insn_chain): Declare variable.
(new_insn_chain): Declare function.
* reload1.c (reload_startobj): New variable.
(reload_insn_chain): New variable.
(unused_insn_chains): New variable.
(new_insn_chain): New function.
(init_reload): Initialize reload_startobj, not reload_firstobj.
(reload): Initialize reload_firstobj.
Before returning, free everything on the reload_obstack.
* stupid.c: Include insn-config.h, reload.h and basic-block.h.
(reg_where_dead_chain, reg_where_born_exact, reg_where_born_clobber,
current_chain): New variables.
(reg_where_born): Delete variable.
(REG_WHERE_BORN): New macro.
(find_clobbered_regs): New function.
(stupid_life_analysis): Don't allocate/free reg_where_born.
Allocate and free reg_where_born_exact, reg_where_born_clobber,
reg_where_dead_chain.
Use REG_WHERE_BORN instead of reg_where_born.
While processing the insns, build the reload_insn_chain with
information about register lifetimes.
(stupid_reg_compare): Use REG_WHERE_BORN instead of reg_where_born.
(stupid_mark_refs): Replace arg INSN with arg CHAIN. All callers
changed.
Compute and information about birth and death of pseudo registers in
reg_where_dead_chain, reg_where_born_exact and reg_where_born_clobber.
Delete code to set elements of reg_where_born.
Mon Oct 5 22:34:30 1998 Alexandre Petit-Bianco <apbianco@cygnus.com>
* tree.def (GOTO_EXPR): Modified documentation.

View File

@ -1461,7 +1461,7 @@ jump.o : jump.c $(CONFIG_H) system.h $(RTL_H) flags.h hard-reg-set.h $(REGS_H) \
insn-config.h insn-flags.h $(RECOG_H) $(EXPR_H) real.h except.h \
toplev.h
stupid.o : stupid.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h \
flags.h toplev.h
$(BASIC_BLOCK_H) insn-config.h reload.h flags.h toplev.h
cse.o : cse.c $(CONFIG_H) system.h $(RTL_H) $(REGS_H) hard-reg-set.h flags.h \
real.h insn-config.h $(RECOG_H) $(EXPR_H) toplev.h output.h
@ -1487,7 +1487,7 @@ local-alloc.o : local-alloc.c $(CONFIG_H) system.h $(RTL_H) flags.h \
insn-attr.h toplev.h
bitmap.o : bitmap.c $(CONFIG_H) system.h $(RTL_H) flags.h $(BASIC_BLOCK_H) \
$(REGS_H)
global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h \
global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h reload.h \
$(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h
varray.o : varray.c $(CONFIG_H) system.h varray.h $(RTL_H) $(TREE_H) bitmap.h

View File

@ -29,6 +29,7 @@ Boston, MA 02111-1307, USA. */
#include "basic-block.h"
#include "regs.h"
#include "insn-config.h"
#include "reload.h"
#include "output.h"
#include "toplev.h"
@ -268,6 +269,9 @@ static void mark_reg_death PROTO((rtx));
static void mark_reg_live_nc PROTO((int, enum machine_mode));
static void set_preference PROTO((rtx, rtx));
static void dump_conflicts PROTO((FILE *));
static void reg_becomes_live PROTO((rtx, rtx));
static void reg_dies PROTO((int, enum machine_mode));
static void build_insn_chain PROTO((rtx));
/* Perform allocation of pseudo-registers not allocated by local_alloc.
FILE is a file to output debugging information on,
@ -573,7 +577,10 @@ global_alloc (file)
for the sake of debugging information. */
if (n_basic_blocks > 0)
#endif
retval = reload (get_insns (), 1, file);
{
build_insn_chain (get_insns ());
retval = reload (get_insns (), 1, file);
}
free (conflicts);
return retval;
@ -1648,6 +1655,135 @@ mark_elimination (from, to)
}
}
/* Used for communication between the following functions. Holds the
current life information. */
static regset live_relevant_regs;
/* Record in live_relevant_regs that register REG became live. This
is called via note_stores. */
static void
reg_becomes_live (reg, setter)
rtx reg;
rtx setter ATTRIBUTE_UNUSED;
{
int regno;
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
if (GET_CODE (reg) != REG)
return;
regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
{
int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (nregs-- > 0)
SET_REGNO_REG_SET (live_relevant_regs, regno++);
}
else if (reg_renumber[regno] >= 0)
SET_REGNO_REG_SET (live_relevant_regs, regno);
}
/* Record in live_relevant_regs that register REGNO died. */
static void
reg_dies (regno, mode)
int regno;
enum machine_mode mode;
{
if (regno < FIRST_PSEUDO_REGISTER)
{
int nregs = HARD_REGNO_NREGS (regno, mode);
while (nregs-- > 0)
CLEAR_REGNO_REG_SET (live_relevant_regs, regno++);
}
else
CLEAR_REGNO_REG_SET (live_relevant_regs, regno);
}
/* Walk the insns of the current function and build reload_insn_chain,
and record register life information. */
static void
build_insn_chain (first)
rtx first;
{
struct insn_chain **p = &reload_insn_chain;
struct insn_chain *prev = 0;
int b = 0;
live_relevant_regs = ALLOCA_REG_SET ();
for (; first; first = NEXT_INSN (first))
{
struct insn_chain *c;
if (first == basic_block_head[b])
{
int i;
CLEAR_REG_SET (live_relevant_regs);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (REGNO_REG_SET_P (basic_block_live_at_start[b], i)
&& ! TEST_HARD_REG_BIT (eliminable_regset, i))
SET_REGNO_REG_SET (live_relevant_regs, i);
for (; i < max_regno; i++)
if (reg_renumber[i] >= 0
&& REGNO_REG_SET_P (basic_block_live_at_start[b], i))
SET_REGNO_REG_SET (live_relevant_regs, i);
}
if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
{
c = new_insn_chain ();
c->prev = prev;
prev = c;
*p = c;
p = &c->next;
c->insn = first;
c->block = b;
COPY_REG_SET (c->live_before, live_relevant_regs);
if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
{
rtx link;
/* Mark the death of everything that dies in this instruction. */
for (link = REG_NOTES (first); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_DEAD
&& GET_CODE (XEXP (link, 0)) == REG)
reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
/* Mark everything born in this instruction as live. */
note_stores (PATTERN (first), reg_becomes_live);
}
/* Remember which registers are live at the end of the insn, before
killing those with REG_UNUSED notes. */
COPY_REG_SET (c->live_after, live_relevant_regs);
if (GET_RTX_CLASS (GET_CODE (first)) == 'i')
{
rtx link;
/* Mark anything that is set in this insn and then unused as dying. */
for (link = REG_NOTES (first); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_UNUSED
&& GET_CODE (XEXP (link, 0)) == REG)
reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)));
}
}
if (first == basic_block_end[b])
b++;
}
FREE_REG_SET (live_relevant_regs);
*p = 0;
}
/* Print debugging trace information if -greg switch is given,
showing the information on which the allocation decisions are based. */

View File

@ -142,6 +142,81 @@ extern enum insn_code reload_in_optab[];
extern enum insn_code reload_out_optab[];
#endif
struct needs
{
/* [0] is normal, [1] is nongroup. */
short regs[2][N_REG_CLASSES];
short groups[N_REG_CLASSES];
};
#if defined SET_HARD_REG_BIT && defined CLEAR_REG_SET
/* This structure describes instructions which are relevant for reload.
Apart from all regular insns, this also includes CODE_LABELs, since they
must be examined for register elimination. */
struct insn_chain
{
/* Links to the neighbour instructions. */
struct insn_chain *next, *prev;
/* Link through a chains set up by calculate_needs_all_insns, containing
all insns that need reloading. */
struct insn_chain *next_need_reload;
/* The basic block this insn is in. */
int block;
/* The rtx of the insn. */
rtx insn;
/* Register life information: record all live hard registers, and all
live pseudos that have a hard register.
This information is recorded for the point immediately before the insn
(in live_before), and for the point within the insn at which all
outputs have just been written to (in live_after). */
regset live_before;
regset live_after;
/* For each class, size of group of consecutive regs
that is needed for the reloads of this class. */
char group_size[N_REG_CLASSES];
/* For each class, the machine mode which requires consecutive
groups of regs of that class.
If two different modes ever require groups of one class,
they must be the same size and equally restrictive for that class,
otherwise we can't handle the complexity. */
enum machine_mode group_mode[N_REG_CLASSES];
/* Indicates if a register was counted against the need for
groups. 0 means it can count against max_nongroup instead. */
HARD_REG_SET counted_for_groups;
/* Indicates if a register was counted against the need for
non-groups. 0 means it can become part of a new group.
During choose_reload_regs, 1 here means don't use this reg
as part of a group, even if it seems to be otherwise ok. */
HARD_REG_SET counted_for_nongroups;
/* Indicates which registers have already been used for spills. */
HARD_REG_SET used_spill_regs;
/* Describe the needs for reload registers of this insn. */
struct needs need;
/* Nonzero if find_reloads said the insn requires reloading. */
unsigned int need_reload:1;
/* Nonzero if eliminate_regs_in_insn said it requires eliminations. */
unsigned int need_elim:1;
/* Nonzero if this insn was inserted by perform_caller_saves. */
unsigned int is_caller_save_insn:1;
};
/* A chain of insn_chain structures to describe all non-note insns in
a function. */
extern struct insn_chain *reload_insn_chain;
/* Allocate a new insn_chain structure. */
extern struct insn_chain *new_insn_chain PROTO((void));
#endif
/* Functions from reload.c: */
/* Return a memory location that will be used to copy X in mode MODE.

View File

@ -32,9 +32,9 @@ Boston, MA 02111-1307, USA. */
#include "flags.h"
#include "expr.h"
#include "regs.h"
#include "basic-block.h"
#include "reload.h"
#include "recog.h"
#include "basic-block.h"
#include "output.h"
#include "real.h"
#include "toplev.h"
@ -279,6 +279,13 @@ enum insn_code reload_out_optab[NUM_MACHINE_MODES];
insn. */
struct obstack reload_obstack;
/* Points to the beginning of the reload_obstack. All insn_chain structures
are allocated first. */
char *reload_startobj;
/* The point after all insn_chain structures. Used to quickly deallocate
memory used while processing one insn. */
char *reload_firstobj;
#define obstack_chunk_alloc xmalloc
@ -286,6 +293,10 @@ char *reload_firstobj;
/* List of labels that must never be deleted. */
extern rtx forced_labels;
/* List of insn_chain instructions, one for every insn that reload needs to
examine. */
struct insn_chain *reload_insn_chain;
/* This structure is used to record information about register eliminations.
Each array entry describes one possible way of eliminating a register
@ -461,7 +472,7 @@ init_reload ()
/* Initialize obstack for our rtl allocation. */
gcc_obstack_init (&reload_obstack);
reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
reload_startobj = (char *) obstack_alloc (&reload_obstack, 0);
/* Decide which register class should be used when reloading
addresses. If we are using SMALL_REGISTER_CLASSES, and any
@ -522,6 +533,32 @@ init_reload ()
}
}
/* List of insn chains that are currently unused. */
static struct insn_chain *unused_insn_chains = 0;
/* Allocate an empty insn_chain structure. */
struct insn_chain *
new_insn_chain ()
{
struct insn_chain *c;
if (unused_insn_chains == 0)
{
c = obstack_alloc (&reload_obstack, sizeof (struct insn_chain));
c->live_before = OBSTACK_ALLOC_REG_SET (&reload_obstack);
c->live_after = OBSTACK_ALLOC_REG_SET (&reload_obstack);
}
else
{
c = unused_insn_chains;
unused_insn_chains = c->next;
}
c->is_caller_save_insn = 0;
c->need_reload = 0;
c->need_elim = 0;
return c;
}
/* Global variables used by reload and its subroutines. */
/* Set during calculate_needs if an insn needs reloading. */
@ -605,6 +642,8 @@ reload (first, global, dumpfile)
failure = 0;
reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
/* Enable find_equiv_reg to distinguish insns made by reload. */
reload_first_uid = get_max_uid ();
@ -1217,7 +1256,9 @@ reload (first, global, dumpfile)
if (size > STACK_CHECK_MAX_FRAME_SIZE)
warning ("frame size too large for reliable stack checking");
}
obstack_free (&reload_obstack, reload_startobj);
/* Indicate that we no longer have known memory locations or constants. */
reg_equiv_constant = 0;
reg_equiv_memory_loc = 0;

View File

@ -47,7 +47,10 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
#include "regs.h"
#include "insn-config.h"
#include "reload.h"
#include "flags.h"
#include "toplev.h"
@ -77,9 +80,21 @@ static int last_setjmp_suid;
static int *reg_where_dead;
/* Element N is suid of insn where life span of pseudo reg N begins. */
/* Likewise, but point to the insn_chain structure of the insn at which
the reg dies. */
static struct insn_chain **reg_where_dead_chain;
static int *reg_where_born;
/* Element N is suid of insn where life span of pseudo reg N begins. */
static int *reg_where_born_exact;
/* Element N is 1 if the birth of pseudo reg N is due to a CLOBBER,
0 otherwise. */
static int *reg_where_born_clobber;
/* Return the suid of the insn where the register is born, or the suid
of the insn before if the birth is due to a CLOBBER. */
#define REG_WHERE_BORN(N) \
(reg_where_born_exact[(N)] - reg_where_born_clobber[(N)])
/* Numbers of pseudo-regs to be allocated, highest priority first. */
@ -111,7 +126,43 @@ static HARD_REG_SET *after_insn_hard_regs;
static int stupid_reg_compare PROTO((const GENERIC_PTR,const GENERIC_PTR));
static int stupid_find_reg PROTO((int, enum reg_class, enum machine_mode,
int, int, int));
static void stupid_mark_refs PROTO((rtx, rtx));
static void stupid_mark_refs PROTO((rtx, struct insn_chain *));
static void find_clobbered_regs PROTO((rtx, rtx));
/* For communication between stupid_life_analysis and find_clobbered_regs. */
static struct insn_chain *current_chain;
/* This function, called via note_stores, marks any hard registers that are
clobbered in an insn as being live in the live_after and live_before fields
of the appropriate insn_chain structure. */
static void
find_clobbered_regs (reg, setter)
rtx reg, setter;
{
int regno, nregs;
if (setter == 0 || GET_CODE (setter) != CLOBBER)
return;
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
if (GET_CODE (reg) != REG)
return;
regno = REGNO (reg);
if (regno >= FIRST_PSEUDO_REGISTER)
return;
if (GET_MODE (reg) == VOIDmode)
abort ();
else
nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg));
while (nregs-- > 0)
{
SET_REGNO_REG_SET (current_chain->live_after, regno);
SET_REGNO_REG_SET (current_chain->live_before, regno++);
}
}
/* Stupid life analysis is for the case where only variables declared
`register' go in registers. For this case, we mark all
@ -171,9 +222,15 @@ stupid_life_analysis (f, nregs, file)
reg_where_dead = (int *) xmalloc (nregs * sizeof (int));
bzero ((char *) reg_where_dead, nregs * sizeof (int));
reg_where_born = (int *) xmalloc (nregs * sizeof (int));
bzero ((char *) reg_where_born, nregs * sizeof (int));
reg_where_born_exact = (int *) xmalloc (nregs * sizeof (int));
bzero ((char *) reg_where_born_exact, nregs * sizeof (int));
reg_where_born_clobber = (int *) xmalloc (nregs * sizeof (int));
bzero ((char *) reg_where_born_clobber, nregs * sizeof (int));
reg_where_dead_chain = (struct insn_chain **) xmalloc (nregs * sizeof (struct insn_chain *));
bzero ((char *) reg_where_dead_chain, nregs * sizeof (struct insn_chain *));
reg_order = (int *) xmalloc (nregs * sizeof (int));
bzero ((char *) reg_order, nregs * sizeof (int));
@ -210,11 +267,15 @@ stupid_life_analysis (f, nregs, file)
Also find where each hard register is live
and record that info in after_insn_hard_regs.
regs_live[I] is 1 if hard reg I is live
at the current point in the scan. */
at the current point in the scan.
Build reload_insn_chain while we're walking the insns. */
reload_insn_chain = 0;
for (insn = last; insn; insn = PREV_INSN (insn))
{
register HARD_REG_SET *p = after_insn_hard_regs + INSN_SUID (insn);
struct insn_chain *chain;
/* Copy the info in regs_live into the element of after_insn_hard_regs
for the current position in the rtl code. */
@ -223,12 +284,27 @@ stupid_life_analysis (f, nregs, file)
if (regs_live[i])
SET_HARD_REG_BIT (*p, i);
if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER)
{
chain = new_insn_chain ();
if (reload_insn_chain)
reload_insn_chain->prev = chain;
chain->next = reload_insn_chain;
chain->prev = 0;
reload_insn_chain = chain;
chain->block = 0;
chain->insn = insn;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_live[i])
SET_REGNO_REG_SET (chain->live_before, i);
}
/* Update which hard regs are currently live
and also the birth and death suids of pseudo regs
based on the pattern of this insn. */
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
stupid_mark_refs (PATTERN (insn), insn);
stupid_mark_refs (PATTERN (insn), chain);
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
@ -266,8 +342,23 @@ stupid_life_analysis (f, nregs, file)
/* It is important that this be done after processing the insn's
pattern because we want the function result register to still
be live if it's also used to pass arguments. */
stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), insn);
stupid_mark_refs (CALL_INSN_FUNCTION_USAGE (insn), chain);
}
if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER)
{
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_live[i])
SET_REGNO_REG_SET (chain->live_after, i);
/* The regs_live array doesn't say anything about hard registers
clobbered by this insn. So we need an extra pass over the
pattern. */
current_chain = chain;
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
note_stores (PATTERN (insn), find_clobbered_regs);
}
if (GET_CODE (insn) == JUMP_INSN && computed_jump_p (insn))
current_function_has_computed_jump = 1;
}
@ -289,8 +380,10 @@ stupid_life_analysis (f, nregs, file)
/* Some regnos disappear from the rtl. Ignore them to avoid crash.
Also don't allocate registers that cross a setjmp, or live across
a call if this function receives a nonlocal goto. */
a call if this function receives a nonlocal goto.
Also ignore registers we didn't see during the scan. */
if (regno_reg_rtx[r] == 0 || regs_crosses_setjmp[r]
|| (reg_where_born_exact[r] == 0 && reg_where_dead[r] == 0)
|| (REG_N_CALLS_CROSSED (r) > 0
&& current_function_has_nonlocal_label))
continue;
@ -300,7 +393,7 @@ stupid_life_analysis (f, nregs, file)
reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
reg_preferred_class (r),
PSEUDO_REGNO_MODE (r),
reg_where_born[r],
REG_WHERE_BORN (r),
reg_where_dead[r],
regs_change_size[r]);
@ -309,18 +402,48 @@ stupid_life_analysis (f, nregs, file)
reg_renumber[r] = stupid_find_reg (REG_N_CALLS_CROSSED (r),
reg_alternate_class (r),
PSEUDO_REGNO_MODE (r),
reg_where_born[r],
REG_WHERE_BORN (r),
reg_where_dead[r],
regs_change_size[r]);
}
/* Fill in the pseudo reg life information into the insn chain. */
for (i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
{
struct insn_chain *chain;
int regno;
regno = reg_renumber[i];
if (regno < 0)
continue;
chain = reg_where_dead_chain[i];
if (reg_where_dead[i] > INSN_SUID (chain->insn))
SET_REGNO_REG_SET (chain->live_after, i);
while (INSN_SUID (chain->insn) > reg_where_born_exact[i])
{
SET_REGNO_REG_SET (chain->live_before, i);
chain = chain->prev;
if (!chain)
break;
SET_REGNO_REG_SET (chain->live_after, i);
}
if (INSN_SUID (chain->insn) == reg_where_born_exact[i]
&& reg_where_born_clobber[i])
SET_REGNO_REG_SET (chain->live_before, i);
}
if (file)
dump_flow_info (file);
free (regs_live);
free (uid_suid);
free (reg_where_dead);
free (reg_where_born);
free (reg_where_born_exact);
free (reg_where_born_clobber);
free (reg_where_dead_chain);
free (reg_order);
free (regs_change_size);
free (regs_crosses_setjmp);
@ -336,8 +459,8 @@ stupid_reg_compare (r1p, r2p)
const GENERIC_PTR r2p;
{
register int r1 = *(int *)r1p, r2 = *(int *)r2p;
register int len1 = reg_where_dead[r1] - reg_where_born[r1];
register int len2 = reg_where_dead[r2] - reg_where_born[r2];
register int len1 = reg_where_dead[r1] - REG_WHERE_BORN (r1);
register int len2 = reg_where_dead[r2] - REG_WHERE_BORN (r2);
int tem;
tem = len2 - len1;
@ -470,12 +593,14 @@ stupid_find_reg (call_preserved, class, mode,
INSN is the current insn, supplied so we can find its suid. */
static void
stupid_mark_refs (x, insn)
rtx x, insn;
stupid_mark_refs (x, chain)
rtx x;
struct insn_chain *chain;
{
register RTX_CODE code;
register char *fmt;
register int regno, i;
rtx insn = chain->insn;
if (x == 0)
return;
@ -530,7 +655,11 @@ stupid_mark_refs (x, insn)
the clobbering insn. When setting, just after. */
int where_born = INSN_SUID (insn) - (code == CLOBBER);
reg_where_born[regno] = where_born;
reg_where_born_exact[regno] = INSN_SUID (insn);
reg_where_born_clobber[regno] = (code == CLOBBER);
if (reg_where_dead_chain[regno] == 0)
reg_where_dead_chain[regno] = chain;
/* The reg must live at least one insn even
in it is never again used--because it has to go
@ -573,9 +702,9 @@ stupid_mark_refs (x, insn)
If setting a SUBREG, we treat the entire reg as *used*. */
if (code == SET)
{
stupid_mark_refs (SET_SRC (x), insn);
stupid_mark_refs (SET_SRC (x), chain);
if (GET_CODE (SET_DEST (x)) != REG)
stupid_mark_refs (SET_DEST (x), insn);
stupid_mark_refs (SET_DEST (x), chain);
}
return;
}
@ -608,12 +737,14 @@ stupid_mark_refs (x, insn)
{
/* Pseudo reg: record first use, last use and number of uses. */
reg_where_born[regno] = INSN_SUID (insn);
reg_where_born_exact[regno] = INSN_SUID (insn);
reg_where_born_clobber[regno] = 0;
REG_N_REFS (regno)++;
if (regs_live[regno] == 0)
{
regs_live[regno] = 1;
reg_where_dead[regno] = INSN_SUID (insn);
reg_where_dead_chain[regno] = chain;
}
}
return;
@ -625,12 +756,12 @@ stupid_mark_refs (x, insn)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
stupid_mark_refs (XEXP (x, i), insn);
stupid_mark_refs (XEXP (x, i), chain);
if (fmt[i] == 'E')
{
register int j;
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
stupid_mark_refs (XVECEXP (x, i, j), insn);
stupid_mark_refs (XVECEXP (x, i, j), chain);
}
}
}