Commit 787dc842 by Jan Hubicka Committed by Jan Hubicka

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
parent dc2698bc
Wed Feb 28 17:19:28 CET 2001 Jan Hubicka <jh@suse.cz. Wed Feb 28 17:22:35 CET 2001 Jan Hubicka <jh@suse.cz>
* 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.
Wed Feb 28 17:19:28 CET 2001 Jan Hubicka <jh@suse.cz>
* ifcvt.c (noce_emit_store_flag, noce_try_store_flag_constants, * ifcvt.c (noce_emit_store_flag, noce_try_store_flag_constants,
noce_try_store_flag_inc, noce_try_store_flag_mask, noce_try_store_flag_inc, noce_try_store_flag_mask,
......
...@@ -65,9 +65,9 @@ static rtx ...@@ -65,9 +65,9 @@ static rtx
be recognized. */ be recognized. */
static enum insn_code 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 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). */ /* Set of hard regs currently residing in save area (during insn scan). */
...@@ -89,9 +89,10 @@ static HARD_REG_SET this_insn_sets; ...@@ -89,9 +89,10 @@ static HARD_REG_SET this_insn_sets;
static void mark_set_regs PARAMS ((rtx, rtx, void *)); static void mark_set_regs PARAMS ((rtx, rtx, void *));
static void mark_referenced_regs PARAMS ((rtx)); static void mark_referenced_regs PARAMS ((rtx));
static int insert_save PARAMS ((struct insn_chain *, int, int, 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, 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, static struct insn_chain *insert_one_insn PARAMS ((struct insn_chain *, int,
enum insn_code, rtx)); enum insn_code, rtx));
static void add_stored_regs PARAMS ((rtx, rtx, void *)); static void add_stored_regs PARAMS ((rtx, rtx, void *));
...@@ -113,6 +114,7 @@ init_caller_save () ...@@ -113,6 +114,7 @@ init_caller_save ()
int offset; int offset;
rtx address; rtx address;
int i, j; int i, j;
enum machine_mode mode;
/* First find all the registers that we need to deal with and all /* 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, the modes that they can have. If we can't find a mode to use,
...@@ -124,7 +126,8 @@ init_caller_save () ...@@ -124,7 +126,8 @@ init_caller_save ()
{ {
for (j = 1; j <= MOVE_MAX_WORDS; j++) 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) if (regno_save_mode[i][j] == VOIDmode && j == 1)
{ {
call_fixed_regs[i] = 1; call_fixed_regs[i] = 1;
...@@ -179,24 +182,24 @@ init_caller_save () ...@@ -179,24 +182,24 @@ init_caller_save ()
start_sequence (); start_sequence ();
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 1; j <= MOVE_MAX_WORDS; j++) for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
if (regno_save_mode[i][j] != VOIDmode) if (HARD_REGNO_MODE_OK (i, mode))
{ {
rtx mem = gen_rtx_MEM (regno_save_mode[i][j], address); rtx mem = gen_rtx_MEM (mode, address);
rtx reg = gen_rtx_REG (regno_save_mode[i][j], i); rtx reg = gen_rtx_REG (mode, i);
rtx savepat = gen_rtx_SET (VOIDmode, mem, reg); rtx savepat = gen_rtx_SET (VOIDmode, mem, reg);
rtx restpat = gen_rtx_SET (VOIDmode, reg, mem); rtx restpat = gen_rtx_SET (VOIDmode, reg, mem);
rtx saveinsn = emit_insn (savepat); rtx saveinsn = emit_insn (savepat);
rtx restinsn = emit_insn (restpat); rtx restinsn = emit_insn (restpat);
int ok; int ok;
reg_save_code[i][j] = recog_memoized (saveinsn); reg_save_code[i][mode] = recog_memoized (saveinsn);
reg_restore_code[i][j] = recog_memoized (restinsn); reg_restore_code[i][mode] = recog_memoized (restinsn);
/* Now extract both insns and see if we can meet their /* Now extract both insns and see if we can meet their
constraints. */ constraints. */
ok = (reg_save_code[i][j] != (enum insn_code)-1 ok = (reg_save_code[i][mode] != (enum insn_code)-1
&& reg_restore_code[i][j] != (enum insn_code)-1); && reg_restore_code[i][mode] != (enum insn_code)-1);
if (ok) if (ok)
{ {
extract_insn (saveinsn); extract_insn (saveinsn);
...@@ -207,14 +210,26 @@ init_caller_save () ...@@ -207,14 +210,26 @@ init_caller_save ()
if (! ok) if (! ok)
{ {
regno_save_mode[i][j] = VOIDmode; reg_save_code[i][mode] = (enum insn_code) -1;
if (j == 1) reg_restore_code[i][mode] = (enum insn_code) -1;
{
call_fixed_regs[i] = 1;
SET_HARD_REG_BIT (call_fixed_reg_set, i);
}
} }
} }
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 (); end_sequence ();
} }
...@@ -339,6 +354,7 @@ void ...@@ -339,6 +354,7 @@ void
save_call_clobbered_regs () save_call_clobbered_regs ()
{ {
struct insn_chain *chain, *next; struct insn_chain *chain, *next;
enum machine_mode save_mode [FIRST_PSEUDO_REGISTER];
CLEAR_HARD_REG_SET (hard_regs_saved); CLEAR_HARD_REG_SET (hard_regs_saved);
n_regs_saved = 0; n_regs_saved = 0;
...@@ -374,7 +390,7 @@ save_call_clobbered_regs () ...@@ -374,7 +390,7 @@ save_call_clobbered_regs ()
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (referenced_regs, 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) if (code == CALL_INSN)
...@@ -386,8 +402,37 @@ save_call_clobbered_regs () ...@@ -386,8 +402,37 @@ save_call_clobbered_regs ()
regs are live during the call. */ regs are live during the call. */
REG_SET_TO_HARD_REG_SET (hard_regs_to_save, REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout); &chain->live_throughout);
compute_use_by_pseudos (&hard_regs_to_save, /* Save hard registers always in the widest mode availble. */
&chain->live_throughout); 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 /* 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 to be saved. N.B. the call insn might set a subreg of a
...@@ -404,7 +449,7 @@ save_call_clobbered_regs () ...@@ -404,7 +449,7 @@ save_call_clobbered_regs ()
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, 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. */ /* Must recompute n_regs_saved. */
n_regs_saved = 0; n_regs_saved = 0;
...@@ -425,7 +470,7 @@ save_call_clobbered_regs () ...@@ -425,7 +470,7 @@ save_call_clobbered_regs ()
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno)) if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
regno += insert_restore (chain, GET_CODE (insn) == JUMP_INSN, 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) ...@@ -572,17 +617,19 @@ mark_referenced_regs (x)
Return the extra number of registers saved. */ Return the extra number of registers saved. */
static int static int
insert_restore (chain, before_p, regno, maxrestore) insert_restore (chain, before_p, regno, maxrestore, save_mode)
struct insn_chain *chain; struct insn_chain *chain;
int before_p; int before_p;
int regno; int regno;
int maxrestore; int maxrestore;
enum machine_mode *save_mode;
{ {
int i, k; int i, k;
rtx pat = NULL_RTX; rtx pat = NULL_RTX;
enum insn_code code = CODE_FOR_nothing; enum insn_code code = CODE_FOR_nothing;
int numregs = 0; unsigned int numregs = 0;
struct insn_chain *new; struct insn_chain *new;
rtx mem;
/* A common failure mode if register status is not correct in the RTL /* 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 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) ...@@ -620,11 +667,15 @@ insert_restore (chain, before_p, regno, maxrestore)
break; 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, pat = gen_rtx_SET (VOIDmode,
gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]), gen_rtx_REG (GET_MODE (mem),
regno), regno), mem);
regno_save_mem[regno][numregs]); code = reg_restore_code[regno][GET_MODE (mem)];
code = reg_restore_code[regno][numregs];
new = insert_one_insn (chain, before_p, code, pat); new = insert_one_insn (chain, before_p, code, pat);
/* Clear status for all registers we restored. */ /* Clear status for all registers we restored. */
...@@ -643,17 +694,20 @@ insert_restore (chain, before_p, regno, maxrestore) ...@@ -643,17 +694,20 @@ insert_restore (chain, before_p, regno, maxrestore)
/* Like insert_restore above, but save registers instead. */ /* Like insert_restore above, but save registers instead. */
static int static int
insert_save (chain, before_p, regno, to_save) insert_save (chain, before_p, regno, to_save, save_mode)
struct insn_chain *chain; struct insn_chain *chain;
int before_p; int before_p;
int regno; int regno;
HARD_REG_SET *to_save; HARD_REG_SET *to_save;
enum machine_mode *save_mode;
{ {
int i, k; int i;
unsigned int k;
rtx pat = NULL_RTX; rtx pat = NULL_RTX;
enum insn_code code = CODE_FOR_nothing; enum insn_code code = CODE_FOR_nothing;
int numregs = 0; unsigned int numregs = 0;
struct insn_chain *new; struct insn_chain *new;
rtx mem;
/* A common failure mode if register status is not correct in the RTL /* 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 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) ...@@ -690,10 +744,15 @@ insert_save (chain, before_p, regno, to_save)
break; break;
} }
pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][numregs], mem = regno_save_mem [regno][numregs];
gen_rtx_REG (GET_MODE (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)); regno));
code = reg_save_code[regno][numregs]; code = reg_save_code[regno][GET_MODE (mem)];
new = insert_one_insn (chain, before_p, code, pat); new = insert_one_insn (chain, before_p, code, pat);
/* Set hard_regs_saved and dead_or_set for all the registers we saved. */ /* Set hard_regs_saved and dead_or_set for all the registers we saved. */
......
...@@ -648,7 +648,7 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string; ...@@ -648,7 +648,7 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string;
/* Specify the modes required to caller save a given hard regno. */ /* Specify the modes required to caller save a given hard regno. */
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) (c4x_caller_save_map[REGNO]) #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) (c4x_caller_save_map[REGNO])
#define HARD_REGNO_MODE_OK(REGNO, MODE) c4x_hard_regno_mode_ok(REGNO, MODE) #define HARD_REGNO_MODE_OK(REGNO, MODE) c4x_hard_regno_mode_ok(REGNO, MODE)
......
...@@ -819,11 +819,16 @@ extern int ix86_arch; ...@@ -819,11 +819,16 @@ extern int ix86_arch;
|| ((MODE1) == HImode && (MODE2) == SImode)) || ((MODE1) == HImode && (MODE2) == SImode))
/* Specify the modes required to caller save a given hard regno. /* Specify the modes required to caller save a given hard regno.
We do this on i386 to prevent flags from being saved at all. */ We do this on i386 to prevent flags from being saved at all.
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) \ Kill any attempts to combine saving of modes. */
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
(CC_REGNO_P (REGNO) ? VOIDmode \ (CC_REGNO_P (REGNO) ? VOIDmode \
: choose_hard_reg_mode ((REGNO), (NREGS))) : (MODE) == VOIDmode && (NREGS) != 1 ? VOIDmode \
: (MODE) == VOIDmode ? choose_hard_reg_mode ((REGNO), (NREGS)) \
: (MODE) == HImode && !TARGET_PARTIAL_REG_STALL ? SImode \
: (MODE) == QImode && (REGNO) >= 4 ? SImode : (MODE))
/* Specify the registers used for certain standard purposes. /* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */ The values of these macros are register numbers. */
......
...@@ -192,7 +192,7 @@ extern int caller_save_needed; ...@@ -192,7 +192,7 @@ extern int caller_save_needed;
/* Select a register mode required for caller save of hard regno REGNO. */ /* Select a register mode required for caller save of hard regno REGNO. */
#ifndef HARD_REGNO_CALLER_SAVE_MODE #ifndef HARD_REGNO_CALLER_SAVE_MODE
#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) \ #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
choose_hard_reg_mode (REGNO, NREGS) choose_hard_reg_mode (REGNO, NREGS)
#endif #endif
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment