summaryrefslogtreecommitdiff
path: root/gcc/caller-save.c
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2001-02-28 17:24:00 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>2001-02-28 16:24:00 +0000
commit787dc84216bdf0def91f8e2fa3bbb15415959af3 (patch)
tree31cd8790a0faef2e8fb8e0fb385ee169d62d5f59 /gcc/caller-save.c
parentdc2698bc26065d3300ca0353f92c00f4f0a1496b (diff)
downloadgcc-787dc84216bdf0def91f8e2fa3bbb15415959af3.tar.gz
caller-save.c (reg_save_code, [...]): Index by mode, not NREGS.
* caller-save.c (reg_save_code, reg_restore_code): Index by mode, not NREGS. (insert_save, insert_restore): New parameter save_mode. (init_caller_save): Update initialization of reg_save_code and reg_restore_code. (save_call_clobbered_regs): Compute save_modes and update calls to reg_save_code and reg_restore_code. (insert_restore): Unsignetize numbers; use save_modes to choose mode of spill; update use of reg_restore_code. (insert_save): Likewise. * i386.h (HARD_REGNO_CALLER_SAVE_MODE): Update. * c4x.h (HARD_REGNO_CALLER_SAVE_MODE): Update. * regs.h (HARD_REGNO_CALLER_SAVE_MODE): Likewise. From-SVN: r40120
Diffstat (limited to 'gcc/caller-save.c')
-rw-r--r--gcc/caller-save.c133
1 files changed, 96 insertions, 37 deletions
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index c8302ae6a7e..445de2cf532 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -65,9 +65,9 @@ static rtx
be recognized. */
static enum insn_code
- reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
+ reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
static enum insn_code
- reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
+ reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
/* Set of hard regs currently residing in save area (during insn scan). */
@@ -89,9 +89,10 @@ static HARD_REG_SET this_insn_sets;
static void mark_set_regs PARAMS ((rtx, rtx, void *));
static void mark_referenced_regs PARAMS ((rtx));
static int insert_save PARAMS ((struct insn_chain *, int, int,
- HARD_REG_SET *));
+ HARD_REG_SET *,
+ enum machine_mode *));
static int insert_restore PARAMS ((struct insn_chain *, int, int,
- int));
+ int, enum machine_mode *));
static struct insn_chain *insert_one_insn PARAMS ((struct insn_chain *, int,
enum insn_code, rtx));
static void add_stored_regs PARAMS ((rtx, rtx, void *));
@@ -113,6 +114,7 @@ init_caller_save ()
int offset;
rtx address;
int i, j;
+ enum machine_mode mode;
/* First find all the registers that we need to deal with and all
the modes that they can have. If we can't find a mode to use,
@@ -124,7 +126,8 @@ init_caller_save ()
{
for (j = 1; j <= MOVE_MAX_WORDS; j++)
{
- regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j);
+ regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j,
+ VOIDmode);
if (regno_save_mode[i][j] == VOIDmode && j == 1)
{
call_fixed_regs[i] = 1;
@@ -179,24 +182,24 @@ init_caller_save ()
start_sequence ();
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- for (j = 1; j <= MOVE_MAX_WORDS; j++)
- if (regno_save_mode[i][j] != VOIDmode)
+ for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
+ if (HARD_REGNO_MODE_OK (i, mode))
{
- rtx mem = gen_rtx_MEM (regno_save_mode[i][j], address);
- rtx reg = gen_rtx_REG (regno_save_mode[i][j], i);
+ rtx mem = gen_rtx_MEM (mode, address);
+ rtx reg = gen_rtx_REG (mode, i);
rtx savepat = gen_rtx_SET (VOIDmode, mem, reg);
rtx restpat = gen_rtx_SET (VOIDmode, reg, mem);
rtx saveinsn = emit_insn (savepat);
rtx restinsn = emit_insn (restpat);
int ok;
- reg_save_code[i][j] = recog_memoized (saveinsn);
- reg_restore_code[i][j] = recog_memoized (restinsn);
+ reg_save_code[i][mode] = recog_memoized (saveinsn);
+ reg_restore_code[i][mode] = recog_memoized (restinsn);
/* Now extract both insns and see if we can meet their
constraints. */
- ok = (reg_save_code[i][j] != (enum insn_code)-1
- && reg_restore_code[i][j] != (enum insn_code)-1);
+ ok = (reg_save_code[i][mode] != (enum insn_code)-1
+ && reg_restore_code[i][mode] != (enum insn_code)-1);
if (ok)
{
extract_insn (saveinsn);
@@ -207,14 +210,26 @@ init_caller_save ()
if (! ok)
{
- regno_save_mode[i][j] = VOIDmode;
- if (j == 1)
- {
- call_fixed_regs[i] = 1;
- SET_HARD_REG_BIT (call_fixed_reg_set, i);
- }
+ reg_save_code[i][mode] = (enum insn_code) -1;
+ reg_restore_code[i][mode] = (enum insn_code) -1;
}
- }
+ }
+ else
+ {
+ reg_save_code[i][mode] = (enum insn_code) -1;
+ reg_restore_code[i][mode] = (enum insn_code) -1;
+ }
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ for (j = 1; j <= MOVE_MAX_WORDS; j++)
+ if (reg_save_code [i][regno_save_mode[i][j]] == (enum insn_code) -1)
+ {
+ regno_save_mode[i][j] = VOIDmode;
+ if (j == 1)
+ {
+ call_fixed_regs[i] = 1;
+ SET_HARD_REG_BIT (call_fixed_reg_set, i);
+ }
+ }
end_sequence ();
}
@@ -339,6 +354,7 @@ void
save_call_clobbered_regs ()
{
struct insn_chain *chain, *next;
+ enum machine_mode save_mode [FIRST_PSEUDO_REGISTER];
CLEAR_HARD_REG_SET (hard_regs_saved);
n_regs_saved = 0;
@@ -374,7 +390,7 @@ save_call_clobbered_regs ()
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (referenced_regs, regno))
- regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS);
+ regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS, save_mode);
}
if (code == CALL_INSN)
@@ -386,8 +402,37 @@ save_call_clobbered_regs ()
regs are live during the call. */
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
- compute_use_by_pseudos (&hard_regs_to_save,
- &chain->live_throughout);
+ /* Save hard registers always in the widest mode availble. */
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
+ save_mode [regno] = regno_save_mode [regno][1];
+ else
+ save_mode [regno] = VOIDmode;
+
+ /* Look trought all live pseudos, mark their hard registers
+ and choose proper mode for saving. */
+ EXECUTE_IF_SET_IN_REG_SET
+ (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno,
+ {
+ int r = reg_renumber[regno];
+ int nregs;
+
+ if (r > 0)
+ {
+ enum machine_mode mode;
+
+ nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (regno));
+ mode = HARD_REGNO_CALLER_SAVE_MODE
+ (r, nregs, PSEUDO_REGNO_MODE (regno));
+ if (GET_MODE_BITSIZE (mode)
+ > GET_MODE_BITSIZE (save_mode[r]))
+ save_mode[r] = mode;
+ while (nregs-- > 0)
+ SET_HARD_REG_BIT (hard_regs_to_save, r + nregs);
+ }
+ else
+ abort ();
+ });
/* Record all registers set in this call insn. These don't need
to be saved. N.B. the call insn might set a subreg of a
@@ -404,7 +449,7 @@ save_call_clobbered_regs ()
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
- regno += insert_save (chain, 1, regno, &hard_regs_to_save);
+ regno += insert_save (chain, 1, regno, &hard_regs_to_save, save_mode);
/* Must recompute n_regs_saved. */
n_regs_saved = 0;
@@ -425,7 +470,7 @@ save_call_clobbered_regs ()
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
regno += insert_restore (chain, GET_CODE (insn) == JUMP_INSN,
- regno, MOVE_MAX_WORDS);
+ regno, MOVE_MAX_WORDS, save_mode);
}
}
}
@@ -572,17 +617,19 @@ mark_referenced_regs (x)
Return the extra number of registers saved. */
static int
-insert_restore (chain, before_p, regno, maxrestore)
+insert_restore (chain, before_p, regno, maxrestore, save_mode)
struct insn_chain *chain;
int before_p;
int regno;
int maxrestore;
+ enum machine_mode *save_mode;
{
int i, k;
rtx pat = NULL_RTX;
enum insn_code code = CODE_FOR_nothing;
- int numregs = 0;
+ unsigned int numregs = 0;
struct insn_chain *new;
+ rtx mem;
/* A common failure mode if register status is not correct in the RTL
is for this routine to be called with a REGNO we didn't expect to
@@ -620,11 +667,15 @@ insert_restore (chain, before_p, regno, maxrestore)
break;
}
+ mem = regno_save_mem [regno][numregs];
+ if (save_mode [regno] != VOIDmode
+ && save_mode [regno] != GET_MODE (mem)
+ && numregs == HARD_REGNO_NREGS (regno, save_mode [regno]))
+ mem = change_address (mem, save_mode[regno], XEXP (mem, 0));
pat = gen_rtx_SET (VOIDmode,
- gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]),
- regno),
- regno_save_mem[regno][numregs]);
- code = reg_restore_code[regno][numregs];
+ gen_rtx_REG (GET_MODE (mem),
+ regno), mem);
+ code = reg_restore_code[regno][GET_MODE (mem)];
new = insert_one_insn (chain, before_p, code, pat);
/* Clear status for all registers we restored. */
@@ -643,17 +694,20 @@ insert_restore (chain, before_p, regno, maxrestore)
/* Like insert_restore above, but save registers instead. */
static int
-insert_save (chain, before_p, regno, to_save)
+insert_save (chain, before_p, regno, to_save, save_mode)
struct insn_chain *chain;
int before_p;
int regno;
HARD_REG_SET *to_save;
+ enum machine_mode *save_mode;
{
- int i, k;
+ int i;
+ unsigned int k;
rtx pat = NULL_RTX;
enum insn_code code = CODE_FOR_nothing;
- int numregs = 0;
+ unsigned int numregs = 0;
struct insn_chain *new;
+ rtx mem;
/* A common failure mode if register status is not correct in the RTL
is for this routine to be called with a REGNO we didn't expect to
@@ -690,10 +744,15 @@ insert_save (chain, before_p, regno, to_save)
break;
}
- pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][numregs],
- gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]),
+ mem = regno_save_mem [regno][numregs];
+ if (save_mode [regno] != VOIDmode
+ && save_mode [regno] != GET_MODE (mem)
+ && numregs == HARD_REGNO_NREGS (regno, save_mode [regno]))
+ mem = change_address (mem, save_mode[regno], XEXP (mem, 0));
+ pat = gen_rtx_SET (VOIDmode, mem,
+ gen_rtx_REG (GET_MODE (mem),
regno));
- code = reg_save_code[regno][numregs];
+ code = reg_save_code[regno][GET_MODE (mem)];
new = insert_one_insn (chain, before_p, code, pat);
/* Set hard_regs_saved and dead_or_set for all the registers we saved. */