X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcaller-save.c;h=6dc90189ee6e61563d9f19f1b058f34bd233c6d1;hb=2b01e39a79377e11ff780654f8f35c6448e6dd30;hp=3518feb373bc770f9506f76152b032596dccf54f;hpb=b615c119248b5b29b6cec41bdcc0b8baa9b6b7b6;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/caller-save.c b/gcc/caller-save.c index 3518feb373b..6dc90189ee6 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -1,5 +1,5 @@ /* Save and restore call-clobbered registers which are live across a call. - Copyright (C) 1989, 1992 Free Software Foundation, Inc. + Copyright (C) 1989, 1992, 1994, 1995 Free Software Foundation, Inc. This file is part of GNU CC. @@ -15,7 +15,8 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU CC; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ #include "config.h" #include "rtl.h" @@ -32,8 +33,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #define MAX_MOVE_MAX MOVE_MAX #endif -#ifndef MAX_UNITS_PER_WORD -#define MAX_UNITS_PER_WORD UNITS_PER_WORD +#ifndef MIN_UNITS_PER_WORD +#define MIN_UNITS_PER_WORD UNITS_PER_WORD #endif /* Modes for each hard register that we can save. The smallest mode is wide @@ -42,13 +43,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ If that is not possible the save is done one register at a time. */ static enum machine_mode - regno_save_mode[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MAX_UNITS_PER_WORD + 1]; + regno_save_mode[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1]; /* For each hard register, a place on the stack where it can be saved, if needed. */ static rtx - regno_save_mem[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MAX_UNITS_PER_WORD + 1]; + regno_save_mem[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1]; /* We will only make a register eligible for caller-save if it can be saved in its widest mode with a simple SET insn as long as the memory @@ -57,9 +58,9 @@ static rtx be recognized. */ static enum insn_code - reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MAX_UNITS_PER_WORD + 1]; + reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1]; static enum insn_code - reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MAX_UNITS_PER_WORD + 1]; + reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1]; /* Set of hard regs currently live (during scan of all insns). */ @@ -77,53 +78,12 @@ static HARD_REG_SET hard_regs_need_restore; int n_regs_saved; -static enum machine_mode choose_hard_reg_mode PROTO((int, int)); 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)); static int insert_save_restore PROTO((rtx, int, int, enum machine_mode, int)); -/* Return a machine mode that is legitimate for hard reg REGNO and large - enough to save nregs. If we can't find one, return VOIDmode. */ - -static enum machine_mode -choose_hard_reg_mode (regno, nregs) - int regno; - int nregs; -{ - enum machine_mode found_mode = VOIDmode, mode; - - /* We first look for the largest integer mode that can be validly - held in REGNO. If none, we look for the largest floating-point mode. - If we still didn't find a valid mode, try CCmode. */ - - for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != VOIDmode; - mode = GET_MODE_WIDER_MODE (mode)) - if (HARD_REGNO_NREGS (regno, mode) == nregs - && HARD_REGNO_MODE_OK (regno, mode)) - found_mode = mode; - - if (found_mode != VOIDmode) - return found_mode; - - for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode; - mode = GET_MODE_WIDER_MODE (mode)) - if (HARD_REGNO_NREGS (regno, mode) == nregs - && HARD_REGNO_MODE_OK (regno, mode)) - found_mode = mode; - - if (found_mode != VOIDmode) - return found_mode; - - if (HARD_REGNO_NREGS (regno, CCmode) == nregs - && HARD_REGNO_MODE_OK (regno, CCmode)) - return CCmode; - - /* We can't find a mode valid for this register. */ - return VOIDmode; -} - /* Initialize for caller-save. Look at all the hard registers that are used by a call and for which @@ -465,32 +425,62 @@ save_call_clobbered_regs (insn_mode) live, call-used, not fixed, and not already saved. We must test at this point because registers that die in a CALL_INSN are not live across the call and likewise for registers that - are born in the CALL_INSN. */ + are born in the CALL_INSN. + + If registers are filled with parameters for this function, + and some of these are also being set by this function, then + they will not appear to die (no REG_DEAD note for them), + to check if in fact they do, collect the set registers in + hard_regs_live first. */ if (code == CALL_INSN) { + HARD_REG_SET this_call_sets; + { + HARD_REG_SET old_hard_regs_live; + + /* Save the hard_regs_live information. */ + COPY_HARD_REG_SET (old_hard_regs_live, hard_regs_live); + + /* Now calculate hard_regs_live for this CALL_INSN + only. */ + CLEAR_HARD_REG_SET (hard_regs_live); + note_stores (PATTERN (insn), set_reg_live); + COPY_HARD_REG_SET (this_call_sets, hard_regs_live); + + /* Restore the hard_regs_live information. */ + COPY_HARD_REG_SET (hard_regs_live, old_hard_regs_live); + } + for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (call_used_regs[regno] && ! call_fixed_regs[regno] && TEST_HARD_REG_BIT (hard_regs_live, regno) + /* 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_restore (insn, 1, regno, insn_mode, 0); -#ifdef HARD_REG_SET - hard_regs_need_restore = hard_regs_saved; -#else - COPY_HARD_REG_SET (hard_regs_need_restore, - hard_regs_saved); -#endif + + /* Put the information for this CALL_INSN on top of what + we already had. */ + IOR_HARD_REG_SET (hard_regs_live, this_call_sets); + COPY_HARD_REG_SET (hard_regs_need_restore, hard_regs_saved); /* Must recompute n_regs_saved. */ n_regs_saved = 0; for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (TEST_HARD_REG_BIT (hard_regs_saved, regno)) n_regs_saved++; - } - - note_stores (PATTERN (insn), set_reg_live); + else + { + note_stores (PATTERN (insn), set_reg_live); +#ifdef AUTO_INC_DEC + for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) + if (REG_NOTE_KIND (link) == REG_INC) + set_reg_live (XEXP (link, 0), NULL_RTX); +#endif + } for (link = REG_NOTES (insn); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_UNUSED) @@ -674,14 +664,6 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore) if (regno_save_mem[regno][1] == 0) abort (); - /* If INSN is a CALL_INSN, we must insert our insns before any - USE insns in front of the CALL_INSN. */ - - if (GET_CODE (insn) == CALL_INSN) - while (GET_CODE (PREV_INSN (insn)) == INSN - && GET_CODE (PATTERN (PREV_INSN (insn))) == USE) - insn = PREV_INSN (insn); - #ifdef HAVE_cc0 /* If INSN references CC0, put our insns in front of the insn that sets CC0. This is always safe, since the only way we could be passed an