From 437a710df01fbb24c920c80ee65803612c2b5ce2 Mon Sep 17 00:00:00 2001 From: Bernd Schmidt Date: Tue, 6 Oct 1998 18:13:49 -0600 Subject: [PATCH] caller-save.c (restore_referenced_regs): Lose mode argument. * caller-save.c (restore_referenced_regs): Lose mode argument. (insert_save): Lose mode argument. (insert_restore): Lose mode argument. (insert_one_insn): Lose mode argument. (save_call_clobbered_regs): Lose mode argument. (setup_save_areas): Take no argument and return void. All callers changed. Don't verify validity of memory addresses. * reload.h (setup_save_ares): Adjust prototype. (save_call_clobbered_regs): Likewise. * reload1.c (delete_caller_save_insns): New function. (caller_save_spill_class): Delete variable. (caller_save_group_size): Delete variable. (reload): Call setup_save_areas and save_call_clobbered_regs in the main loop, before calling calculate_needs_all_insns. Don't call save_call_clobbered_regs after the loop. Call delete_caller_save_insns at the end of an iteration if something changed. Delete code to manage caller_save_spill_class. Emit the final note before setting reload_first_uid. Simplify test that determines whether reload_as_needed gets run. (calculate_needs): Delete code to manage caller_save_spill_class. From-SVN: r22876 --- gcc/ChangeLog | 25 ++++++ gcc/caller-save.c | 92 +++++++--------------- gcc/reload.h | 4 +- gcc/reload1.c | 196 +++++++++++++++------------------------------- 4 files changed, 122 insertions(+), 195 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 85d9497c7df..826efc80de2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +Wed Oct 7 01:08:43 1998 Bernd Schmidt + + * caller-save.c (restore_referenced_regs): Lose mode argument. + (insert_save): Lose mode argument. + (insert_restore): Lose mode argument. + (insert_one_insn): Lose mode argument. + (save_call_clobbered_regs): Lose mode argument. + (setup_save_areas): Take no argument and return void. All callers + changed. + Don't verify validity of memory addresses. + * reload.h (setup_save_ares): Adjust prototype. + (save_call_clobbered_regs): Likewise. + * reload1.c (delete_caller_save_insns): New function. + (caller_save_spill_class): Delete variable. + (caller_save_group_size): Delete variable. + (reload): Call setup_save_areas and save_call_clobbered_regs + in the main loop, before calling calculate_needs_all_insns. + Don't call save_call_clobbered_regs after the loop. + Call delete_caller_save_insns at the end of an iteration if + something changed. + Delete code to manage caller_save_spill_class. + Emit the final note before setting reload_first_uid. + Simplify test that determines whether reload_as_needed gets run. + (calculate_needs): Delete code to manage caller_save_spill_class. + Tue Oct 6 15:42:27 1998 Richard Henderson * collect2.c (main): Initialize ld_file_name. diff --git a/gcc/caller-save.c b/gcc/caller-save.c index acb9ba43241..03fceaebe65 100644 --- a/gcc/caller-save.c +++ b/gcc/caller-save.c @@ -82,14 +82,11 @@ int n_regs_saved; 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, - int)); -static int insert_restore PROTO((rtx, int, int, - enum machine_mode, int, int)); -static int insert_save PROTO((rtx, int, int, - enum machine_mode, int)); +static void restore_referenced_regs PROTO((rtx, rtx, int)); +static int insert_restore PROTO((rtx, int, int, int, int)); +static int insert_save PROTO((rtx, int, int, int)); static void insert_one_insn PROTO((rtx, int, enum rtx_code, - enum machine_mode, rtx, int)); + rtx, int)); /* Initialize for caller-save. @@ -234,13 +231,6 @@ init_save_areas () overestimate slightly (especially if some of these registers are later used as spill registers), but it should not be significant. - Then perform register elimination in the addresses of the save area - locations; return 1 if all eliminated addresses are strictly valid. - We assume that our caller has set up the elimination table to the - worst (largest) possible offsets. - - Set *PCHANGED to 1 if we had to allocate some memory for the save area. - Future work: In the fallback case we should iterate backwards across all possible @@ -253,14 +243,11 @@ init_save_areas () machine independent since they might be saving non-consecutive registers. (imagine caller-saving d0,d1,a0,a1 on the 68k) */ -int -setup_save_areas (pchanged) - int *pchanged; +void +setup_save_areas () { int i, j, k; HARD_REG_SET hard_regs_used; - int ok = 1; - /* Allocate space in the save area for the largest multi-register pseudos first, then work backwards to single register @@ -334,28 +321,16 @@ setup_save_areas (pchanged) regno_save_mem[i+k][1] = adj_offsettable_operand (temp, k * UNITS_PER_WORD); } - *pchanged = 1; } } - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - for (j = 1; j <= MOVE_MAX / UNITS_PER_WORD; j++) - if (regno_save_mem[i][j] != 0) - ok &= strict_memory_address_p (GET_MODE (regno_save_mem[i][j]), - XEXP (eliminate_regs (regno_save_mem[i][j], 0, NULL_RTX), 0)); - - return ok; + return; } -/* Find the places where hard regs are live across calls and save them. - - INSN_MODE is the mode to assign to any insns that we add. This is used - by reload to determine whether or not reloads or register eliminations - need be done on these insns. */ +/* Find the places where hard regs are live across calls and save them. */ void -save_call_clobbered_regs (insn_mode) - enum machine_mode insn_mode; +save_call_clobbered_regs () { rtx insn; int b; @@ -403,7 +378,7 @@ save_call_clobbered_regs (insn_mode) any of them. We must restore them before the insn if so. */ if (n_regs_saved) - restore_referenced_regs (PATTERN (insn), insn, insn_mode, b); + restore_referenced_regs (PATTERN (insn), insn, b); /* NB: the normal procedure is to first enliven any registers set by insn, then deaden any registers that @@ -453,7 +428,7 @@ save_call_clobbered_regs (insn_mode) /* 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 (insn, 1, regno, insn_mode, b); + regno += insert_save (insn, 1, regno, b); /* Put the information for this CALL_INSN on top of what we already had. */ @@ -493,7 +468,7 @@ save_call_clobbered_regs (insn_mode) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno)) regno += insert_restore (insn, GET_CODE (insn) == JUMP_INSN, - regno, insn_mode, + regno, MOVE_MAX / UNITS_PER_WORD, b); } } @@ -557,14 +532,13 @@ clear_reg_live (reg) } /* If any register currently residing in the save area is referenced in X, - which is part of INSN, emit code to restore the register in front of INSN. - INSN_MODE is the mode to assign to any insns that we add. */ + which is part of INSN, emit code to restore the register in front of + INSN. */ static void -restore_referenced_regs (x, insn, insn_mode, block) +restore_referenced_regs (x, insn, block) rtx x; rtx insn; - enum machine_mode insn_mode; int block; { enum rtx_code code = GET_CODE (x); @@ -584,11 +558,11 @@ restore_referenced_regs (x, insn, insn_mode, block) if (regno >= FIRST_PSEUDO_REGISTER && reg_equiv_mem[regno] != 0) restore_referenced_regs (XEXP (reg_equiv_mem[regno], 0), - insn, insn_mode, block); + insn, block); else if (regno >= FIRST_PSEUDO_REGISTER && reg_equiv_address[regno] != 0) restore_referenced_regs (reg_equiv_address[regno], - insn, insn_mode, block); + insn, block); /* Otherwise if this is a hard register, restore any piece of it that is currently saved. */ @@ -603,7 +577,7 @@ restore_referenced_regs (x, insn, insn_mode, block) for (i = regno; i < endregno; i++) if (TEST_HARD_REG_BIT (hard_regs_need_restore, i)) - i += insert_restore (insn, 1, i, insn_mode, saveregs, block); + i += insert_restore (insn, 1, i, saveregs, block); } return; @@ -613,18 +587,17 @@ restore_referenced_regs (x, insn, insn_mode, block) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { if (fmt[i] == 'e') - restore_referenced_regs (XEXP (x, i), insn, insn_mode, block); + restore_referenced_regs (XEXP (x, i), insn, block); else if (fmt[i] == 'E') for (j = XVECLEN (x, i) - 1; j >= 0; j--) - restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode, block); + restore_referenced_regs (XVECEXP (x, i, j), insn, block); } } /* Insert a sequence of insns to restore REGNO. Place these insns in front - of or after INSN (determined by BEFORE_P). INSN_MODE is the mode - to assign to these insns. MAXRESTORE is the maximum number of registers - which should be restored during this call. It should never be less than - 1 since we only work with entire registers. + of or after INSN (determined by BEFORE_P). MAXRESTORE is the maximum + number of registers which should be restored during this call. It should + never be less than 1 since we only work with entire registers. Note that we have verified in init_caller_save that we can do this with a simple SET, so use it. Set INSN_CODE to what we save there @@ -635,11 +608,10 @@ restore_referenced_regs (x, insn, insn_mode, block) Return the extra number of registers saved. */ static int -insert_restore (insn, before_p, regno, insn_mode, maxrestore, block) +insert_restore (insn, before_p, regno, maxrestore, block) rtx insn; int before_p; int regno; - enum machine_mode insn_mode; int maxrestore; int block; { @@ -697,7 +669,7 @@ insert_restore (insn, before_p, regno, insn_mode, maxrestore, block) break; } - insert_one_insn (insn, before_p, code, insn_mode, pat, block); + insert_one_insn (insn, before_p, code, pat, block); /* Tell our callers how many extra registers we saved/restored */ return numregs - 1; @@ -705,11 +677,10 @@ insert_restore (insn, before_p, regno, insn_mode, maxrestore, block) /* Like insert_restore, but emit code to save REGNO. */ static int -insert_save (insn, before_p, regno, insn_mode, block) +insert_save (insn, before_p, regno, block) rtx insn; int before_p; int regno; - enum machine_mode insn_mode; int block; { rtx pat = NULL_RTX; @@ -767,20 +738,18 @@ insert_save (insn, before_p, regno, insn_mode, block) break; } - insert_one_insn (insn, before_p, code, insn_mode, pat, block); + insert_one_insn (insn, before_p, code, pat, block); /* Tell our callers how many extra registers we saved/restored */ return numregs - 1; } -/* Emit one insn, set the code and mode, and update basic block - boundaries. */ +/* Emit one insn, set the code, and update basic block boundaries. */ static void -insert_one_insn (insn, before_p, code, mode, pat, block) +insert_one_insn (insn, before_p, code, pat, block) rtx insn; int before_p; enum rtx_code code; - enum machine_mode mode; rtx pat; int block; { @@ -811,7 +780,6 @@ insert_one_insn (insn, before_p, code, mode, pat, block) if (insert_point == basic_block_end[block]) basic_block_end[block] = new; } - - PUT_MODE (new, mode); + INSN_CODE (new) = code; } diff --git a/gcc/reload.h b/gcc/reload.h index 58f6be3a101..e86296cb87c 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -327,7 +327,7 @@ extern void init_caller_save PROTO((void)); extern void init_save_areas PROTO((void)); /* Allocate save areas for any hard registers that might need saving. */ -extern int setup_save_areas PROTO((int *)); +extern void setup_save_areas PROTO((void)); /* Find the places where hard regs are live across calls and save them. */ -extern void save_call_clobbered_regs PROTO((enum machine_mode)); +extern void save_call_clobbered_regs PROTO((void)); diff --git a/gcc/reload1.c b/gcc/reload1.c index 8b15e0e8e8d..cea782188a8 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -371,6 +371,7 @@ static void count_possible_groups PROTO((int *, enum machine_mode *, static int modes_equiv_for_class_p PROTO((enum machine_mode, enum machine_mode, enum reg_class)); +static void delete_caller_save_insns PROTO((rtx)); static void spill_failure PROTO((rtx)); static int new_spill_reg PROTO((int, int, int *, int *, int, FILE *)); @@ -566,10 +567,6 @@ static int something_needs_reloads; /* Set during calculate_needs if an insn needs register elimination. */ static int something_needs_elimination; -/* Indicate whether caller saves need a spill register. */ -static enum reg_class caller_save_spill_class = NO_REGS; -static int caller_save_group_size = 1; - /* For each class, number of reload regs needed in that class. This is the maximum over all insns of the needs in that class of the individual insn. */ @@ -644,12 +641,13 @@ reload (first, global, dumpfile) reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0); + /* Make sure that the last insn in the chain + is not something that needs reloading. */ + emit_note (NULL_PTR, NOTE_INSN_DELETED); + /* Enable find_equiv_reg to distinguish insns made by reload. */ reload_first_uid = get_max_uid (); - caller_save_spill_class = NO_REGS; - caller_save_group_size = 1; - for (i = 0; i < N_REG_CLASSES; i++) basic_block_needs[i] = 0; @@ -687,10 +685,6 @@ reload (first, global, dumpfile) regs_ever_live[i] = 1; } - /* Make sure that the last insn in the chain - is not something that needs reloading. */ - emit_note (NULL_PTR, NOTE_INSN_DELETED); - /* Find all the pseudo registers that didn't get hard regs but do have known equivalent constants or memory slots. These include parameters (known equivalent to parameter slots) @@ -986,18 +980,26 @@ reload (first, global, dumpfile) } } + /* Insert code to save and restore call-clobbered hard regs + around calls. Tell if what mode to use so that we will process + those insns in reload_as_needed if we have to. */ + + if (caller_save_needed) + setup_save_areas (); + + if (starting_frame_size != get_frame_size ()) + something_changed = 1; + /* If we allocated another pseudo to the stack, redo elimination bookkeeping. */ if (something_changed) continue; - /* If caller-saves needs a group, initialize the group to include - the size and mode required for caller-saves. */ - - if (caller_save_group_size > 1) + if (caller_save_needed) { - group_mode[(int) caller_save_spill_class] = Pmode; - group_size[(int) caller_save_spill_class] = caller_save_group_size; + save_call_clobbered_regs (); + /* That might have allocated new insn_chain structures. */ + reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0); } something_changed |= calculate_needs_all_insns (first, global); @@ -1010,32 +1012,6 @@ reload (first, global, dumpfile) if (dumpfile) dump_needs (dumpfile); - /* If we have caller-saves, set up the save areas and see if caller-save - will need a spill register. */ - - if (caller_save_needed) - { - /* Set the offsets for setup_save_areas. */ - for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; - ep++) - ep->previous_offset = ep->max_offset; - - if ( ! setup_save_areas (&something_changed) - && caller_save_spill_class == NO_REGS) - { - /* The class we will need depends on whether the machine - supports the sum of two registers for an address; see - find_address_reloads for details. */ - - caller_save_spill_class - = (double_reg_address_ok ? reload_address_index_reg_class - : reload_address_base_reg_class); - caller_save_group_size - = CLASS_MAX_NREGS (caller_save_spill_class, Pmode); - something_changed = 1; - } - } - { HARD_REG_SET to_spill; CLEAR_HARD_REG_SET (to_spill); @@ -1098,6 +1074,9 @@ reload (first, global, dumpfile) something_changed |= find_reload_regs (global, dumpfile); if (failure) goto failed; + + if (something_changed) + delete_caller_save_insns (first); } /* If global-alloc was run, notify it of any register eliminations we have @@ -1107,15 +1086,6 @@ reload (first, global, dumpfile) if (ep->can_eliminate) mark_elimination (ep->from, ep->to); - /* Insert code to save and restore call-clobbered hard regs - around calls. Tell if what mode to use so that we will process - those insns in reload_as_needed if we have to. */ - - if (caller_save_needed) - save_call_clobbered_regs (num_eliminable ? QImode - : caller_save_spill_class != NO_REGS ? HImode - : VOIDmode); - /* If a pseudo has no hard reg, delete the insns that made the equivalence. If that insn didn't set the register (i.e., it copied the register to memory), just delete that insn instead of the equivalencing insn plus @@ -1141,9 +1111,7 @@ reload (first, global, dumpfile) by generating move instructions to move the must-be-register values into or out of the reload registers. */ - if (something_needs_reloads || something_needs_elimination - || (caller_save_needed && num_eliminable) - || caller_save_spill_class != NO_REGS) + if (something_needs_reloads || something_needs_elimination) reload_as_needed (first, global); /* If we were able to eliminate the frame pointer, show that it is no @@ -1384,13 +1352,7 @@ calculate_needs_all_insns (first, global) something_needs_elimination = 1; } - /* If this insn has no reloads, we need not do anything except - in the case of a CALL_INSN when we have caller-saves and - caller-save needs reloads. */ - - if (n_reloads != 0 - || (GET_CODE (insn) == CALL_INSN - && caller_save_spill_class != NO_REGS)) + if (n_reloads != 0) something_changed |= calculate_needs (this_block, insn, avoid_return_reg, global); } @@ -1650,75 +1612,6 @@ calculate_needs (this_block, insn, avoid_return_reg, global) insn_needs.other_addr.groups[i]); } - /* If this is a CALL_INSN and caller-saves will need - a spill register, act as if the spill register is - needed for this insn. However, the spill register - can be used by any reload of this insn, so we only - need do something if no need for that class has - been recorded. - - The assumption that every CALL_INSN will trigger a - caller-save is highly conservative, however, the number - of cases where caller-saves will need a spill register but - a block containing a CALL_INSN won't need a spill register - of that class should be quite rare. - - If a group is needed, the size and mode of the group will - have been set up at the beginning of this loop. */ - - if (GET_CODE (insn) == CALL_INSN - && caller_save_spill_class != NO_REGS) - { - int j; - /* See if this register would conflict with any reload that - needs a group or any reload that needs a nongroup. */ - int nongroup_need = 0; - int *caller_save_needs; - - for (j = 0; j < n_reloads; j++) - if (reg_classes_intersect_p (caller_save_spill_class, - reload_reg_class[j]) - && ((CLASS_MAX_NREGS - (reload_reg_class[j], - (GET_MODE_SIZE (reload_outmode[j]) - > GET_MODE_SIZE (reload_inmode[j])) - ? reload_outmode[j] : reload_inmode[j]) - > 1) - || reload_nongroup[j])) - { - nongroup_need = 1; - break; - } - - caller_save_needs - = (caller_save_group_size > 1 - ? insn_needs.other.groups - : insn_needs.other.regs[nongroup_need]); - - if (caller_save_needs[(int) caller_save_spill_class] == 0) - { - register enum reg_class *p - = reg_class_superclasses[(int) caller_save_spill_class]; - - caller_save_needs[(int) caller_save_spill_class]++; - - while (*p != LIM_REG_CLASSES) - caller_save_needs[(int) *p++] += 1; - } - - /* Show that this basic block will need a register of - this class. */ - - if (global - && ! (basic_block_needs[(int) caller_save_spill_class] - [this_block])) - { - basic_block_needs[(int) caller_save_spill_class] - [this_block] = 1; - something_changed = 1; - } - } - /* If this insn stores the value of a function call, and that value is in a register that has been spilled, and if the insn needs a reload in a class @@ -2166,6 +2059,47 @@ dump_needs (dumpfile) } } +/* Delete all insns that were inserted by emit_caller_save_insns during + this iteration. */ +static void +delete_caller_save_insns (first) + rtx first; +{ + rtx insn = first; + int b = -1; + + while (insn != 0) + { + if (b + 1 != n_basic_blocks + && basic_block_head[b + 1] == insn) + b++; + + while (insn != 0 && INSN_UID (insn) >= reload_first_uid) + { + rtx next = NEXT_INSN (insn); + rtx prev = PREV_INSN (insn); + + if (insn == basic_block_head[b]) + basic_block_head[b] = next; + if (insn == basic_block_end[b]) + basic_block_end[b] = prev; + + if (next != 0) + PREV_INSN (next) = prev; + if (prev != 0) + NEXT_INSN (prev) = next; + + insn = next; + + if (b + 1 != n_basic_blocks + && basic_block_head[b + 1] == insn) + b++; + } + if (insn != 0) + insn = NEXT_INSN (insn); + } +} + /* Nonzero if, after spilling reg REGNO for non-groups, it will still be possible to find a group if we still need one. */