mirror of git://gcc.gnu.org/git/gcc.git
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:
parent
a4c3ddd83a
commit
437a710df0
|
|
@ -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>
|
Tue Oct 6 15:42:27 1998 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
* collect2.c (main): Initialize ld_file_name.
|
* collect2.c (main): Initialize ld_file_name.
|
||||||
|
|
|
||||||
|
|
@ -82,14 +82,11 @@ int n_regs_saved;
|
||||||
|
|
||||||
static void set_reg_live PROTO((rtx, rtx));
|
static void set_reg_live PROTO((rtx, rtx));
|
||||||
static void clear_reg_live PROTO((rtx));
|
static void clear_reg_live PROTO((rtx));
|
||||||
static void restore_referenced_regs PROTO((rtx, rtx, enum machine_mode,
|
static void restore_referenced_regs PROTO((rtx, rtx, int));
|
||||||
int));
|
static int insert_restore PROTO((rtx, int, int, int, int));
|
||||||
static int insert_restore PROTO((rtx, int, int,
|
static int insert_save PROTO((rtx, int, int, int));
|
||||||
enum machine_mode, int, int));
|
|
||||||
static int insert_save PROTO((rtx, int, int,
|
|
||||||
enum machine_mode, int));
|
|
||||||
static void insert_one_insn PROTO((rtx, int, enum rtx_code,
|
static void insert_one_insn PROTO((rtx, int, enum rtx_code,
|
||||||
enum machine_mode, rtx, int));
|
rtx, int));
|
||||||
|
|
||||||
/* Initialize for caller-save.
|
/* Initialize for caller-save.
|
||||||
|
|
||||||
|
|
@ -234,13 +231,6 @@ init_save_areas ()
|
||||||
overestimate slightly (especially if some of these registers are later
|
overestimate slightly (especially if some of these registers are later
|
||||||
used as spill registers), but it should not be significant.
|
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:
|
Future work:
|
||||||
|
|
||||||
In the fallback case we should iterate backwards across all possible
|
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
|
machine independent since they might be saving non-consecutive
|
||||||
registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */
|
registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */
|
||||||
|
|
||||||
int
|
void
|
||||||
setup_save_areas (pchanged)
|
setup_save_areas ()
|
||||||
int *pchanged;
|
|
||||||
{
|
{
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
HARD_REG_SET hard_regs_used;
|
HARD_REG_SET hard_regs_used;
|
||||||
int ok = 1;
|
|
||||||
|
|
||||||
|
|
||||||
/* Allocate space in the save area for the largest multi-register
|
/* Allocate space in the save area for the largest multi-register
|
||||||
pseudos first, then work backwards to single register
|
pseudos first, then work backwards to single register
|
||||||
|
|
@ -334,28 +321,16 @@ setup_save_areas (pchanged)
|
||||||
regno_save_mem[i+k][1]
|
regno_save_mem[i+k][1]
|
||||||
= adj_offsettable_operand (temp, k * UNITS_PER_WORD);
|
= adj_offsettable_operand (temp, k * UNITS_PER_WORD);
|
||||||
}
|
}
|
||||||
*pchanged = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
return;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the places where hard regs are live across calls and save them.
|
/* 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. */
|
|
||||||
|
|
||||||
void
|
void
|
||||||
save_call_clobbered_regs (insn_mode)
|
save_call_clobbered_regs ()
|
||||||
enum machine_mode insn_mode;
|
|
||||||
{
|
{
|
||||||
rtx insn;
|
rtx insn;
|
||||||
int b;
|
int b;
|
||||||
|
|
@ -403,7 +378,7 @@ save_call_clobbered_regs (insn_mode)
|
||||||
any of them. We must restore them before the insn if so. */
|
any of them. We must restore them before the insn if so. */
|
||||||
|
|
||||||
if (n_regs_saved)
|
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
|
/* NB: the normal procedure is to first enliven any
|
||||||
registers set by insn, then deaden any registers that
|
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. */
|
/* It must not be set by this instruction. */
|
||||||
&& ! TEST_HARD_REG_BIT (this_call_sets, regno)
|
&& ! TEST_HARD_REG_BIT (this_call_sets, regno)
|
||||||
&& ! TEST_HARD_REG_BIT (hard_regs_saved, 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
|
/* Put the information for this CALL_INSN on top of what
|
||||||
we already had. */
|
we already had. */
|
||||||
|
|
@ -493,7 +468,7 @@ save_call_clobbered_regs (insn_mode)
|
||||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||||
if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
|
if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
|
||||||
regno += insert_restore (insn, GET_CODE (insn) == JUMP_INSN,
|
regno += insert_restore (insn, GET_CODE (insn) == JUMP_INSN,
|
||||||
regno, insn_mode,
|
regno,
|
||||||
MOVE_MAX / UNITS_PER_WORD, b);
|
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,
|
/* 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.
|
which is part of INSN, emit code to restore the register in front of
|
||||||
INSN_MODE is the mode to assign to any insns that we add. */
|
INSN. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
restore_referenced_regs (x, insn, insn_mode, block)
|
restore_referenced_regs (x, insn, block)
|
||||||
rtx x;
|
rtx x;
|
||||||
rtx insn;
|
rtx insn;
|
||||||
enum machine_mode insn_mode;
|
|
||||||
int block;
|
int block;
|
||||||
{
|
{
|
||||||
enum rtx_code code = GET_CODE (x);
|
enum rtx_code code = GET_CODE (x);
|
||||||
|
|
@ -584,11 +558,11 @@ restore_referenced_regs (x, insn, insn_mode, block)
|
||||||
if (regno >= FIRST_PSEUDO_REGISTER
|
if (regno >= FIRST_PSEUDO_REGISTER
|
||||||
&& reg_equiv_mem[regno] != 0)
|
&& reg_equiv_mem[regno] != 0)
|
||||||
restore_referenced_regs (XEXP (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
|
else if (regno >= FIRST_PSEUDO_REGISTER
|
||||||
&& reg_equiv_address[regno] != 0)
|
&& reg_equiv_address[regno] != 0)
|
||||||
restore_referenced_regs (reg_equiv_address[regno],
|
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
|
/* Otherwise if this is a hard register, restore any piece of it that
|
||||||
is currently saved. */
|
is currently saved. */
|
||||||
|
|
@ -603,7 +577,7 @@ restore_referenced_regs (x, insn, insn_mode, block)
|
||||||
|
|
||||||
for (i = regno; i < endregno; i++)
|
for (i = regno; i < endregno; i++)
|
||||||
if (TEST_HARD_REG_BIT (hard_regs_need_restore, 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;
|
return;
|
||||||
|
|
@ -613,18 +587,17 @@ restore_referenced_regs (x, insn, insn_mode, block)
|
||||||
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
if (fmt[i] == 'e')
|
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')
|
else if (fmt[i] == 'E')
|
||||||
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
|
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
|
/* 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
|
of or after INSN (determined by BEFORE_P). MAXRESTORE is the maximum
|
||||||
to assign to these insns. MAXRESTORE is the maximum number of registers
|
number of registers which should be restored during this call. It should
|
||||||
which should be restored during this call. It should never be less than
|
never be less than 1 since we only work with entire registers.
|
||||||
1 since we only work with entire registers.
|
|
||||||
|
|
||||||
Note that we have verified in init_caller_save that we can do this
|
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
|
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. */
|
Return the extra number of registers saved. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
|
insert_restore (insn, before_p, regno, maxrestore, block)
|
||||||
rtx insn;
|
rtx insn;
|
||||||
int before_p;
|
int before_p;
|
||||||
int regno;
|
int regno;
|
||||||
enum machine_mode insn_mode;
|
|
||||||
int maxrestore;
|
int maxrestore;
|
||||||
int block;
|
int block;
|
||||||
{
|
{
|
||||||
|
|
@ -697,7 +669,7 @@ insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
|
||||||
break;
|
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 */
|
/* Tell our callers how many extra registers we saved/restored */
|
||||||
return numregs - 1;
|
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. */
|
/* Like insert_restore, but emit code to save REGNO. */
|
||||||
static int
|
static int
|
||||||
insert_save (insn, before_p, regno, insn_mode, block)
|
insert_save (insn, before_p, regno, block)
|
||||||
rtx insn;
|
rtx insn;
|
||||||
int before_p;
|
int before_p;
|
||||||
int regno;
|
int regno;
|
||||||
enum machine_mode insn_mode;
|
|
||||||
int block;
|
int block;
|
||||||
{
|
{
|
||||||
rtx pat = NULL_RTX;
|
rtx pat = NULL_RTX;
|
||||||
|
|
@ -767,20 +738,18 @@ insert_save (insn, before_p, regno, insn_mode, block)
|
||||||
break;
|
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 */
|
/* Tell our callers how many extra registers we saved/restored */
|
||||||
return numregs - 1;
|
return numregs - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit one insn, set the code and mode, and update basic block
|
/* Emit one insn, set the code, and update basic block boundaries. */
|
||||||
boundaries. */
|
|
||||||
static void
|
static void
|
||||||
insert_one_insn (insn, before_p, code, mode, pat, block)
|
insert_one_insn (insn, before_p, code, pat, block)
|
||||||
rtx insn;
|
rtx insn;
|
||||||
int before_p;
|
int before_p;
|
||||||
enum rtx_code code;
|
enum rtx_code code;
|
||||||
enum machine_mode mode;
|
|
||||||
rtx pat;
|
rtx pat;
|
||||||
int block;
|
int block;
|
||||||
{
|
{
|
||||||
|
|
@ -811,7 +780,6 @@ insert_one_insn (insn, before_p, code, mode, pat, block)
|
||||||
if (insert_point == basic_block_end[block])
|
if (insert_point == basic_block_end[block])
|
||||||
basic_block_end[block] = new;
|
basic_block_end[block] = new;
|
||||||
}
|
}
|
||||||
|
|
||||||
PUT_MODE (new, mode);
|
|
||||||
INSN_CODE (new) = code;
|
INSN_CODE (new) = code;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -327,7 +327,7 @@ extern void init_caller_save PROTO((void));
|
||||||
extern void init_save_areas PROTO((void));
|
extern void init_save_areas PROTO((void));
|
||||||
|
|
||||||
/* Allocate save areas for any hard registers that might need saving. */
|
/* 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. */
|
/* 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));
|
||||||
|
|
|
||||||
196
gcc/reload1.c
196
gcc/reload1.c
|
|
@ -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,
|
static int modes_equiv_for_class_p PROTO((enum machine_mode,
|
||||||
enum machine_mode,
|
enum machine_mode,
|
||||||
enum reg_class));
|
enum reg_class));
|
||||||
|
static void delete_caller_save_insns PROTO((rtx));
|
||||||
static void spill_failure PROTO((rtx));
|
static void spill_failure PROTO((rtx));
|
||||||
static int new_spill_reg PROTO((int, int, int *, int *, int,
|
static int new_spill_reg PROTO((int, int, int *, int *, int,
|
||||||
FILE *));
|
FILE *));
|
||||||
|
|
@ -566,10 +567,6 @@ static int something_needs_reloads;
|
||||||
/* Set during calculate_needs if an insn needs register elimination. */
|
/* Set during calculate_needs if an insn needs register elimination. */
|
||||||
static int something_needs_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.
|
/* For each class, number of reload regs needed in that class.
|
||||||
This is the maximum over all insns of the needs in that class
|
This is the maximum over all insns of the needs in that class
|
||||||
of the individual insn. */
|
of the individual insn. */
|
||||||
|
|
@ -644,12 +641,13 @@ reload (first, global, dumpfile)
|
||||||
|
|
||||||
reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
|
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. */
|
/* Enable find_equiv_reg to distinguish insns made by reload. */
|
||||||
reload_first_uid = get_max_uid ();
|
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++)
|
for (i = 0; i < N_REG_CLASSES; i++)
|
||||||
basic_block_needs[i] = 0;
|
basic_block_needs[i] = 0;
|
||||||
|
|
||||||
|
|
@ -687,10 +685,6 @@ reload (first, global, dumpfile)
|
||||||
regs_ever_live[i] = 1;
|
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
|
/* Find all the pseudo registers that didn't get hard regs
|
||||||
but do have known equivalent constants or memory slots.
|
but do have known equivalent constants or memory slots.
|
||||||
These include parameters (known equivalent to parameter 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
|
/* If we allocated another pseudo to the stack, redo elimination
|
||||||
bookkeeping. */
|
bookkeeping. */
|
||||||
if (something_changed)
|
if (something_changed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* If caller-saves needs a group, initialize the group to include
|
if (caller_save_needed)
|
||||||
the size and mode required for caller-saves. */
|
|
||||||
|
|
||||||
if (caller_save_group_size > 1)
|
|
||||||
{
|
{
|
||||||
group_mode[(int) caller_save_spill_class] = Pmode;
|
save_call_clobbered_regs ();
|
||||||
group_size[(int) caller_save_spill_class] = caller_save_group_size;
|
/* That might have allocated new insn_chain structures. */
|
||||||
|
reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
something_changed |= calculate_needs_all_insns (first, global);
|
something_changed |= calculate_needs_all_insns (first, global);
|
||||||
|
|
@ -1010,32 +1012,6 @@ reload (first, global, dumpfile)
|
||||||
if (dumpfile)
|
if (dumpfile)
|
||||||
dump_needs (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 < ®_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;
|
HARD_REG_SET to_spill;
|
||||||
CLEAR_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);
|
something_changed |= find_reload_regs (global, dumpfile);
|
||||||
if (failure)
|
if (failure)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
|
if (something_changed)
|
||||||
|
delete_caller_save_insns (first);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If global-alloc was run, notify it of any register eliminations we have
|
/* 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)
|
if (ep->can_eliminate)
|
||||||
mark_elimination (ep->from, ep->to);
|
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 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
|
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
|
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
|
by generating move instructions to move the must-be-register
|
||||||
values into or out of the reload registers. */
|
values into or out of the reload registers. */
|
||||||
|
|
||||||
if (something_needs_reloads || something_needs_elimination
|
if (something_needs_reloads || something_needs_elimination)
|
||||||
|| (caller_save_needed && num_eliminable)
|
|
||||||
|| caller_save_spill_class != NO_REGS)
|
|
||||||
reload_as_needed (first, global);
|
reload_as_needed (first, global);
|
||||||
|
|
||||||
/* If we were able to eliminate the frame pointer, show that it is no
|
/* 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;
|
something_needs_elimination = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If this insn has no reloads, we need not do anything except
|
if (n_reloads != 0)
|
||||||
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))
|
|
||||||
something_changed |= calculate_needs (this_block, insn,
|
something_changed |= calculate_needs (this_block, insn,
|
||||||
avoid_return_reg, global);
|
avoid_return_reg, global);
|
||||||
}
|
}
|
||||||
|
|
@ -1650,75 +1612,6 @@ calculate_needs (this_block, insn, avoid_return_reg, global)
|
||||||
insn_needs.other_addr.groups[i]);
|
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,
|
/* If this insn stores the value of a function call,
|
||||||
and that value is in a register that has been spilled,
|
and that value is in a register that has been spilled,
|
||||||
and if the insn needs a reload in a class
|
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,
|
/* Nonzero if, after spilling reg REGNO for non-groups,
|
||||||
it will still be possible to find a group if we still need one. */
|
it will still be possible to find a group if we still need one. */
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue