From 285f3cf09acda794f6e7bba9cb6d5163c94b5af4 Mon Sep 17 00:00:00 2001 From: "J\"orn Rennecke" Date: Wed, 15 Dec 1999 14:57:29 +0000 Subject: caller-save.c (insert_one_insn): Returns struct insn_chain *. * caller-save.c (insert_one_insn): Returns struct insn_chain *. Handle live_throughout / dead_or_set instead of live_before / live_after. (save_call_clobbered_regs): Get register livenessinformation from chain->live_throughout. (add_stored_regs): New function. (insert_restore, insert_save): Add restored / saved registers to dead_or_set. * global.c (reg_dies): New parameter chain. (reg_becomes_live): Third parameter is regs_set now. Changed all callers. (reg_dies): New parameter chain. Changed all callers. (build_insn_chain): Set live_throughout instead of live_before / live_after. * reload.h (struct insn_chain): Replace members live_before / live_after with live_throughout / dead_or_set. * reload1.c (new_insn_chain): Handle live_throughout / dead_or_set instead of live_before / live_after. (maybe_fix_stack_asms, find_reload_regs, finish_spills): Likewise. (order_regs_for_reload, find_reg, finish_spills): Likewise. (choose_reload_regs_init): Likewise. * stupid.c (current_chain, find_clobbered_regs): Delete. (stupid_life_analysis): Set chain->live_throughout chain->dead_or_set instead of chain->live_before / chain->live_after. (mark_hard_ref): New function. (stupid_mark_refs): Call mark_hard_ref. Clear chain->live_throughout. From-SVN: r30957 --- gcc/ChangeLog | 29 ++++++++ gcc/caller-save.c | 196 +++++++++++++++++++++++++++++++----------------------- gcc/global.c | 58 ++++++++++------ gcc/reload.h | 9 +-- gcc/reload1.c | 44 ++++++------ gcc/stupid.c | 83 +++++++++++++---------- 6 files changed, 253 insertions(+), 166 deletions(-) (limited to 'gcc') diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aaf9470..5bc25d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,32 @@ +Wed Dec 15 14:55:24 1999 J"orn Rennecke + + * caller-save.c (insert_one_insn): Returns struct insn_chain *. + Handle live_throughout / dead_or_set instead of live_before / + live_after. + (save_call_clobbered_regs): Get register livenessinformation from + chain->live_throughout. + (add_stored_regs): New function. + (insert_restore, insert_save): Add restored / saved registers to + dead_or_set. + * global.c (reg_dies): New parameter chain. + (reg_becomes_live): Third parameter is regs_set now. + Changed all callers. + (reg_dies): New parameter chain. Changed all callers. + (build_insn_chain): Set live_throughout instead of + live_before / live_after. + * reload.h (struct insn_chain): Replace members live_before / + live_after with live_throughout / dead_or_set. + * reload1.c (new_insn_chain): Handle live_throughout / dead_or_set + instead of live_before / live_after. + (maybe_fix_stack_asms, find_reload_regs, finish_spills): Likewise. + (order_regs_for_reload, find_reg, finish_spills): Likewise. + (choose_reload_regs_init): Likewise. + * stupid.c (current_chain, find_clobbered_regs): Delete. + (stupid_life_analysis): Set chain->live_throughout chain->dead_or_set + instead of chain->live_before / chain->live_after. + (mark_hard_ref): New function. + (stupid_mark_refs): Call mark_hard_ref. Clear chain->live_throughout. + 1999-12-15 David S. Miller * rtlanal.c (reg_overlap_mentioned_p): Handle CONCAT. diff --git a/gcc/caller-save.c b/gcc/caller-save.c index b58fe87..bbd7831 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -90,8 +90,8 @@ 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 struct insn_chain *insert_one_insn PROTO((struct insn_chain *, int, + enum insn_code, rtx)); /* Initialize for caller-save. @@ -373,17 +373,20 @@ save_call_clobbered_regs () 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); + compute_use_by_pseudos (&hard_regs_to_save, + chain->live_throughout); /* 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, NULL); @@ -393,45 +396,6 @@ 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); @@ -490,6 +454,39 @@ mark_set_regs (reg, setter, data) 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; +{ + register int regno, endregno, i; + enum machine_mode mode = GET_MODE (reg); + int word = 0; + + if (GET_CODE (setter) == CLOBBER) + return; + + while (GET_CODE (reg) == SUBREG) + { + word += SUBREG_WORD (reg); + reg = SUBREG_REG (reg); + } + + if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER) + return; + + regno = REGNO (reg) + word; + endregno = regno + HARD_REGNO_NREGS (regno, mode); + + for (i = regno; i < endregno; i++) + SET_REGNO_REG_SET ((regset) data, i); +} + /* Walk X and record all referenced registers in REFERENCED_REGS. */ static void mark_referenced_regs (x) @@ -568,10 +565,11 @@ insert_restore (chain, before_p, regno, maxrestore) int regno; int maxrestore; { - int i; + int i, k; rtx pat = NULL_RTX; enum insn_code code = CODE_FOR_nothing; int numregs = 0; + struct insn_chain *new; /* 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 @@ -589,7 +587,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) @@ -605,24 +603,26 @@ 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); + 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]; + 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; @@ -636,10 +636,11 @@ insert_save (chain, before_p, regno, to_save) int regno; HARD_REG_SET *to_save; { - int i; + int i, k; rtx pat = NULL_RTX; enum insn_code code = CODE_FOR_nothing; int numregs = 0; + struct insn_chain *new; /* 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 @@ -657,7 +658,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; @@ -672,30 +673,30 @@ 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); + pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][numregs], + gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]), + regno)); + code = reg_save_code[regno][numregs]; + 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; @@ -721,6 +722,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; @@ -732,8 +735,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; } @@ -747,8 +771,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; } @@ -756,4 +785,5 @@ insert_one_insn (chain, before_p, code, pat) new->is_caller_save_insn = 1; INSN_CODE (new->insn) = code; + return new; } diff --git a/gcc/global.c b/gcc/global.c index c46c297..0405829 100644 --- a/gcc/global.c +++ b/gcc/global.c @@ -303,7 +303,8 @@ static void mark_reg_live_nc PROTO((int, enum machine_mode)); static void set_preference PROTO((rtx, rtx)); static void dump_conflicts PROTO((FILE *)); static void reg_becomes_live PROTO((rtx, rtx, void *)); -static void reg_dies PROTO((int, enum machine_mode)); +static void reg_dies PROTO((int, enum machine_mode, + struct insn_chain *)); static void build_insn_chain PROTO((rtx)); /* Perform allocation of pseudo-registers not allocated by local_alloc. @@ -1693,13 +1694,13 @@ mark_elimination (from, to) current life information. */ static regset live_relevant_regs; -/* Record in live_relevant_regs that register REG became live. This - is called via note_stores. */ +/* Record in live_relevant_regs and REGS_SET that register REG became live. + This is called via note_stores. */ static void -reg_becomes_live (reg, setter, data) +reg_becomes_live (reg, setter, regs_set) rtx reg; rtx setter ATTRIBUTE_UNUSED; - void *data ATTRIBUTE_UNUSED; + void *regs_set; { int regno; @@ -1714,26 +1715,44 @@ reg_becomes_live (reg, setter, data) { int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg)); while (nregs-- > 0) - SET_REGNO_REG_SET (live_relevant_regs, regno++); + { + SET_REGNO_REG_SET (live_relevant_regs, regno); + if (! fixed_regs[regno]) + SET_REGNO_REG_SET ((regset) regs_set, regno); + regno++; + } } else if (reg_renumber[regno] >= 0) - SET_REGNO_REG_SET (live_relevant_regs, regno); + { + SET_REGNO_REG_SET (live_relevant_regs, regno); + SET_REGNO_REG_SET ((regset) regs_set, regno); + } } /* Record in live_relevant_regs that register REGNO died. */ static void -reg_dies (regno, mode) +reg_dies (regno, mode, chain) int regno; enum machine_mode mode; + struct insn_chain *chain; { if (regno < FIRST_PSEUDO_REGISTER) { int nregs = HARD_REGNO_NREGS (regno, mode); while (nregs-- > 0) - CLEAR_REGNO_REG_SET (live_relevant_regs, regno++); + { + CLEAR_REGNO_REG_SET (live_relevant_regs, regno); + if (! fixed_regs[regno]) + SET_REGNO_REG_SET (chain->dead_or_set, regno); + regno++; + } } else - CLEAR_REGNO_REG_SET (live_relevant_regs, regno); + { + CLEAR_REGNO_REG_SET (live_relevant_regs, regno); + if (reg_renumber[regno] >= 0) + SET_REGNO_REG_SET (chain->dead_or_set, regno); + } } /* Walk the insns of the current function and build reload_insn_chain, @@ -1778,8 +1797,6 @@ build_insn_chain (first) c->insn = first; c->block = b; - COPY_REG_SET (c->live_before, live_relevant_regs); - if (GET_RTX_CLASS (GET_CODE (first)) == 'i') { rtx link; @@ -1789,16 +1806,18 @@ build_insn_chain (first) for (link = REG_NOTES (first); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_DEAD && GET_CODE (XEXP (link, 0)) == REG) - reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0))); + reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)), + c); + + COPY_REG_SET (c->live_throughout, live_relevant_regs); /* Mark everything born in this instruction as live. */ - note_stores (PATTERN (first), reg_becomes_live, NULL); + note_stores (PATTERN (first), reg_becomes_live, + c->dead_or_set); } - - /* Remember which registers are live at the end of the insn, before - killing those with REG_UNUSED notes. */ - COPY_REG_SET (c->live_after, live_relevant_regs); + else + COPY_REG_SET (c->live_throughout, live_relevant_regs); if (GET_RTX_CLASS (GET_CODE (first)) == 'i') { @@ -1809,7 +1828,8 @@ build_insn_chain (first) for (link = REG_NOTES (first); link; link = XEXP (link, 1)) if (REG_NOTE_KIND (link) == REG_UNUSED && GET_CODE (XEXP (link, 0)) == REG) - reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0))); + reg_dies (REGNO (XEXP (link, 0)), GET_MODE (XEXP (link, 0)), + c); } } diff --git a/gcc/reload.h b/gcc/reload.h index 52ede8d..391c047 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -224,12 +224,9 @@ struct insn_chain /* The rtx of the insn. */ rtx insn; /* Register life information: record all live hard registers, and all - live pseudos that have a hard register. - This information is recorded for the point immediately before the insn - (in live_before), and for the point within the insn at which all - outputs have just been written to (in live_after). */ - regset live_before; - regset live_after; + live pseudos that have a hard register. */ + regset live_throughout; + regset dead_or_set; /* Copies of the global variables computed by find_reloads. */ struct reload *rld; diff --git a/gcc/reload1.c b/gcc/reload1.c index bedcebb..dc69085 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -514,8 +514,8 @@ new_insn_chain () { c = (struct insn_chain *) obstack_alloc (&reload_obstack, sizeof (struct insn_chain)); - c->live_before = OBSTACK_ALLOC_REG_SET (&reload_obstack); - c->live_after = OBSTACK_ALLOC_REG_SET (&reload_obstack); + c->live_throughout = OBSTACK_ALLOC_REG_SET (&reload_obstack); + c->dead_or_set = OBSTACK_ALLOC_REG_SET (&reload_obstack); } else { @@ -1295,8 +1295,8 @@ maybe_fix_stack_asms () for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (allowed, i)) { - CLEAR_REGNO_REG_SET (chain->live_before, i); - CLEAR_REGNO_REG_SET (chain->live_after, i); + CLEAR_REGNO_REG_SET (chain->live_throughout, i); + CLEAR_REGNO_REG_SET (chain->dead_or_set, i); } } @@ -1516,8 +1516,8 @@ order_regs_for_reload (chain) /* Test the various reasons why we can't use a register for spilling in this insn. */ if (fixed_regs[i] - || REGNO_REG_SET_P (chain->live_before, i) - || REGNO_REG_SET_P (chain->live_after, i)) + || REGNO_REG_SET_P (chain->live_throughout, i) + || REGNO_REG_SET_P (chain->dead_or_set, i)) SET_HARD_REG_BIT (bad_spill_regs, i); } /* Now find out which pseudos are allocated to it, and update @@ -1525,12 +1525,12 @@ order_regs_for_reload (chain) CLEAR_REG_SET (&pseudos_counted); EXECUTE_IF_SET_IN_REG_SET - (chain->live_before, FIRST_PSEUDO_REGISTER, j, + (chain->live_throughout, FIRST_PSEUDO_REGISTER, j, { count_pseudo (j); }); EXECUTE_IF_SET_IN_REG_SET - (chain->live_after, FIRST_PSEUDO_REGISTER, j, + (chain->dead_or_set, FIRST_PSEUDO_REGISTER, j, { count_pseudo (j); }); @@ -1645,12 +1645,12 @@ find_reg (chain, order, dumpfile) rl->regno = best_reg; EXECUTE_IF_SET_IN_REG_SET - (chain->live_before, FIRST_PSEUDO_REGISTER, j, + (chain->live_throughout, FIRST_PSEUDO_REGISTER, j, { count_spilled_pseudo (best_reg, rl->nregs, j); }); EXECUTE_IF_SET_IN_REG_SET - (chain->live_after, FIRST_PSEUDO_REGISTER, j, + (chain->dead_or_set, FIRST_PSEUDO_REGISTER, j, { count_spilled_pseudo (best_reg, rl->nregs, j); }); @@ -3489,13 +3489,13 @@ finish_spills (global, dumpfile) for (chain = insns_need_reload; chain; chain = chain->next_need_reload) { EXECUTE_IF_SET_IN_REG_SET - (chain->live_before, FIRST_PSEUDO_REGISTER, i, + (chain->live_throughout, FIRST_PSEUDO_REGISTER, i, { ior_hard_reg_set (pseudo_forbidden_regs + i, &chain->used_spill_regs); }); EXECUTE_IF_SET_IN_REG_SET - (chain->live_after, FIRST_PSEUDO_REGISTER, i, + (chain->dead_or_set, FIRST_PSEUDO_REGISTER, i, { ior_hard_reg_set (pseudo_forbidden_regs + i, &chain->used_spill_regs); @@ -3528,22 +3528,22 @@ finish_spills (global, dumpfile) HARD_REG_SET used_by_pseudos; HARD_REG_SET used_by_pseudos2; - AND_COMPL_REG_SET (chain->live_before, &spilled_pseudos); - AND_COMPL_REG_SET (chain->live_after, &spilled_pseudos); + AND_COMPL_REG_SET (chain->live_throughout, &spilled_pseudos); + AND_COMPL_REG_SET (chain->dead_or_set, &spilled_pseudos); /* Mark any unallocated hard regs as available for spills. That makes inheritance work somewhat better. */ if (chain->need_reload) { - REG_SET_TO_HARD_REG_SET (used_by_pseudos, chain->live_before); - REG_SET_TO_HARD_REG_SET (used_by_pseudos2, chain->live_after); + REG_SET_TO_HARD_REG_SET (used_by_pseudos, chain->live_throughout); + REG_SET_TO_HARD_REG_SET (used_by_pseudos2, chain->dead_or_set); IOR_HARD_REG_SET (used_by_pseudos, used_by_pseudos2); /* Save the old value for the sanity test below. */ COPY_HARD_REG_SET (used_by_pseudos2, chain->used_spill_regs); - compute_use_by_pseudos (&used_by_pseudos, chain->live_before); - compute_use_by_pseudos (&used_by_pseudos, chain->live_after); + compute_use_by_pseudos (&used_by_pseudos, chain->live_throughout); + compute_use_by_pseudos (&used_by_pseudos, chain->dead_or_set); COMPL_HARD_REG_SET (chain->used_spill_regs, used_by_pseudos); AND_HARD_REG_SET (chain->used_spill_regs, used_spill_regs); @@ -5033,12 +5033,12 @@ choose_reload_regs_init (chain, save_reload_reg_rtx) CLEAR_HARD_REG_SET (reg_used_in_insn); { HARD_REG_SET tmp; - REG_SET_TO_HARD_REG_SET (tmp, chain->live_before); + REG_SET_TO_HARD_REG_SET (tmp, chain->live_throughout); IOR_HARD_REG_SET (reg_used_in_insn, tmp); - REG_SET_TO_HARD_REG_SET (tmp, chain->live_after); + REG_SET_TO_HARD_REG_SET (tmp, chain->dead_or_set); IOR_HARD_REG_SET (reg_used_in_insn, tmp); - compute_use_by_pseudos (®_used_in_insn, chain->live_before); - compute_use_by_pseudos (®_used_in_insn, chain->live_after); + compute_use_by_pseudos (®_used_in_insn, chain->live_throughout); + compute_use_by_pseudos (®_used_in_insn, chain->dead_or_set); } for (i = 0; i < reload_n_operands; i++) { diff --git a/gcc/stupid.c b/gcc/stupid.c index 61bac12..a4392e4 100644 --- a/gcc/stupid.c +++ b/gcc/stupid.c @@ -129,12 +129,13 @@ static int stupid_find_reg PROTO((int, enum reg_class, enum machine_mode, int, int, int)); static void stupid_mark_refs PROTO((rtx, struct insn_chain *)); static void find_clobbered_regs PROTO((rtx, rtx, void *)); +static void mark_hard_ref PROTO((rtx, int, struct insn_chain *)); /* For communication between stupid_life_analysis and find_clobbered_regs. */ static struct insn_chain *current_chain; /* This function, called via note_stores, marks any hard registers that are - clobbered in an insn as being live in the live_after and live_before fields + clobbered in an insn as being live in the live_throughout field of the appropriate insn_chain structure. */ static void @@ -161,8 +162,7 @@ find_clobbered_regs (reg, setter, data) nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg)); while (nregs-- > 0) { - SET_REGNO_REG_SET (current_chain->live_after, regno); - SET_REGNO_REG_SET (current_chain->live_before, regno++); + SET_REGNO_REG_SET (current_chain->live_throughout, regno++); } } @@ -285,7 +285,7 @@ stupid_life_analysis (f, nregs, file) chain->insn = insn; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (regs_live[i]) - SET_REGNO_REG_SET (chain->live_before, i); + SET_REGNO_REG_SET (chain->live_throughout, i); } /* Update which hard regs are currently live @@ -336,10 +336,6 @@ stupid_life_analysis (f, nregs, file) if (GET_CODE (insn) != NOTE && GET_CODE (insn) != BARRIER) { - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (regs_live[i]) - SET_REGNO_REG_SET (chain->live_after, i); - /* The regs_live array doesn't say anything about hard registers clobbered by this insn. So we need an extra pass over the pattern. */ @@ -407,21 +403,14 @@ stupid_life_analysis (f, nregs, file) continue; chain = reg_where_dead_chain[i]; - if (reg_where_dead[i] > INSN_SUID (chain->insn)) - SET_REGNO_REG_SET (chain->live_after, i); + SET_REGNO_REG_SET (chain->dead_or_set, i); - while (INSN_SUID (chain->insn) > reg_where_born_exact[i]) - { - SET_REGNO_REG_SET (chain->live_before, i); - chain = chain->prev; - if (!chain) - break; - SET_REGNO_REG_SET (chain->live_after, i); - } + while ((chain = chain->prev) + && INSN_SUID (chain->insn) > reg_where_born_exact[i]) + SET_REGNO_REG_SET (chain->live_throughout, i); - if (INSN_SUID (chain->insn) == reg_where_born_exact[i] - && reg_where_born_clobber[i]) - SET_REGNO_REG_SET (chain->live_before, i); + if (chain) + SET_REGNO_REG_SET (chain->dead_or_set, i); } if (file) @@ -568,6 +557,32 @@ stupid_find_reg (call_preserved, class, mode, return -1; } +/* Note that REG is being set or referenced, and add the appropriate + REG_DEAD / REG_UNUSED note(s). For sets, LIVE_BEFORE_P will be 0, + while for references, LIVE_BEFORE_P will be 1. + INSN is the instruction that the reg notes have to be added to. */ +static void +mark_hard_ref (reg, live_before_p, chain) + rtx reg; + int live_before_p; + struct insn_chain *chain; +{ + /* Hard reg: mark it live for continuing scan of previous insns. */ + int regno = REGNO (reg); + char *live = regs_live; + register int j; + int nregs = HARD_REGNO_NREGS (regno, GET_MODE (reg)); + + for (j = nregs - 1; j >= 0; j--) + { + if (! fixed_regs[regno+j] + && (! live_before_p || ! live[regno+j])) + SET_REGNO_REG_SET (chain->dead_or_set, regno+j); + regs_ever_live[regno+j] = 1; + live[regno+j] = live_before_p; + } +} + /* Walk X, noting all assignments and references to registers and recording what they imply about life spans. INSN is the current insn, supplied so we can find its suid. */ @@ -597,11 +612,13 @@ stupid_mark_refs (x, chain) >= FIRST_PSEUDO_REGISTER)))) { /* Register is being assigned. */ + rtx reg = SET_DEST (x); + /* If setting a SUBREG, we treat the entire reg as being set. */ if (GET_CODE (SET_DEST (x)) == SUBREG) - regno = REGNO (SUBREG_REG (SET_DEST (x))); - else - regno = REGNO (SET_DEST (x)); + reg = SUBREG_REG (reg); + + regno = REGNO (reg); /* For hard regs, update the where-live info. */ if (regno < FIRST_PSEUDO_REGISTER) @@ -609,15 +626,16 @@ stupid_mark_refs (x, chain) register int j = HARD_REGNO_NREGS (regno, GET_MODE (SET_DEST (x))); + mark_hard_ref (reg, 0, chain); + while (--j >= 0) { - regs_ever_live[regno+j] = 1; - regs_live[regno+j] = 0; - /* The following line is for unused outputs; they do get stored even though never used again. */ MARK_LIVE_AFTER (insn, regno+j); + CLEAR_REGNO_REG_SET (chain->live_throughout, regno + j); + /* When a hard reg is clobbered, mark it in use just before this insn, so it is live all through. */ if (code == CLOBBER && INSN_SUID (insn) > 0) @@ -706,15 +724,8 @@ stupid_mark_refs (x, chain) { regno = REGNO (x); if (regno < FIRST_PSEUDO_REGISTER) - { - /* Hard reg: mark it live for continuing scan of previous insns. */ - register int j = HARD_REGNO_NREGS (regno, GET_MODE (x)); - while (--j >= 0) - { - regs_ever_live[regno+j] = 1; - regs_live[regno+j] = 1; - } - } + /* Hard reg: mark it live for continuing scan of previous insns. */ + mark_hard_ref (x, 1, chain); else { /* Pseudo reg: record first use, last use and number of uses. */ -- cgit v1.1