diff options
author | obrien <obrien@FreeBSD.org> | 2002-02-01 18:16:02 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2002-02-01 18:16:02 +0000 |
commit | c9ab9ae440a8066b2c2b85b157b1fdadcf09916a (patch) | |
tree | 086d9d6c8fbd4fc8fe4495059332f66bc0f8d12b /contrib/gcc/caller-save.c | |
parent | 2ecfd8bd04b63f335c1ec6295740a4bfd97a4fa6 (diff) | |
download | FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.zip FreeBSD-src-c9ab9ae440a8066b2c2b85b157b1fdadcf09916a.tar.gz |
Enlist the FreeBSD-CURRENT users as testers of what is to become Gcc 3.1.0.
These bits are taken from the FSF anoncvs repo on 1-Feb-2002 08:20 PST.
Diffstat (limited to 'contrib/gcc/caller-save.c')
-rw-r--r-- | contrib/gcc/caller-save.c | 430 |
1 files changed, 269 insertions, 161 deletions
diff --git a/contrib/gcc/caller-save.c b/contrib/gcc/caller-save.c index 7c390a5..87a13dc 100644 --- a/contrib/gcc/caller-save.c +++ b/contrib/gcc/caller-save.c @@ -1,22 +1,23 @@ /* Save and restore call-clobbered registers which are live across a call. - Copyright (C) 1989, 1992, 94-95, 97, 98, 1999 Free Software Foundation, Inc. + Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998, + 1999, 2000, 2001, 2002 Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the 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, 59 Temple Place - Suite 330, -Boston, MA 02111-1307, USA. */ +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ #include "config.h" #include "system.h" @@ -28,8 +29,10 @@ Boston, MA 02111-1307, USA. */ #include "recog.h" #include "basic-block.h" #include "reload.h" +#include "function.h" #include "expr.h" #include "toplev.h" +#include "tm_p.h" #ifndef MAX_MOVE_MAX #define MAX_MOVE_MAX MOVE_MAX @@ -61,10 +64,10 @@ static rtx when we emit them, the addresses might not be valid, so they might not be recognized. */ -static enum insn_code - 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 / MIN_UNITS_PER_WORD + 1]; +static int + reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE]; +static int + reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE]; /* Set of hard regs currently residing in save area (during insn scan). */ @@ -83,14 +86,16 @@ static HARD_REG_SET referenced_regs; static HARD_REG_SET this_insn_sets; -static void mark_set_regs PROTO((rtx, rtx)); -static void mark_referenced_regs PROTO((rtx)); -static int insert_save PROTO((struct insn_chain *, int, int, - HARD_REG_SET *)); -static int insert_restore PROTO((struct insn_chain *, int, int, - int)); -static void insert_one_insn PROTO((struct insn_chain *, int, - enum insn_code, rtx)); +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 *, + enum machine_mode *)); +static int insert_restore PARAMS ((struct insn_chain *, int, int, + int, enum machine_mode *)); +static struct insn_chain *insert_one_insn PARAMS ((struct insn_chain *, int, + int, rtx)); +static void add_stored_regs PARAMS ((rtx, rtx, void *)); /* Initialize for caller-save. @@ -105,11 +110,11 @@ static void insert_one_insn PROTO((struct insn_chain *, int, void init_caller_save () { - char *first_obj = (char *) oballoc (0); rtx addr_reg; 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, @@ -121,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; @@ -145,7 +151,9 @@ init_caller_save () that register in every mode we will use to save registers. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (TEST_HARD_REG_BIT (reg_class_contents[(int) BASE_REG_CLASS], i)) + if (TEST_HARD_REG_BIT + (reg_class_contents + [(int) MODE_BASE_REG_CLASS (regno_save_mode [i][1])], i)) break; if (i == FIRST_PSEUDO_REGISTER) @@ -176,24 +184,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] != -1 + && reg_restore_code[i][mode] != -1); if (ok) { extract_insn (saveinsn); @@ -204,18 +212,28 @@ 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] = -1; + reg_restore_code[i][mode] = -1; } - } + } + else + { + reg_save_code[i][mode] = -1; + reg_restore_code[i][mode] = -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]] == -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 (); - - obfree (first_obj); } /* Initialize save areas by showing that we haven't allocated any yet. */ @@ -252,6 +270,7 @@ void setup_save_areas () { int i, j, k; + unsigned int r; HARD_REG_SET hard_regs_used; /* Allocate space in the save area for the largest multi-register @@ -263,16 +282,13 @@ setup_save_areas () for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) if (reg_renumber[i] >= 0 && REG_N_CALLS_CROSSED (i) > 0) { - int regno = reg_renumber[i]; - int endregno + unsigned int regno = reg_renumber[i]; + unsigned int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (regno_reg_rtx[i])); - int nregs = endregno - regno; - for (j = 0; j < nregs; j++) - { - if (call_used_regs[regno+j]) - SET_HARD_REG_BIT (hard_regs_used, regno+j); - } + for (r = regno; r < endregno; r++) + if (call_used_regs[r]) + SET_HARD_REG_BIT (hard_regs_used, r); } /* Now run through all the call-used hard-registers and allocate @@ -315,23 +331,29 @@ setup_save_areas () /* Setup single word save area just in case... */ for (k = 0; k < j; k++) - { - /* This should not depend on WORDS_BIG_ENDIAN. - The order of words in regs is the same as in memory. */ - rtx temp = gen_rtx_MEM (regno_save_mode[i+k][1], - XEXP (regno_save_mem[i][j], 0)); - - regno_save_mem[i+k][1] - = adj_offsettable_operand (temp, k * UNITS_PER_WORD); - } + /* This should not depend on WORDS_BIG_ENDIAN. + The order of words in regs is the same as in memory. */ + regno_save_mem[i + k][1] + = adjust_address_nv (regno_save_mem[i][j], + regno_save_mode[i + k][1], + k * UNITS_PER_WORD); } + + /* Now loop again and set the alias set of any save areas we made to + the alias set used to represent frame objects. */ + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + for (j = MOVE_MAX_WORDS; j > 0; j--) + if (regno_save_mem[i][j] != 0) + set_mem_alias_set (regno_save_mem[i][j], get_frame_alias_set ()); } /* Find the places where hard regs are live across calls and save them. */ + 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; @@ -367,24 +389,56 @@ 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) { - rtx x; - int regno, nregs; + int regno; HARD_REG_SET hard_regs_to_save; /* Use the register life information in CHAIN to compute which - regs are live before the call. */ - REG_SET_TO_HARD_REG_SET (hard_regs_to_save, chain->live_before); - compute_use_by_pseudos (&hard_regs_to_save, chain->live_before); + regs are live during the call. */ + REG_SET_TO_HARD_REG_SET (hard_regs_to_save, + &chain->live_throughout); + /* Save hard registers always in the widest mode available. */ + 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 through 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. */ + to be saved. N.B. the call insn might set a subreg of a + multi-hard-reg pseudo; then the pseudo is considered live + during the call, but the subreg that is set isn't. */ CLEAR_HARD_REG_SET (this_insn_sets); - note_stores (PATTERN (insn), mark_set_regs); + note_stores (PATTERN (insn), mark_set_regs, NULL); /* Compute which hard regs must be saved before this call. */ AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set); @@ -392,48 +446,9 @@ save_call_clobbered_regs () AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved); AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set); - /* Registers used for function parameters need not be saved. */ - for (x = CALL_INSN_FUNCTION_USAGE (insn); x != 0; - x = XEXP (x, 1)) - { - rtx y; - - if (GET_CODE (XEXP (x, 0)) != USE) - continue; - y = XEXP (XEXP (x, 0), 0); - if (GET_CODE (y) != REG) - abort (); - regno = REGNO (y); - if (REGNO (y) >= FIRST_PSEUDO_REGISTER) - abort (); - nregs = HARD_REGNO_NREGS (regno, GET_MODE (y)); - while (nregs-- > 0) - CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs); - } - - /* Neither do registers for which we find a death note. */ - for (x = REG_NOTES (insn); x != 0; x = XEXP (x, 1)) - { - rtx y = XEXP (x, 0); - - if (REG_NOTE_KIND (x) != REG_DEAD) - continue; - if (GET_CODE (y) != REG) - abort (); - regno = REGNO (y); - - if (regno >= FIRST_PSEUDO_REGISTER) - regno = reg_renumber[regno]; - if (regno < 0) - continue; - nregs = HARD_REGNO_NREGS (regno, GET_MODE (y)); - while (nregs-- > 0) - CLEAR_HARD_REG_BIT (hard_regs_to_save, regno + nregs); - } - 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; @@ -454,7 +469,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); } } } @@ -464,28 +479,68 @@ save_call_clobbered_regs () been assigned hard regs have had their register number changed already, so we can ignore pseudos. */ static void -mark_set_regs (reg, setter) +mark_set_regs (reg, setter, data) rtx reg; rtx setter ATTRIBUTE_UNUSED; + void *data ATTRIBUTE_UNUSED; { - register int regno, endregno, i; + int regno, endregno, i; enum machine_mode mode = GET_MODE (reg); - int word = 0; if (GET_CODE (reg) == SUBREG) { - word = SUBREG_WORD (reg); + rtx inner = SUBREG_REG (reg); + if (GET_CODE (inner) != REG || REGNO (inner) >= FIRST_PSEUDO_REGISTER) + return; + + regno = subreg_hard_regno (reg, 1); + } + else if (GET_CODE (reg) == REG + && REGNO (reg) < FIRST_PSEUDO_REGISTER) + regno = REGNO (reg); + else + return; + + endregno = regno + HARD_REGNO_NREGS (regno, mode); + + for (i = regno; i < endregno; i++) + SET_HARD_REG_BIT (this_insn_sets, i); +} + +/* Here from note_stores when an insn stores a value in a register. + Set the proper bit or bits in the passed regset. All pseudos that have + been assigned hard regs have had their register number changed already, + so we can ignore pseudos. */ +static void +add_stored_regs (reg, setter, data) + rtx reg; + rtx setter; + void *data; +{ + int regno, endregno, i; + enum machine_mode mode = GET_MODE (reg); + int offset = 0; + + if (GET_CODE (setter) == CLOBBER) + return; + + if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG) + { + offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)), + GET_MODE (SUBREG_REG (reg)), + SUBREG_BYTE (reg), + GET_MODE (reg)); reg = SUBREG_REG (reg); } if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER) return; - regno = REGNO (reg) + word; + regno = REGNO (reg) + offset; endregno = regno + HARD_REGNO_NREGS (regno, mode); for (i = regno; i < endregno; i++) - SET_HARD_REG_BIT (this_insn_sets, i); + SET_REGNO_REG_SET ((regset) data, i); } /* Walk X and record all referenced registers in REFERENCED_REGS. */ @@ -494,7 +549,7 @@ mark_referenced_regs (x) rtx x; { enum rtx_code code = GET_CODE (x); - char *fmt; + const char *fmt; int i, j; if (code == SET) @@ -504,7 +559,14 @@ mark_referenced_regs (x) x = SET_DEST (x); code = GET_CODE (x); if (code == REG || code == PC || code == CC0 - || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG)) + || (code == SUBREG && GET_CODE (SUBREG_REG (x)) == REG + /* If we're setting only part of a multi-word register, + we shall mark it as referenced, because the words + that are not being set should be restored. */ + && ((GET_MODE_SIZE (GET_MODE (x)) + >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))) + || (GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))) + <= UNITS_PER_WORD)))) return; } if (code == MEM || code == SUBREG) @@ -560,16 +622,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; + int i, k; rtx pat = NULL_RTX; - enum insn_code code = CODE_FOR_nothing; - int numregs = 0; + int code; + 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 @@ -587,7 +652,7 @@ insert_restore (chain, before_p, regno, maxrestore) backwards to the single register case. */ for (i = maxrestore; i > 0; i--) { - int j, k; + int j; int ok = 1; if (regno_save_mem[regno][i] == 0) @@ -603,41 +668,50 @@ insert_restore (chain, before_p, regno, maxrestore) if (! ok) continue; - pat = gen_rtx_SET (VOIDmode, - gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]), - regno), - regno_save_mem[regno][i]); - code = reg_restore_code[regno][i]; - - /* Clear status for all registers we restored. */ - for (k = 0; k < i; k++) - { - CLEAR_HARD_REG_BIT (hard_regs_saved, regno + k); - n_regs_saved--; - } - numregs = i; break; } - insert_one_insn (chain, before_p, code, pat); + mem = regno_save_mem [regno][numregs]; + if (save_mode [regno] != VOIDmode + && save_mode [regno] != GET_MODE (mem) + && numregs == (unsigned int) HARD_REGNO_NREGS (regno, save_mode [regno])) + mem = adjust_address (mem, save_mode[regno], 0); + pat = gen_rtx_SET (VOIDmode, + 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. */ + for (k = 0; k < i; k++) + { + CLEAR_HARD_REG_BIT (hard_regs_saved, regno + k); + SET_REGNO_REG_SET (&new->dead_or_set, regno + k); + n_regs_saved--; + } /* Tell our callers how many extra registers we saved/restored */ return numregs - 1; } /* 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; + unsigned int k; rtx pat = NULL_RTX; - enum insn_code code = CODE_FOR_nothing; - int numregs = 0; + int code; + 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 @@ -655,7 +729,7 @@ insert_save (chain, before_p, regno, to_save) Work backwards to the single register case. */ for (i = MOVE_MAX_WORDS; i > 0; i--) { - int j, k; + int j; int ok = 1; if (regno_save_mem[regno][i] == 0) continue; @@ -670,34 +744,39 @@ insert_save (chain, before_p, regno, to_save) if (! ok) continue; - pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i], - gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]), - regno)); - code = reg_save_code[regno][i]; - - /* Set hard_regs_saved for all the registers we saved. */ - for (k = 0; k < i; k++) - { - SET_HARD_REG_BIT (hard_regs_saved, regno + k); - n_regs_saved++; - } - numregs = i; break; } - insert_one_insn (chain, before_p, code, pat); + mem = regno_save_mem [regno][numregs]; + if (save_mode [regno] != VOIDmode + && save_mode [regno] != GET_MODE (mem) + && numregs == (unsigned int) HARD_REGNO_NREGS (regno, save_mode [regno])) + mem = adjust_address (mem, save_mode[regno], 0); + pat = gen_rtx_SET (VOIDmode, mem, + gen_rtx_REG (GET_MODE (mem), + regno)); + 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. */ + for (k = 0; k < numregs; k++) + { + SET_HARD_REG_BIT (hard_regs_saved, regno + k); + SET_REGNO_REG_SET (&new->dead_or_set, regno + k); + n_regs_saved++; + } /* Tell our callers how many extra registers we saved/restored */ return numregs - 1; } /* Emit a new caller-save insn and set the code. */ -static void +static struct insn_chain * insert_one_insn (chain, before_p, code, pat) struct insn_chain *chain; int before_p; - enum insn_code code; + int code; rtx pat; { rtx insn = chain->insn; @@ -719,6 +798,8 @@ insert_one_insn (chain, before_p, code, pat) new = new_insn_chain (); if (before_p) { + rtx link; + new->prev = chain->prev; if (new->prev != 0) new->prev->next = new; @@ -730,8 +811,29 @@ insert_one_insn (chain, before_p, code, pat) new->insn = emit_insn_before (pat, insn); /* ??? It would be nice if we could exclude the already / still saved registers from the live sets. */ - COPY_REG_SET (new->live_before, chain->live_before); - COPY_REG_SET (new->live_after, chain->live_before); + COPY_REG_SET (&new->live_throughout, &chain->live_throughout); + /* Registers that die in CHAIN->INSN still live in the new insn. */ + for (link = REG_NOTES (chain->insn); link; link = XEXP (link, 1)) + { + if (REG_NOTE_KIND (link) == REG_DEAD) + { + rtx reg = XEXP (link, 0); + int regno, i; + + if (GET_CODE (reg) != REG) + abort (); + + regno = REGNO (reg); + if (regno >= FIRST_PSEUDO_REGISTER) + regno = reg_renumber[regno]; + if (regno < 0) + continue; + for (i = HARD_REGNO_NREGS (regno, GET_MODE (reg)) - 1; + i >= 0; i--) + SET_REGNO_REG_SET (&new->live_throughout, regno + i); + } + } + CLEAR_REG_SET (&new->dead_or_set); if (chain->insn == BLOCK_HEAD (chain->block)) BLOCK_HEAD (chain->block) = new->insn; } @@ -745,8 +847,13 @@ insert_one_insn (chain, before_p, code, pat) new->insn = emit_insn_after (pat, insn); /* ??? It would be nice if we could exclude the already / still saved registers from the live sets, and observe REG_UNUSED notes. */ - COPY_REG_SET (new->live_before, chain->live_after); - COPY_REG_SET (new->live_after, chain->live_after); + COPY_REG_SET (&new->live_throughout, &chain->live_throughout); + /* Registers that are set in CHAIN->INSN live in the new insn. + (Unless there is a REG_UNUSED note for them, but we don't + look for them here.) */ + note_stores (PATTERN (chain->insn), add_stored_regs, + &new->live_throughout); + CLEAR_REG_SET (&new->dead_or_set); if (chain->insn == BLOCK_END (chain->block)) BLOCK_END (chain->block) = new->insn; } @@ -754,4 +861,5 @@ insert_one_insn (chain, before_p, code, pat) new->is_caller_save_insn = 1; INSN_CODE (new->insn) = code; + return new; } |