From 301652e232285a4193a7190b5a266f391c726c05 Mon Sep 17 00:00:00 2001 From: hubicka Date: Wed, 28 Feb 2001 16:24:00 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@40120 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 18 ++++++- gcc/caller-save.c | 133 +++++++++++++++++++++++++++++++++++-------------- gcc/config/c4x/c4x.h | 2 +- gcc/config/i386/i386.h | 11 ++-- gcc/regs.h | 2 +- 5 files changed, 123 insertions(+), 43 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9517123..b4ac8bc 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,20 @@ -Wed Feb 28 17:19:28 CET 2001 Jan Hubicka + + * 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 * ifcvt.c (noce_emit_store_flag, noce_try_store_flag_constants, noce_try_store_flag_inc, noce_try_store_flag_mask, diff --git a/gcc/caller-save.c b/gcc/caller-save.c index c8302ae..445de2c 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. */ diff --git a/gcc/config/c4x/c4x.h b/gcc/config/c4x/c4x.h index 72ffb37..4250bf5 100644 --- a/gcc/config/c4x/c4x.h +++ b/gcc/config/c4x/c4x.h @@ -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. */ -#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) diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index b4f7d30..1ba6118 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -819,11 +819,16 @@ extern int ix86_arch; || ((MODE1) == HImode && (MODE2) == SImode)) /* 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 \ - : 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. The values of these macros are register numbers. */ diff --git a/gcc/regs.h b/gcc/regs.h index c219ecc..0822966 100644 --- a/gcc/regs.h +++ b/gcc/regs.h @@ -192,7 +192,7 @@ extern int caller_save_needed; /* Select a register mode required for caller save of hard regno REGNO. */ #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) #endif -- 2.7.4