caller-save.c (restore_referenced_regs): Lose mode argument.

* caller-save.c (restore_referenced_regs): Lose mode argument.
	(insert_save): Lose mode argument.
	(insert_restore): Lose mode argument.
	(insert_one_insn): Lose mode argument.
	(save_call_clobbered_regs): Lose mode argument.
	(setup_save_areas): Take no argument and return void.  All callers
	changed.
	Don't verify validity of memory addresses.
	* reload.h (setup_save_ares): Adjust prototype.
	(save_call_clobbered_regs): Likewise.
	* reload1.c (delete_caller_save_insns): New function.
	(caller_save_spill_class): Delete variable.
	(caller_save_group_size): Delete variable.
	(reload): Call setup_save_areas and save_call_clobbered_regs
	in the main loop, before calling calculate_needs_all_insns.
	Don't call save_call_clobbered_regs after the loop.
	Call delete_caller_save_insns at the end of an iteration if
	something changed.
	Delete code to manage caller_save_spill_class.
	Emit the final note before setting reload_first_uid.
	Simplify test that determines whether reload_as_needed gets run.
	(calculate_needs): Delete code to manage caller_save_spill_class.

From-SVN: r22876
This commit is contained in:
Bernd Schmidt 1998-10-06 18:13:49 -06:00 committed by Jeff Law
parent a4c3ddd83a
commit 437a710df0
4 changed files with 122 additions and 195 deletions

View File

@ -1,3 +1,28 @@
Wed Oct 7 01:08:43 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
* caller-save.c (restore_referenced_regs): Lose mode argument.
(insert_save): Lose mode argument.
(insert_restore): Lose mode argument.
(insert_one_insn): Lose mode argument.
(save_call_clobbered_regs): Lose mode argument.
(setup_save_areas): Take no argument and return void. All callers
changed.
Don't verify validity of memory addresses.
* reload.h (setup_save_ares): Adjust prototype.
(save_call_clobbered_regs): Likewise.
* reload1.c (delete_caller_save_insns): New function.
(caller_save_spill_class): Delete variable.
(caller_save_group_size): Delete variable.
(reload): Call setup_save_areas and save_call_clobbered_regs
in the main loop, before calling calculate_needs_all_insns.
Don't call save_call_clobbered_regs after the loop.
Call delete_caller_save_insns at the end of an iteration if
something changed.
Delete code to manage caller_save_spill_class.
Emit the final note before setting reload_first_uid.
Simplify test that determines whether reload_as_needed gets run.
(calculate_needs): Delete code to manage caller_save_spill_class.
Tue Oct 6 15:42:27 1998 Richard Henderson <rth@cygnus.com>
* collect2.c (main): Initialize ld_file_name.

View File

