diff options
author | Bernd Schmidt <crux@pool.informatik.rwth-aachen.de> | 1998-10-02 04:23:37 -0600 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1998-10-02 04:23:37 -0600 |
commit | 09dd11338ac0ffd6917b2e0d10266c8dc221607b (patch) | |
tree | 44e9e33ecd91c8a53ac2bf91c079490dd81504ba | |
parent | 34f89b5f682060e18cc4ba8dfaba8be1d309d5d3 (diff) | |
download | gcc-09dd11338ac0ffd6917b2e0d10266c8dc221607b.zip gcc-09dd11338ac0ffd6917b2e0d10266c8dc221607b.tar.gz gcc-09dd11338ac0ffd6917b2e0d10266c8dc221607b.tar.bz2 |
reload1.c (reload): Break out some more pieces into separate functions.
* reload1.c (reload): Break out some more pieces into separate
functions.
(dump_needs): New function, broken out of reload.
(set_initial_elim_offsets): Likewise.
(init_elim_table): Likewise.
(update_eliminables): Likewise.
From-SVN: r22752
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/reload1.c | 387 |
2 files changed, 222 insertions, 172 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index b9fc7bd..1bdc7e1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ Fri Oct 2 10:51:35 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE> + * reload1.c (reload): Break out some more pieces into separate + functions. + (dump_needs): New function, broken out of reload. + (set_initial_elim_offsets): Likewise. + (init_elim_table): Likewise. + (update_eliminables): Likewise. + * global.c (global_alloc): Delete code to manage the scratch_list. * local-alloc.c (qty_scratch_rtx): Delete. (scratch_block): Delete. diff --git a/gcc/reload1.c b/gcc/reload1.c index 93745e1..6b11bb9 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -348,6 +348,7 @@ static int num_labels; struct hard_reg_n_uses { int regno; int uses; }; +static void dump_needs PROTO((FILE *)); static int calculate_needs_all_insns PROTO((rtx, int)); static int calculate_needs PROTO((int, rtx, rtx, int)); static int find_reload_regs PROTO((int, FILE *)); @@ -367,6 +368,9 @@ static void alter_reg PROTO((int, int)); static void set_label_offsets PROTO((rtx, rtx, int)); static int eliminate_regs_in_insn PROTO((rtx, int)); static void mark_not_eliminable PROTO((rtx, rtx)); +static void set_initial_elim_offsets PROTO((void)); +static void init_elim_table PROTO((void)); +static void update_eliminables PROTO((HARD_REG_SET *)); static int spill_hard_reg PROTO((int, int, FILE *, int)); static void scan_paradoxical_subregs PROTO((rtx)); static int hard_reg_use_compare PROTO((const GENERIC_PTR, const GENERIC_PTR)); @@ -749,46 +753,7 @@ reload (first, global, dumpfile) scan_paradoxical_subregs (PATTERN (insn)); } - /* Does this function require a frame pointer? */ - - frame_pointer_needed = (! flag_omit_frame_pointer -#ifdef EXIT_IGNORE_STACK - /* ?? If EXIT_IGNORE_STACK is set, we will not save - and restore sp for alloca. So we can't eliminate - the frame pointer in that case. At some point, - we should improve this by emitting the - sp-adjusting insns for this case. */ - || (current_function_calls_alloca - && EXIT_IGNORE_STACK) -#endif - || FRAME_POINTER_REQUIRED); - - num_eliminable = 0; - - /* Initialize the table of registers to eliminate. The way we do this - depends on how the eliminable registers were defined. */ -#ifdef ELIMINABLE_REGS - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - { - ep->can_eliminate = ep->can_eliminate_previous - = (CAN_ELIMINATE (ep->from, ep->to) - && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed)); - } -#else - reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous - = ! frame_pointer_needed; -#endif - - /* Count the number of eliminable registers and build the FROM and TO - REG rtx's. Note that code in gen_rtx will cause, e.g., - gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx. - We depend on this. */ - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - { - num_eliminable += ep->can_eliminate; - ep->from_rtx = gen_rtx_REG (Pmode, ep->from); - ep->to_rtx = gen_rtx_REG (Pmode, ep->to); - } + init_elim_table (); num_labels = max_label_num () - get_first_label_num (); @@ -903,12 +868,7 @@ reload (first, global, dumpfile) something_needs_elimination = 0; while (something_changed) { - rtx x; HOST_WIDE_INT starting_frame_size; -#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM - int previous_frame_pointer_needed = frame_pointer_needed; -#endif - static char *reg_class_names[] = REG_CLASS_NAMES; something_changed = 0; bzero ((char *) max_needs, sizeof max_needs); @@ -929,39 +889,8 @@ reload (first, global, dumpfile) starting_frame_size = get_frame_size (); - /* Reset all offsets on eliminable registers to their initial values. */ -#ifdef ELIMINABLE_REGS - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - { - INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset); - ep->previous_offset = ep->offset - = ep->max_offset = ep->initial_offset; - } -#else -#ifdef INITIAL_FRAME_POINTER_OFFSET - INITIAL_FRAME_POINTER_OFFSET (reg_eliminate[0].initial_offset); -#else - if (!FRAME_POINTER_REQUIRED) - abort (); - reg_eliminate[0].initial_offset = 0; -#endif - reg_eliminate[0].previous_offset = reg_eliminate[0].max_offset - = reg_eliminate[0].offset = reg_eliminate[0].initial_offset; -#endif - - num_not_at_initial_offset = 0; - - bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels); - - /* Set a known offset for each forced label to be at the initial offset - of each elimination. We do this because we assume that all - computed jumps occur from a location where each elimination is - at its initial offset. */ - - for (x = forced_labels; x; x = XEXP (x, 1)) - if (XEXP (x, 0)) - set_label_offsets (XEXP (x, 0), NULL_RTX, 1); - + set_initial_elim_offsets (); + /* For each pseudo register that has an equivalent location defined, try to eliminate any eliminable registers (such as the frame pointer) assuming initial offsets for the replacement register, which @@ -1040,25 +969,7 @@ reload (first, global, dumpfile) something_changed = 1; if (dumpfile) - for (i = 0; i < N_REG_CLASSES; i++) - { - if (max_needs[i] > 0) - fprintf (dumpfile, - ";; Need %d reg%s of class %s (for insn %d).\n", - max_needs[i], max_needs[i] == 1 ? "" : "s", - reg_class_names[i], INSN_UID (max_needs_insn[i])); - if (max_nongroups[i] > 0) - fprintf (dumpfile, - ";; Need %d nongroup reg%s of class %s (for insn %d).\n", - max_nongroups[i], max_nongroups[i] == 1 ? "" : "s", - reg_class_names[i], INSN_UID (max_nongroups_insn[i])); - if (max_groups[i] > 0) - fprintf (dumpfile, - ";; Need %d group%s (%smode) of class %s (for insn %d).\n", - max_groups[i], max_groups[i] == 1 ? "" : "s", - mode_name[(int) group_mode[i]], - reg_class_names[i], INSN_UID (max_groups_insn[i])); - } + dump_needs (dumpfile); /* If we have caller-saves, set up the save areas and see if caller-save will need a spill register. */ @@ -1086,84 +997,17 @@ reload (first, global, dumpfile) } } - /* See if anything that happened changes which eliminations are valid. - For example, on the Sparc, whether or not the frame pointer can - be eliminated can depend on what registers have been used. We need - not check some conditions again (such as flag_omit_frame_pointer) - since they can't have changed. */ - - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED) -#ifdef ELIMINABLE_REGS - || ! CAN_ELIMINATE (ep->from, ep->to) -#endif - ) - ep->can_eliminate = 0; - - /* Look for the case where we have discovered that we can't replace - register A with register B and that means that we will now be - trying to replace register A with register C. This means we can - no longer replace register C with register B and we need to disable - such an elimination, if it exists. This occurs often with A == ap, - B == sp, and C == fp. */ - - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - { - struct elim_table *op; - register int new_to = -1; - - if (! ep->can_eliminate && ep->can_eliminate_previous) - { - /* Find the current elimination for ep->from, if there is a - new one. */ - for (op = reg_eliminate; - op < ®_eliminate[NUM_ELIMINABLE_REGS]; op++) - if (op->from == ep->from && op->can_eliminate) - { - new_to = op->to; - break; - } - - /* See if there is an elimination of NEW_TO -> EP->TO. If so, - disable it. */ - for (op = reg_eliminate; - op < ®_eliminate[NUM_ELIMINABLE_REGS]; op++) - if (op->from == new_to && op->to == ep->to) - op->can_eliminate = 0; - } - } - - /* See if any registers that we thought we could eliminate the previous - time are no longer eliminable. If so, something has changed and we - must spill the register. Also, recompute the number of eliminable - registers and see if the frame pointer is needed; it is if there is - no elimination of the frame pointer that we can perform. */ - - frame_pointer_needed = 1; - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) - { - if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM - && ep->to != HARD_FRAME_POINTER_REGNUM) - frame_pointer_needed = 0; - - if (! ep->can_eliminate && ep->can_eliminate_previous) + { + HARD_REG_SET to_spill; + CLEAR_HARD_REG_SET (to_spill); + update_eliminables (&to_spill); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (to_spill, i)) { - ep->can_eliminate_previous = 0; - spill_hard_reg (ep->from, global, dumpfile, 1); + spill_hard_reg (i, global, dumpfile, 1); something_changed = 1; - num_eliminable--; } - } - -#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM - /* If we didn't need a frame pointer last time, but we do now, spill - the hard frame pointer. */ - if (frame_pointer_needed && ! previous_frame_pointer_needed) - { - spill_hard_reg (HARD_FRAME_POINTER_REGNUM, global, dumpfile, 1); - something_changed = 1; - } -#endif + } /* If all needs are met, we win. */ @@ -2253,6 +2097,33 @@ find_reload_regs (global, dumpfile) return something_changed; } +static void +dump_needs (dumpfile) + FILE *dumpfile; +{ + static char *reg_class_names[] = REG_CLASS_NAMES; + int i; + + for (i = 0; i < N_REG_CLASSES; i++) + { + if (max_needs[i] > 0) + fprintf (dumpfile, + ";; Need %d reg%s of class %s (for insn %d).\n", + max_needs[i], max_needs[i] == 1 ? "" : "s", + reg_class_names[i], INSN_UID (max_needs_insn[i])); + if (max_nongroups[i] > 0) + fprintf (dumpfile, + ";; Need %d nongroup reg%s of class %s (for insn %d).\n", + max_nongroups[i], max_nongroups[i] == 1 ? "" : "s", + reg_class_names[i], INSN_UID (max_nongroups_insn[i])); + if (max_groups[i] > 0) + fprintf (dumpfile, + ";; Need %d group%s (%smode) of class %s (for insn %d).\n", + max_groups[i], max_groups[i] == 1 ? "" : "s", + mode_name[(int) group_mode[i]], + reg_class_names[i], INSN_UID (max_groups_insn[i])); + } +} /* Nonzero if, after spilling reg REGNO for non-groups, it will still be possible to find a group if we still need one. */ @@ -3720,6 +3591,178 @@ mark_not_eliminable (dest, x) num_eliminable--; } } + +/* Reset all offsets on eliminable registers to their initial values. */ +static void +set_initial_elim_offsets () +{ + rtx x; + +#ifdef ELIMINABLE_REGS + struct elim_table *ep; + + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + { + INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->initial_offset); + ep->previous_offset = ep->offset + = ep->max_offset = ep->initial_offset; + } +#else +#ifdef INITIAL_FRAME_POINTER_OFFSET + INITIAL_FRAME_POINTER_OFFSET (reg_eliminate[0].initial_offset); +#else + if (!FRAME_POINTER_REQUIRED) + abort (); + reg_eliminate[0].initial_offset = 0; +#endif + reg_eliminate[0].previous_offset = reg_eliminate[0].max_offset + = reg_eliminate[0].offset = reg_eliminate[0].initial_offset; +#endif + + num_not_at_initial_offset = 0; + + bzero ((char *) &offsets_known_at[get_first_label_num ()], num_labels); + + /* Set a known offset for each forced label to be at the initial offset + of each elimination. We do this because we assume that all + computed jumps occur from a location where each elimination is + at its initial offset. */ + + for (x = forced_labels; x; x = XEXP (x, 1)) + if (XEXP (x, 0)) + set_label_offsets (XEXP (x, 0), NULL_RTX, 1); +} + +/* See if anything that happened changes which eliminations are valid. + For example, on the Sparc, whether or not the frame pointer can + be eliminated can depend on what registers have been used. We need + not check some conditions again (such as flag_omit_frame_pointer) + since they can't have changed. */ + +static void +update_eliminables (pset) + HARD_REG_SET *pset; +{ +#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM + int previous_frame_pointer_needed = frame_pointer_needed; +#endif + struct elim_table *ep; + + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + if ((ep->from == HARD_FRAME_POINTER_REGNUM && FRAME_POINTER_REQUIRED) +#ifdef ELIMINABLE_REGS + || ! CAN_ELIMINATE (ep->from, ep->to) +#endif + ) + ep->can_eliminate = 0; + + /* Look for the case where we have discovered that we can't replace + register A with register B and that means that we will now be + trying to replace register A with register C. This means we can + no longer replace register C with register B and we need to disable + such an elimination, if it exists. This occurs often with A == ap, + B == sp, and C == fp. */ + + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + { + struct elim_table *op; + register int new_to = -1; + + if (! ep->can_eliminate && ep->can_eliminate_previous) + { + /* Find the current elimination for ep->from, if there is a + new one. */ + for (op = reg_eliminate; + op < ®_eliminate[NUM_ELIMINABLE_REGS]; op++) + if (op->from == ep->from && op->can_eliminate) + { + new_to = op->to; + break; + } + + /* See if there is an elimination of NEW_TO -> EP->TO. If so, + disable it. */ + for (op = reg_eliminate; + op < ®_eliminate[NUM_ELIMINABLE_REGS]; op++) + if (op->from == new_to && op->to == ep->to) + op->can_eliminate = 0; + } + } + + /* See if any registers that we thought we could eliminate the previous + time are no longer eliminable. If so, something has changed and we + must spill the register. Also, recompute the number of eliminable + registers and see if the frame pointer is needed; it is if there is + no elimination of the frame pointer that we can perform. */ + + frame_pointer_needed = 1; + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + { + if (ep->can_eliminate && ep->from == FRAME_POINTER_REGNUM + && ep->to != HARD_FRAME_POINTER_REGNUM) + frame_pointer_needed = 0; + + if (! ep->can_eliminate && ep->can_eliminate_previous) + { + ep->can_eliminate_previous = 0; + SET_HARD_REG_BIT (*pset, ep->from); + num_eliminable--; + } + } + +#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM + /* If we didn't need a frame pointer last time, but we do now, spill + the hard frame pointer. */ + if (frame_pointer_needed && ! previous_frame_pointer_needed) + SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM); +#endif +} + +/* Initialize the table of registers to eliminate. */ +static void +init_elim_table () +{ + struct elim_table *ep; + + /* Does this function require a frame pointer? */ + + frame_pointer_needed = (! flag_omit_frame_pointer +#ifdef EXIT_IGNORE_STACK + /* ?? If EXIT_IGNORE_STACK is set, we will not save + and restore sp for alloca. So we can't eliminate + the frame pointer in that case. At some point, + we should improve this by emitting the + sp-adjusting insns for this case. */ + || (current_function_calls_alloca + && EXIT_IGNORE_STACK) +#endif + || FRAME_POINTER_REQUIRED); + + num_eliminable = 0; + +#ifdef ELIMINABLE_REGS + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + { + ep->can_eliminate = ep->can_eliminate_previous + = (CAN_ELIMINATE (ep->from, ep->to) + && ! (ep->to == STACK_POINTER_REGNUM && frame_pointer_needed)); + } +#else + reg_eliminate[0].can_eliminate = reg_eliminate[0].can_eliminate_previous + = ! frame_pointer_needed; +#endif + + /* Count the number of eliminable registers and build the FROM and TO + REG rtx's. Note that code in gen_rtx will cause, e.g., + gen_rtx (REG, Pmode, STACK_POINTER_REGNUM) to equal stack_pointer_rtx. + We depend on this. */ + for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++) + { + num_eliminable += ep->can_eliminate; + ep->from_rtx = gen_rtx_REG (Pmode, ep->from); + ep->to_rtx = gen_rtx_REG (Pmode, ep->to); + } +} /* Kick all pseudos out of hard register REGNO. If GLOBAL is nonzero, try to find someplace else to put them. |