@ -82,14 +82,11 @@ int n_regs_saved;
static void set_reg_live PROTO((rtx, rtx));
static void clear_reg_live PROTO((rtx));
static void restore_referenced_regs PROTO((rtx, rtx, enum machine_mode,
int));
static int insert_restore PROTO((rtx, int, int,
enum machine_mode, int, int));
static int insert_save PROTO((rtx, int, int,
enum machine_mode, int));
static void restore_referenced_regs PROTO((rtx, rtx, int));
static int insert_restore PROTO((rtx, int, int, int, int));
static int insert_save PROTO((rtx, int, int, int));
static void insert_one_insn PROTO((rtx, int, enum rtx_code,
enum machine_mode, rtx, int));
rtx, int));
/* Initialize for caller-save.
@ -234,13 +231,6 @@ init_save_areas ()
overestimate slightly (especially if some of these registers are later
used as spill registers), but it should not be significant.
Then perform register elimination in the addresses of the save area
locations; return 1 if all eliminated addresses are strictly valid.
We assume that our caller has set up the elimination table to the
worst (largest) possible offsets.
Set *PCHANGED to 1 if we had to allocate some memory for the save area.
Future work:
In the fallback case we should iterate backwards across all possible
@ -253,14 +243,11 @@ init_save_areas ()
machine independent since they might be saving non-consecutive
registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */
int
setup_save_areas (pchanged)
int *pchanged;
void
setup_save_areas ()
{
int i, j, k;
HARD_REG_SET hard_regs_used;
int ok = 1;
/* Allocate space in the save area for the largest multi-register
pseudos first, then work backwards to single register
@ -334,28 +321,16 @@ setup_save_areas (pchanged)
regno_save_mem[i+k][1]
= adj_offsettable_operand (temp, k * UNITS_PER_WORD);
}
*pchanged = 1;
}
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++)
if (regno_save_mem[i][j] != 0)
ok &= strict_memory_address_p (GET_MODE (regno_save_mem[i][j]),
XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX), 0));
return ok;
return;
}
/* Find the places where hard regs are live across calls and save them.
INSN_MODE is the mode to assign to any insns that we add. This is used
by reload to determine whether or not reloads or register eliminations
need be done on these insns. */
/* Find the places where hard regs are live across calls and save them. */
void
save_call_clobbered_regs (insn_mode)
enum machine_mode insn_mode;
save_call_clobbered_regs ()
{
rtx insn;
int b;
@ -403,7 +378,7 @@ save_call_clobbered_regs (insn_mode)
any of them. We must restore them before the insn if so. */
if (n_regs_saved)
restore_referenced_regs (PATTERN (insn), insn, insn_mode, b);
restore_referenced_regs (PATTERN (insn), insn, b);
/* NB: the normal procedure is to first enliven any
registers set by insn, then deaden any registers that
@ -453,7 +428,7 @@ save_call_clobbered_regs (insn_mode)
/* It must not be set by this instruction. */
&& ! TEST_HARD_REG_BIT (this_call_sets, regno)
&& ! TEST_HARD_REG_BIT (hard_regs_saved, regno))
regno += insert_save (insn, 1, regno, insn_mode, b);
regno += insert_save (insn, 1, regno, b);
/* Put the information for this CALL_INSN on top of what
we already had. */
@ -493,7 +468,7 @@ save_call_clobbered_regs (insn_mode)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
regno += insert_restore (insn, GET_CODE (insn) == JUMP_INSN,
regno, insn_mode,
regno,
MOVE_MAX / UNITS_PER_WORD, b);
}
}
@ -557,14 +532,13 @@ clear_reg_live (reg)
}
/* If any register currently residing in the save area is referenced in X,
which is part of INSN, emit code to restore the register in front of INSN.
INSN_MODE is the mode to assign to any insns that we add. */
which is part of INSN, emit code to restore the register in front of
INSN. */
static void
restore_referenced_regs (x, insn, insn_mode, block)
restore_referenced_regs (x, insn, block)
rtx x;
rtx insn;
enum machine_mode insn_mode;
int block;
{
enum rtx_code code = GET_CODE (x);
@ -584,11 +558,11 @@ restore_referenced_regs (x, insn, insn_mode, block)
if (regno >= FIRST_PSEUDO_REGISTER
&& reg_equiv_mem[regno] != 0)
restore_referenced_regs (XEXP (reg_equiv_mem[regno], 0),
insn, insn_mode, block);
insn, block);
else if (regno >= FIRST_PSEUDO_REGISTER
&& reg_equiv_address[regno] != 0)
restore_referenced_regs (reg_equiv_address[regno],
insn, insn_mode, block);
insn, block);
/* Otherwise if this is a hard register, restore any piece of it that
is currently saved. */
@ -603,7 +577,7 @@ restore_referenced_regs (x, insn, insn_mode, block)
for (i = regno; i < endregno; i++)
if (TEST_HARD_REG_BIT (hard_regs_need_restore, i))
i += insert_restore (insn, 1, i, insn_mode, saveregs, block);
i += insert_restore (insn, 1, i, saveregs, block);
}
return;
@ -613,18 +587,17 @@ restore_referenced_regs (x, insn, insn_mode, block)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
restore_referenced_regs (XEXP (x, i), insn, insn_mode, block);
restore_referenced_regs (XEXP (x, i), insn, block);
else if (fmt[i] == 'E')
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode, block);
restore_referenced_regs (XVECEXP (x, i, j), insn, block);
}
}
/* Insert a sequence of insns to restore REGNO. Place these insns in front
of or after INSN (determined by BEFORE_P). INSN_MODE is the mode
to assign to these insns. MAXRESTORE is the maximum number of registers
which should be restored during this call. It should never be less than
1 since we only work with entire registers.
of or after INSN (determined by BEFORE_P). MAXRESTORE is the maximum
number of registers which should be restored during this call. It should
never be less than 1 since we only work with entire registers.
Note that we have verified in init_caller_save that we can do this
with a simple SET, so use it. Set INSN_CODE to what we save there
@ -635,11 +608,10 @@ restore_referenced_regs (x, insn, insn_mode, block)
Return the extra number of registers saved. */
static int
insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
insert_restore (insn, before_p, regno, maxrestore, block)
rtx insn;
int before_p;
int regno;
enum machine_mode insn_mode;
int maxrestore;
int block;
{
@ -697,7 +669,7 @@ insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
break;
}
insert_one_insn (insn, before_p, code, insn_mode, pat, block);
insert_one_insn (insn, before_p, code, pat, block);
/* Tell our callers how many extra registers we saved/restored */
return numregs - 1;
@ -705,11 +677,10 @@ insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
/* Like insert_restore, but emit code to save REGNO. */
static int
insert_save (insn, before_p, regno, insn_mode, block)
insert_save (insn, before_p, regno, block)
rtx insn;
int before_p;
int regno;
enum machine_mode insn_mode;
int block;
{
rtx pat = NULL_RTX;
@ -767,20 +738,18 @@ insert_save (insn, before_p, regno, insn_mode, block)
break;
}
insert_one_insn (insn, before_p, code, insn_mode, pat, block);
insert_one_insn (insn, before_p, code, pat, block);
/* Tell our callers how many extra registers we saved/restored */
return numregs - 1;
}
/* Emit one insn, set the code and mode, and update basic block
boundaries. */
/* Emit one insn, set the code, and update basic block boundaries. */
static void
insert_one_insn (insn, before_p, code, mode, pat, block)
insert_one_insn (insn, before_p, code, pat, block)
rtx insn;
int before_p;
enum rtx_code code;
enum machine_mode mode;
rtx pat;
int block;
{
@ -811,7 +780,6 @@ insert_one_insn (insn, before_p, code, mode, pat, block)
if (insert_point == basic_block_end[block])
basic_block_end[block] = new;
}
PUT_MODE (new, mode);
INSN_CODE (new) = code;
}

View File

@ -327,7 +327,7 @@ extern void init_caller_save PROTO((void));
extern void init_save_areas PROTO((void));
/* Allocate save areas for any hard registers that might need saving. */
extern int setup_save_areas PROTO((int *));
extern void setup_save_areas PROTO((void));
/* Find the places where hard regs are live across calls and save them. */
extern void save_call_clobbered_regs PROTO((enum machine_mode));
extern void save_call_clobbered_regs PROTO((void));

View File

@ -371,6 +371,7 @@ static void count_possible_groups PROTO((int *, enum machine_mode *,
static int modes_equiv_for_class_p PROTO((enum machine_mode,
enum machine_mode,
enum reg_class));
static void delete_caller_save_insns PROTO((rtx));
static void spill_failure PROTO((rtx));
static int new_spill_reg PROTO((int, int, int *, int *, int,
FILE *));
@ -566,10 +567,6 @@ static int something_needs_reloads;
/* Set during calculate_needs if an insn needs register elimination. */
static int something_needs_elimination;
/* Indicate whether caller saves need a spill register. */
static enum reg_class caller_save_spill_class = NO_REGS;
static int caller_save_group_size = 1;
/* For each class, number of reload regs needed in that class.
This is the maximum over all insns of the needs in that class
of the individual insn. */
@ -644,12 +641,13 @@ reload (first, global, dumpfile)
reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
/* Make sure that the last insn in the chain
is not something that needs reloading. */
emit_note (NULL_PTR, NOTE_INSN_DELETED);
/* Enable find_equiv_reg to distinguish insns made by reload. */
reload_first_uid = get_max_uid ();
caller_save_spill_class = NO_REGS;
caller_save_group_size = 1;
for (i = 0; i < N_REG_CLASSES; i++)
basic_block_needs[i] = 0;
@ -687,10 +685,6 @@ reload (first, global, dumpfile)
regs_ever_live[i] = 1;
}
/* Make sure that the last insn in the chain
is not something that needs reloading. */
emit_note (NULL_PTR, NOTE_INSN_DELETED);
/* Find all the pseudo registers that didn't get hard regs
but do have known equivalent constants or memory slots.
These include parameters (known equivalent to parameter slots)
@ -986,18 +980,26 @@ reload (first, global, dumpfile)
}
}
/* Insert code to save and restore call-clobbered hard regs
around calls. Tell if what mode to use so that we will process
those insns in reload_as_needed if we have to. */
if (caller_save_needed)
setup_save_areas ();
if (starting_frame_size != get_frame_size ())
something_changed = 1;
/* If we allocated another pseudo to the stack, redo elimination
bookkeeping. */
if (something_changed)
continue;
/* If caller-saves needs a group, initialize the group to include
the size and mode required for caller-saves. */
if (caller_save_group_size > 1)
if (caller_save_needed)
{
group_mode[(int) caller_save_spill_class] = Pmode;
group_size[(int) caller_save_spill_class] = caller_save_group_size;
save_call_clobbered_regs ();
/* That might have allocated new insn_chain structures. */
reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
}
something_changed |= calculate_needs_all_insns (first, global);
@ -1010,32 +1012,6 @@ reload (first, global, dumpfile)
if (dumpfile)
dump_needs (dumpfile);
/* If we have caller-saves, set up the save areas and see if caller-save
will need a spill register. */
if (caller_save_needed)
{
/* Set the offsets for setup_save_areas. */
for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
ep++)
ep->previous_offset = ep->max_offset;
if ( ! setup_save_areas (&something_changed)
&& caller_save_spill_class == NO_REGS)
{
/* The class we will need depends on whether the machine
supports the sum of two registers for an address; see
find_address_reloads for details. */
caller_save_spill_class
= (double_reg_address_ok ? reload_address_index_reg_class
: reload_address_base_reg_class);
caller_save_group_size
= CLASS_MAX_NREGS (caller_save_spill_class, Pmode);
something_changed = 1;
}
}
{
HARD_REG_SET to_spill;
CLEAR_HARD_REG_SET (to_spill);
@ -1098,6 +1074,9 @@ reload (first, global, dumpfile)
something_changed |= find_reload_regs (global, dumpfile);
if (failure)
goto failed;
if (something_changed)
delete_caller_save_insns (first);
}
/* If global-alloc was run, notify it of any register eliminations we have
@ -1107,15 +1086,6 @@ reload (first, global, dumpfile)
if (ep->can_eliminate)
mark_elimination (ep->from, ep->to);
/* Insert code to save and restore call-clobbered hard regs
around calls. Tell if what mode to use so that we will process
those insns in reload_as_needed if we have to. */
if (caller_save_needed)
save_call_clobbered_regs (num_eliminable ? QImode
: caller_save_spill_class != NO_REGS ? HImode
: VOIDmode);
/* If a pseudo has no hard reg, delete the insns that made the equivalence.
If that insn didn't set the register (i.e., it copied the register to
memory), just delete that insn instead of the equivalencing insn plus
@ -1141,9 +1111,7 @@ reload (first, global, dumpfile)
by generating move instructions to move the must-be-register
values into or out of the reload registers. */
if (something_needs_reloads || something_needs_elimination
|| (caller_save_needed && num_eliminable)
|| caller_save_spill_class != NO_REGS)
if (something_needs_reloads || something_needs_elimination)
reload_as_needed (first, global);
/* If we were able to eliminate the frame pointer, show that it is no
@ -1384,13 +1352,7 @@ calculate_needs_all_insns (first, global)
something_needs_elimination = 1;
}
/* If this insn has no reloads, we need not do anything except
in the case of a CALL_INSN when we have caller-saves and
caller-save needs reloads. */
if (n_reloads != 0
|| (GET_CODE (insn) == CALL_INSN
&& caller_save_spill_class != NO_REGS))
if (n_reloads != 0)
something_changed |= calculate_needs (this_block, insn,
avoid_return_reg, global);
}
@ -1650,75 +1612,6 @@ calculate_needs (this_block, insn, avoid_return_reg, global)
insn_needs.other_addr.groups[i]);
}
/* If this is a CALL_INSN and caller-saves will need
a spill register, act as if the spill register is
needed for this insn. However, the spill register
can be used by any reload of this insn, so we only
need do something if no need for that class has
been recorded.
The assumption that every CALL_INSN will trigger a
caller-save is highly conservative, however, the number
of cases where caller-saves will need a spill register but
a block containing a CALL_INSN won't need a spill register
of that class should be quite rare.
If a group is needed, the size and mode of the group will
have been set up at the beginning of this loop. */
if (GET_CODE (insn) == CALL_INSN
&& caller_save_spill_class != NO_REGS)
{
int j;
/* See if this register would conflict with any reload that
needs a group or any reload that needs a nongroup. */
int nongroup_need = 0;
int *caller_save_needs;
for (j = 0; j < n_reloads; j++)
if (reg_classes_intersect_p (caller_save_spill_class,
reload_reg_class[j])
&& ((CLASS_MAX_NREGS
(reload_reg_class[j],
(GET_MODE_SIZE (reload_outmode[j])
> GET_MODE_SIZE (reload_inmode[j]))
? reload_outmode[j] : reload_inmode[j])
> 1)
|| reload_nongroup[j]))
{
nongroup_need = 1;
break;
}
caller_save_needs
= (caller_save_group_size > 1
? insn_needs.other.groups
: insn_needs.other.regs[nongroup_need]);
if (caller_save_needs[(int) caller_save_spill_class] == 0)
{
register enum reg_class *p
= reg_class_superclasses[(int) caller_save_spill_class];
caller_save_needs[(int) caller_save_spill_class]++;
while (*p != LIM_REG_CLASSES)
caller_save_needs[(int) *p++] += 1;
}
/* Show that this basic block will need a register of
this class. */
if (global
&& ! (basic_block_needs[(int) caller_save_spill_class]
[this_block]))
{
basic_block_needs[(int) caller_save_spill_class]
[this_block] = 1;
something_changed = 1;
}
}
/* If this insn stores the value of a function call,
and that value is in a register that has been spilled,
and if the insn needs a reload in a class
@ -2166,6 +2059,47 @@ dump_needs (dumpfile)
}
}
/* Delete all insns that were inserted by emit_caller_save_insns during
this iteration. */
static void
delete_caller_save_insns (first)
rtx first;
{
rtx insn = first;
int b = -1;
while (insn != 0)
{
if (b + 1 != n_basic_blocks
&& basic_block_head[b + 1] == insn)
b++;
while (insn != 0 && INSN_UID (insn) >= reload_first_uid)
{
rtx next = NEXT_INSN (insn);
rtx prev = PREV_INSN (insn);
if (insn == basic_block_head[b])
basic_block_head[b] = next;
if (insn == basic_block_end[b])
basic_block_end[b] = prev;
if (next != 0)
PREV_INSN (next) = prev;
if (prev != 0)
NEXT_INSN (prev) = next;
insn = next;
if (b + 1 != n_basic_blocks
&& basic_block_head[b + 1] == insn)
b++;
}
if (insn != 0)
insn = NEXT_INSN (insn);
}
}
/* Nonzero if, after spilling reg REGNO for non-groups,
it will still be possible to find a group if we still need one. */