diff options
Diffstat (limited to 'gcc')
-rwxr-xr-x | gcc/Makefile.in | 23 | ||||
-rwxr-xr-x | gcc/final.c | 23 | ||||
-rwxr-xr-x | gcc/flags.h | 11 | ||||
-rwxr-xr-x | gcc/global.c | 531 | ||||
-rwxr-xr-x | gcc/range.c | 1931 | ||||
-rwxr-xr-x | gcc/range.h | 49 | ||||
-rwxr-xr-x | gcc/regs.h | 17 | ||||
-rwxr-xr-x | gcc/toplev.c | 87 |
8 files changed, 75 insertions, 2597 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 8b8deef..bcda03d 100755 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -611,7 +611,6 @@ OBJS = toplev.o version.o tree.o print-tree.o stor-layout.o fold-const.o \ insn-peep.o reorg.o $(SCHED_PREFIX)sched.o final.o recog.o reg-stack.o \ insn-opinit.o insn-recog.o insn-extract.o insn-output.o insn-emit.o \ $(CYGNUS-LOCAL-lcm) lcm.o \ - $(CYGNUS-LOCAL-range) range.o \ insn-attrtab.o $(out_object_file) getpwd.o $(EXTRA_OBJS) convert.o \ mbchar.o dyn-string.o splay-tree.o graph.o sbitmap.o resource.o @@ -639,7 +638,6 @@ STAGESTUFF = *$(objext) insn-flags.h insn-config.h insn-codes.h \ $(EXTRA_PROGRAMS) gcc-cross$(exeext) \ $(CCCP)$(exeext) cc1obj$(exeext) enquire$(exeext) \ specs underscore.c \ - $(CYGNUS-LOCAL-range) *.range \ *.greg *.lreg *.combine *.flow *.cse *.jump *.rtl *.tree *.loop \ *.dbr *.jump2 *.sched *.cse2 *.sched2 *.stack *.gcse \ *.[si] libcpp.a \ @@ -1335,16 +1333,16 @@ stor-layout.o : stor-layout.c $(CONFIG_H) system.h $(TREE_H) flags.h \ function.h $(EXPR_H) $(RTL_H) toplev.h except.h fold-const.o : fold-const.c $(CONFIG_H) system.h $(TREE_H) flags.h toplev.h \ $(RTL_H) -# CYGNUS LOCAL live range + toplev.o : toplev.c $(CONFIG_H) system.h $(TREE_H) $(RTL_H) \ - flags.h input.h insn-attr.h defaults.h output.h range.h \ + flags.h input.h insn-attr.h defaults.h output.h \ insn-codes.h insn-config.h $(RECOG_H) Makefile toplev.h \ dwarf2out.h $(EXPR_H) \ $(lang_options_files) $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ -DTARGET_NAME=\"$(target_alias)\" \ -c `echo $(srcdir)/toplev.c | sed 's,^\./,,'` -# END CYGNUS LOCAL + rtl.o : rtl.c $(CONFIG_H) system.h $(RTL_H) bitmap.h @@ -1420,14 +1418,8 @@ local-alloc.o : local-alloc.c $(CONFIG_H) system.h $(RTL_H) flags.h \ insn-attr.h toplev.h bitmap.o : bitmap.c $(CONFIG_H) system.h $(RTL_H) flags.h $(BASIC_BLOCK_H) \ $(REGS_H) -# CYGNUS LOCAL live range -range.o : range.c $(CONFIG_H) $(RTL_H) $(TREE_H) $(BASIC_BLOCK_H) flags.h \ - $(REGS_H) hard-reg-set.h insn-config.h recog.h output.h expr.h insn-codes.h \ - range.h function.h except.h system.h toplev.h global.o : global.c $(CONFIG_H) system.h $(RTL_H) flags.h reload.h \ - $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h \ - range.h -#END CYGNUS LOCAL + $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h insn-config.h output.h toplev.h varray.o : varray.c $(CONFIG_H) system.h varray.h $(RTL_H) $(TREE_H) bitmap.h reload.o : reload.c $(CONFIG_H) system.h $(RTL_H) flags.h output.h $(EXPR_H) \ @@ -1450,12 +1442,10 @@ regmove.o : regmove.c $(CONFIG_H) system.h $(RTL_H) insn-config.h \ $(SCHED_PREFIX)sched.o : $(SCHED_PREFIX)sched.c $(CONFIG_H) system.h $(RTL_H) \ $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h flags.h insn-config.h \ insn-attr.h toplev.h recog.h -# CYGNUS LOCAL live range final.o : final.c $(CONFIG_H) system.h $(RTL_H) $(TREE_H) flags.h $(REGS_H) \ $(RECOG_H) conditions.h insn-config.h insn-attr.h except.h real.h output.h \ hard-reg-set.h insn-flags.h insn-codes.h defaults.h \ - toplev.h reload.h dwarf2out.h range.h -# END CYGNUS LOCAL + toplev.h reload.h dwarf2out.h recog.o : recog.c $(CONFIG_H) system.h $(RTL_H) \ $(REGS_H) $(RECOG_H) hard-reg-set.h flags.h insn-config.h insn-attr.h \ insn-flags.h insn-codes.h real.h toplev.h @@ -1990,9 +1980,6 @@ mostlyclean: lang.mostlyclean -rm -f c-parse.c c-parse.output c-parse.h -rm -f cexp.c cexp.output $(BUILD_SO1) $(BUILD_SO2) $(BUILD_SO3) # END CYGNUS LOCAL -# CYGNUS LOCAL: live range - -rm -f *.range */*.range -# END CYGNUS LOCAL -rm -f *.bp */*.bp # Delete all files made by compilation diff --git a/gcc/final.c b/gcc/final.c index 2f54102..96836ed 100755 --- a/gcc/final.c +++ b/gcc/final.c @@ -66,7 +66,6 @@ Boston, MA 02111-1307, USA. */ #include "reload.h" /* CYGNUS LOCAL LRS */ #include "function.h" -#include "range.h" #include "bitmap.h" #include "obstack.h" @@ -1541,28 +1540,6 @@ final_scan_insn (insn, file, optimize, prescan, nopeepholes) break; } - /* CYGNUS LOCAL LRS */ - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_START) - { -#ifdef ASM_COMMENT_START - if (flag_debug_asm) - live_range_print (file, NOTE_RANGE_INFO (insn), "\t", - ASM_COMMENT_START); -#endif - break; - } - - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_END) - { -#ifdef ASM_COMMENT_START - if (flag_debug_asm) - fprintf (file, "\t%s range #%d end\n", ASM_COMMENT_START, - RANGE_INFO_UNIQUE (NOTE_RANGE_INFO (insn))); -#endif - break; - } - /* END CYGNUS LOCAL */ - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PROLOGUE_END) { #ifdef FUNCTION_END_PROLOGUE diff --git a/gcc/flags.h b/gcc/flags.h index 77f839b..d817cdb 100755 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -430,17 +430,6 @@ extern int flag_unaligned_struct_hack; extern int flag_unaligned_pointers; /* END CYGNUS LOCAL */ -/* CYGNUS LOCAL LRS */ -/* Enable live range splitting. */ -extern int flag_live_range; - -/* Enable/disable using GDB extensions for denoting live ranges. */ -extern int flag_live_range_gdb; - -/* Create scoping blocks for live ranges when debugging. */ -extern int flag_live_range_scope; -/* END CYGNUS LOCAL LRS */ - /* Tag all structures with __attribute__(packed) */ extern int flag_pack_struct; diff --git a/gcc/global.c b/gcc/global.c index 03b7288..9255b36 100755 --- a/gcc/global.c +++ b/gcc/global.c @@ -34,7 +34,6 @@ Boston, MA 02111-1307, USA. */ #include "toplev.h" /* CYGNUS LOCAL live range */ #include "obstack.h" -#include "range.h" #define obstack_chunk_alloc xmalloc #define obstack_chunk_free free @@ -110,20 +109,6 @@ static int *allocno_size; static int *reg_may_share; -/* CYGNUS LOCAL live range */ -/* Indexed by (pseudo) reg number, gives the hard registers that where - allocated by any register which is split into distinct live ranges. - We try to use the same registers, to cut down on copies made. */ - -static HARD_REG_SET **reg_live_ranges; - -/* Copy of reg_renumber to reinitialize it if we need to run register - allocation a second time due to some live range copy registers - not getting hard registers. */ - -static short *save_reg_renumber; -/* END CYGNUS LOCAL */ - /* Define the number of bits in each element of `conflicts' and what type that element has. We use the largest integer format on the host machine. */ @@ -155,12 +140,6 @@ static int allocno_row_words; (conflicts[(I) * allocno_row_words + (J) / INT_BITS] \ |= ((INT_TYPE) 1 << ((J) % INT_BITS))) -/* CYGNUS LOCAL LRS */ -#define CLEAR_CONFLICT(I, J) \ - (conflicts[(I) * allocno_row_words + (J) / INT_BITS] \ - &= ~ ((INT_TYPE) 1 << ((J) % INT_BITS))) -/* END CYGNUS LOCAL */ - /* Set of hard regs currently live (during scan of all insns). */ static HARD_REG_SET hard_regs_live; @@ -301,9 +280,7 @@ static void dump_conflicts PROTO((FILE *)); static void reg_becomes_live PROTO((rtx, rtx)); static void reg_dies PROTO((int, enum machine_mode)); static void build_insn_chain PROTO((rtx)); -/* CYGNUS LOCAL live range */ -static void undo_live_range PROTO((FILE *)); -static void global_init PROTO((FILE *, int)); +static void global_init PROTO((FILE *)); /* Perform allocation of pseudo-registers not allocated by local_alloc. FILE is a file to output debugging information on, @@ -314,19 +291,10 @@ static void global_init PROTO((FILE *, int)); /* Initialize for allocating registers. */ static void -global_init (file, alloc_p) - FILE *file; - int alloc_p; +global_init (FILE *file) { -#ifdef ELIMINABLE_REGS static struct {int from, to; } eliminables[] = ELIMINABLE_REGS; -#endif - int need_fp - = (! flag_omit_frame_pointer -#ifdef EXIT_IGNORE_STACK - || (current_function_calls_alloca && EXIT_IGNORE_STACK) -#endif - || FRAME_POINTER_REQUIRED); + int need_fp = (!flag_omit_frame_pointer || FRAME_POINTER_REQUIRED); register size_t i; rtx x; @@ -337,64 +305,30 @@ global_init (file, alloc_p) are safe to use only within a basic block. */ CLEAR_HARD_REG_SET (no_global_alloc_regs); -#ifdef OVERLAPPING_REGNO_P - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (OVERLAPPING_REGNO_P (i)) - SET_HARD_REG_BIT (no_global_alloc_regs, i); -#endif /* Build the regset of all eliminable registers and show we can't use those that we already know won't be eliminated. */ -#ifdef ELIMINABLE_REGS - for (i = 0; i < sizeof eliminables / sizeof eliminables[0]; i++) + + for (i = 0; i < sizeof eliminables / sizeof eliminables[0]; i++) { - SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from); + SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from); - if (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to) - || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp)) - SET_HARD_REG_BIT (no_global_alloc_regs, eliminables[i].from); + if (!CAN_ELIMINATE(eliminables[i].from, eliminables[i].to) + || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp)) + SET_HARD_REG_BIT (no_global_alloc_regs, eliminables[i].from); } -#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM - SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM); - if (need_fp) - SET_HARD_REG_BIT (no_global_alloc_regs, HARD_FRAME_POINTER_REGNUM); -#endif - -#else - SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM); - if (need_fp) - SET_HARD_REG_BIT (no_global_alloc_regs, FRAME_POINTER_REGNUM); -#endif /* Track which registers have already been used. Start with registers explicitly in the rtl, then registers allocated by local register allocation. */ CLEAR_HARD_REG_SET (regs_used_so_far); -#ifdef LEAF_REGISTERS - /* If we are doing the leaf function optimization, and this is a leaf - function, it means that the registers that take work to save are those - that need a register window. So prefer the ones that can be used in - a leaf function. */ - { - char *cheap_regs; - static char leaf_regs[] = LEAF_REGISTERS; - - if (only_leaf_regs_used () && leaf_function_p ()) - cheap_regs = leaf_regs; - else - cheap_regs = call_used_regs; - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (regs_ever_live[i] || cheap_regs[i]) - SET_HARD_REG_BIT (regs_used_so_far, i); - } -#else + /* We consider registers that do not have to be saved over calls as if they were already used since there is no cost in using them. */ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (regs_ever_live[i] || call_used_regs[i]) SET_HARD_REG_BIT (regs_used_so_far, i); -#endif for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++) if (reg_renumber[i] >= 0) @@ -403,97 +337,24 @@ global_init (file, alloc_p) /* Establish mappings from register number to allocation number and vice versa. In the process, count the allocnos. */ - if (alloc_p) - reg_allocno = (int *) obstack_alloc (&global_obstack, - max_regno * sizeof (int)); + reg_allocno = (int *) obstack_alloc (&global_obstack, max_regno * sizeof (int)); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) reg_allocno[i] = -1; /* Initialize the shared-hard-reg mapping from the list of pairs that may share. */ - if (alloc_p) - { - reg_may_share = (int *) obstack_alloc (&global_obstack, - max_regno * sizeof (int)); - bzero ((char *) reg_may_share, max_regno * sizeof (int)); - for (x = regs_may_share; x; x = XEXP (XEXP (x, 1), 1)) - { - int r1 = REGNO (XEXP (x, 0)); - int r2 = REGNO (XEXP (XEXP (x, 1), 0)); - if (r1 > r2) - reg_may_share[r1] = r2; - else - reg_may_share[r2] = r1; - } - /* Initialize the register sets for registers split into distinct live - ranges. */ - if (live_range_list) + reg_may_share = (int *) obstack_alloc (&global_obstack, max_regno * sizeof (int)); + bzero ((char *) reg_may_share, max_regno * sizeof (int)); + for (x = regs_may_share; x; x = XEXP (XEXP (x, 1), 1)) { - rtx range; - - reg_live_ranges = (HARD_REG_SET **) - obstack_alloc (&global_obstack, max_regno * sizeof (HARD_REG_SET *)); - bzero ((char *)reg_live_ranges, max_regno * sizeof (HARD_REG_SET *)); - - for (range = live_range_list; range; range = XEXP (range, 1)) - { - rtx range_start = XEXP (range, 0); - rtx rinfo = NOTE_RANGE_INFO (range_start); - - for (i = 0; i < RANGE_INFO_NUM_REGS (rinfo); i++) - { - int old_regno = RANGE_REG_PSEUDO (rinfo, i); - int new_regno = RANGE_REG_COPY (rinfo, i); - HARD_REG_SET *old_regset = reg_live_ranges[old_regno]; - HARD_REG_SET *new_regset = reg_live_ranges[new_regno]; - - /* Copy registers that don't need either copyins or - copyouts don't need to try to share registers */ - if (!RANGE_REG_COPY_FLAGS (rinfo, i)) - continue; - - if (old_regset == (HARD_REG_SET *)0 - && new_regset == (HARD_REG_SET *)0) - { - reg_live_ranges[old_regno] - = reg_live_ranges[new_regno] - = new_regset - = (HARD_REG_SET *) obstack_alloc (&global_obstack, - sizeof (HARD_REG_SET)); - SET_HARD_REG_SET (*new_regset); - } - else if (old_regset != (HARD_REG_SET *)0 - && new_regset == (HARD_REG_SET *)0) - { - reg_live_ranges[new_regno] = new_regset = old_regset; - } - else if (old_regset == (HARD_REG_SET *)0 - && new_regset != (HARD_REG_SET *)0) - { - reg_live_ranges[old_regno] = new_regset; - } - else if (old_regset != new_regset) - { - int j; - for (j = 0; j < max_regno; j++) - { - if (reg_live_ranges[j] == old_regset) - reg_live_ranges[j] = new_regset; - } - } - - if (reg_renumber[old_regno] >= 0) - CLEAR_HARD_REG_BIT (*new_regset, reg_renumber[old_regno]); - - if (reg_renumber[new_regno] >= 0) - CLEAR_HARD_REG_BIT (*new_regset, reg_renumber[new_regno]); - } - } - } - else - reg_live_ranges = (HARD_REG_SET **)0; + int r1 = REGNO (XEXP (x, 0)); + int r2 = REGNO (XEXP (XEXP (x, 1), 0)); + if (r1 > r2) + reg_may_share[r1] = r2; + else + reg_may_share[r2] = r1; } for (i = FIRST_PSEUDO_REGISTER; i < (size_t) max_regno; i++) @@ -516,20 +377,11 @@ global_init (file, alloc_p) else reg_allocno[i] = -1; - if (alloc_p) - { - allocno_reg = (int *) obstack_alloc (&global_obstack, - max_allocno * sizeof (int)); - allocno_size = (int *) obstack_alloc (&global_obstack, - max_allocno * sizeof (int)); - allocno_calls_crossed = (int *) obstack_alloc (&global_obstack, - (max_allocno - * sizeof (int))); - allocno_n_refs = (int *) obstack_alloc (&global_obstack, - max_allocno * sizeof (int)); - allocno_live_length = (int *) obstack_alloc (&global_obstack, - max_allocno * sizeof (int)); - } + allocno_reg = (int *) obstack_alloc (&global_obstack, max_allocno * sizeof (int)); + allocno_size = (int *) obstack_alloc (&global_obstack, max_allocno * sizeof (int)); + allocno_calls_crossed = (int *) obstack_alloc (&global_obstack, (max_allocno * sizeof (int))); + allocno_n_refs = (int *) obstack_alloc (&global_obstack, max_allocno * sizeof (int)); + allocno_live_length = (int *) obstack_alloc (&global_obstack, max_allocno * sizeof (int)); bzero ((char *) allocno_size, max_allocno * sizeof (int)); bzero ((char *) allocno_calls_crossed, max_allocno * sizeof (int)); @@ -575,8 +427,7 @@ global_init (file, alloc_p) /* Allocate the space for the conflict and preference tables and initialize them. */ - if (alloc_p) - { + hard_reg_conflicts = (HARD_REG_SET *) obstack_alloc (&global_obstack, max_allocno * sizeof (HARD_REG_SET)); @@ -608,7 +459,6 @@ global_init (file, alloc_p) allocnos_live = (INT_TYPE *) obstack_alloc (&global_obstack, (allocno_row_words * sizeof (INT_TYPE))); - } bzero ((char *) hard_reg_conflicts, max_allocno * sizeof (HARD_REG_SET)); bzero ((char *) hard_reg_preferences, max_allocno * sizeof (HARD_REG_SET)); @@ -675,27 +525,22 @@ global_init (file, alloc_p) if (file) { - fprintf (file, "\nPass %d registers to be allocated in sorted order:\n", - (alloc_p) ? 1 : 2); + fprintf (file, "\nRegisters to be allocated in sorted order:\n"); for (i = 0; i < max_allocno; i++) { int r = allocno_order[i]; fprintf (file, - "Register %d, refs = %d, live_length = %d, size = %d%s%s\n", + "Register %d, refs = %d, live_length = %d, size = %d\n", allocno_reg[r], allocno_n_refs[r], - allocno_live_length[r], allocno_size[r], - ((REG_N_RANGE_CANDIDATE_P (allocno_reg[r])) - ? ", live range candidate" : ""), - ((REG_N_RANGE_COPY_P (allocno_reg[r])) - ? ", live range copy" : "")); + allocno_live_length[r], allocno_size[r]); } putc ('\n', file); } prune_preferences (); - if (file) - dump_conflicts (file); + if (file) + dump_conflicts (file); } } @@ -707,85 +552,51 @@ global_init (file, alloc_p) and we must not do any more for this function. */ int -global_alloc (file) - FILE *file; +global_alloc (FILE *file) { - register int i; - int copy_not_alloc_p; - int loop_p = TRUE; - int pass; - int retval; + register int i; + int pass; + int retval; - /* Set up the memory pool we will use here. */ - gcc_obstack_init (&global_obstack); + /* Set up the memory pool we will use here. */ + gcc_obstack_init (&global_obstack); - /* If we are splitting live ranges, save the initial value of the - reg_renumber array. */ - if (flag_live_range) + global_init (file); + + for (i = 0; i < (size_t) max_allocno; i++) { - save_reg_renumber = (short *) obstack_alloc (&global_obstack, - sizeof (short) * max_regno); - for (i = max_regno-1; i >= 0; i--) - save_reg_renumber[i] = reg_renumber[i]; + if (reg_renumber[allocno_reg[allocno_order[i]]] < 0 + && REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0) + { + int order = allocno_order[i]; + int regno = allocno_reg[order]; + + /* If we have more than one register class, + first try allocating in the class that is cheapest + for this pseudo-reg. If that fails, try any reg. */ + if (reg_renumber[regno] < 0 && N_REG_CLASSES > 1) + find_reg (order, 0, 0, 0, 0); + + if (reg_renumber[regno] < 0 + && reg_alternate_class (regno) != NO_REGS) + find_reg (order, 0, 1, 0, 0); + } } + /* Do the reloads now while the allocno data still exist, so that we can + try to assign new hard regs to any pseudo regs that are spilled. */ - /* Try to allocate everything on the first pass. If we are doing live - range splitting, and one or more of the register that were split into live - ranges did not get a register assigned, undo the live range for that - register, and redo the allocation in a second pass. */ - for (pass = 0; pass < 2 && loop_p; pass++) - { - /* Do all of the initialization, allocations only on the first pass. */ - global_init (file, (pass == 0)); - - copy_not_alloc_p = FALSE; - - for (i = 0; i < (size_t) max_allocno; i++) - if (reg_renumber[allocno_reg[allocno_order[i]]] < 0 - && REG_LIVE_LENGTH (allocno_reg[allocno_order[i]]) >= 0) - { - int order = allocno_order[i]; - int regno = allocno_reg[order]; - - /* If we have more than one register class, - first try allocating in the class that is cheapest - for this pseudo-reg. If that fails, try any reg. */ - if (reg_renumber[regno] < 0 && N_REG_CLASSES > 1) - find_reg (order, 0, 0, 0, 0); - - if (reg_renumber[regno] < 0 - && reg_alternate_class (regno) != NO_REGS) - find_reg (order, 0, 1, 0, 0); + /* We need to eliminate regs even if there is no rtl code, + for the sake of debugging information. */ - if (REG_N_RANGE_COPY_P (regno) && reg_renumber[regno] < 0) - copy_not_alloc_p = 1; - } + build_insn_chain (get_insns ()); + retval = reload (get_insns (), 1, file); - if (copy_not_alloc_p) - undo_live_range (file); - else - loop_p = FALSE; - - } - - /* Do the reloads now while the allocno data still exist, so that we can - try to assign new hard regs to any pseudo regs that are spilled. */ + obstack_free (&global_obstack, NULL); + free (conflicts); -#if 0 /* We need to eliminate regs even if there is no rtl code, - for the sake of debugging information. */ - if (n_basic_blocks > 0) -#endif - { - build_insn_chain (get_insns ()); - retval = reload (get_insns (), 1, file); - } - - obstack_free (&global_obstack, NULL); - free (conflicts); - return retval; + return retval; } -/* END CYGNUS LOCAL */ /* Sort predicate for ordering the allocnos. Returns -1 (1) if *v1 should be allocated before (after) *v2. */ @@ -796,16 +607,9 @@ allocno_compare (v1p, v2p) const GENERIC_PTR v2p; { int v1 = *(int *)v1p, v2 = *(int *)v2p; - /* CYGNUS LOCAL live range */ register int pri1; register int pri2; - /* Favor regs referenced in live ranges over other registers */ - pri1 = REG_N_RANGE_COPY_P (allocno_reg [v1]); - pri2 = REG_N_RANGE_COPY_P (allocno_reg [v2]); - if (pri2 - pri1) - return pri2 - pri1; - /* Note that the quotient will never be bigger than the value of floor_log2 times the maximum number of times a register can occur in one insn (surely less than 100). @@ -824,162 +628,8 @@ allocno_compare (v1p, v2p) /* If regs are equally good, sort by allocno, so that the results of qsort leave nothing to chance. */ return v1 - v2; - /* END CYGNUS LOCAL */ } -/* CYGNUS LOCAL live range */ -/* If there were any live_range copies that were not allocated registers, - replace them with the original register, so that we don't get code copying - a stack location to a register, then into a stack location for the live - range. */ - -static void -undo_live_range (file) - FILE *file; -{ - rtx range; - rtx insn; - int i, j; - regset new_dead = ALLOCA_REG_SET (); - regset old_live = ALLOCA_REG_SET (); - rtx *replacements = (rtx *) obstack_alloc (&global_obstack, - max_regno * sizeof (rtx)); - bzero ((char *)replacements, max_regno * sizeof (rtx)); - - for (i = max_regno-1; i >= 0; i--) - reg_renumber[i] = save_reg_renumber[i]; - - for (range = live_range_list; range; range = XEXP (range, 1)) - { - rtx range_start = XEXP (range, 0); - rtx rinfo = NOTE_RANGE_INFO (range_start); - int bb_start = RANGE_INFO_BB_START (rinfo); - int bb_end = RANGE_INFO_BB_END (rinfo); - int block; - int num_dead_regs; - - CLEAR_REG_SET (new_dead); - num_dead_regs = 0; - j = 0; - for (i = 0; i < RANGE_INFO_NUM_REGS (rinfo); i++) - { - int old_regno = RANGE_REG_PSEUDO (rinfo, i); - int new_regno = RANGE_REG_COPY (rinfo, i); - - if (new_regno >= 0 && reg_renumber[new_regno] < 0) - { - int new_allocno = reg_allocno[new_regno]; - int old_allocno = reg_allocno[old_regno]; - int j; - - /* Conflicts are not symmetric! */ - for (j = 0; j < max_allocno; j++) - { - if (CONFLICTP (new_allocno, j)) - SET_CONFLICT (old_allocno, j); - - if (CONFLICTP (j, new_allocno)) - SET_CONFLICT (j, old_allocno); - } - - replacements[new_regno] = regno_reg_rtx[old_regno]; - SET_REGNO_REG_SET (new_dead, new_regno); - -#if 0 - REG_N_REFS (old_regno) += REG_N_REFS (new_regno); - REG_N_SETS (old_regno) += REG_N_SETS (new_regno); - REG_N_DEATHS (old_regno) += REG_N_DEATHS (new_regno); - REG_N_CALLS_CROSSED (old_regno) += REG_N_CALLS_CROSSED (new_regno); - REG_LIVE_LENGTH (old_regno) += REG_LIVE_LENGTH (new_regno); -#endif - - REG_N_REFS (new_regno) = 0; - REG_N_SETS (new_regno) = 0; - REG_N_DEATHS (new_regno) = 0; - REG_N_CALLS_CROSSED (new_regno) = 0; - REG_LIVE_LENGTH (new_regno) = 0; - num_dead_regs++; - - if (file) - fprintf (file, "Live range copy register %d not allocated\n", - new_regno); - } - else - RANGE_INFO_REGS_REG (rinfo, j++) = RANGE_INFO_REGS_REG (rinfo, i); - } - - RANGE_INFO_NUM_REGS (rinfo) -= num_dead_regs; - - /* Update live information */ - for (block = bb_start; block <= bb_end; block++) - { - regset bits = basic_block_live_at_start[block]; - - CLEAR_REG_SET (old_live); - EXECUTE_IF_AND_IN_REG_SET (bits, new_dead, - FIRST_PSEUDO_REGISTER, i, - { - int n = REGNO (replacements[i]); - SET_REGNO_REG_SET (old_live, n); - }); - - AND_COMPL_REG_SET (bits, new_dead); - IOR_REG_SET (bits, old_live); - basic_block_live_at_start[block] = bits; - } - } - - for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) - if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') - { - rtx note; - rtx set = single_set (insn); - - /* Delete the copy-ins, copy-outs. */ - if (set - && GET_CODE (SET_DEST (set)) == REG - && GET_CODE (SET_SRC (set)) == REG - && ((replacements[REGNO (SET_DEST (set))] == SET_SRC (set)) - || (replacements[REGNO (SET_SRC (set))] == SET_DEST (set)))) - { - PUT_CODE (insn, NOTE); - NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (insn) = 0; - } - else - { - PATTERN (insn) = replace_regs (PATTERN (insn), - replacements, max_regno, - TRUE); - - for (note = REG_NOTES (insn); - note != NULL_RTX; - note = XEXP (note, 1)) - { - if ((REG_NOTE_KIND (note) == REG_DEAD - || REG_NOTE_KIND (note) == REG_UNUSED) - && GET_CODE (XEXP (note, 0)) == REG - && (replacements[ REGNO (XEXP (note, 0))] != NULL_RTX)) - { - XEXP (note, 0) = replacements[ REGNO (XEXP (note, 0))]; - } - - /* If the pseudo is set more than once and has a REG_EQUIV - note attached, then demote the REG_EQUIV note to a - REG_EQUAL note. */ - if (set - && GET_CODE (SET_DEST (set)) == REG - && REG_N_SETS (REGNO (SET_DEST (set))) > 1 - && REG_NOTE_KIND (note) == REG_EQUIV) - PUT_REG_NOTE_KIND (note, REG_EQUAL); - } - } - } - - FREE_REG_SET (new_dead); - FREE_REG_SET (old_live); -} - /* Scan the rtl code and record all conflicts and register preferences in the conflict matrices and preference tables. */ @@ -1151,33 +801,6 @@ global_conflicts () insn = NEXT_INSN (insn); } } - - /* CYGNUS LOCAL live range */ - /* Go through any live ranges created, and specifically delete any conflicts - between the original register and the copy that is made for use within - the range. */ -#if 1 - if (live_range_list) - { - rtx range; - for (range = live_range_list; range; range = XEXP (range, 1)) - { - rtx range_start = XEXP (range, 0); - rtx rinfo = NOTE_RANGE_INFO (range_start); - for (i = 0; i < RANGE_INFO_NUM_REGS (rinfo); i++) - { - int old_allocno = reg_allocno[RANGE_REG_PSEUDO (rinfo, i)]; - int new_allocno = reg_allocno[RANGE_REG_COPY (rinfo, i)]; - if (old_allocno >= 0 && new_allocno >= 0) - { - CLEAR_CONFLICT (old_allocno, new_allocno); - CLEAR_CONFLICT (new_allocno, old_allocno); - } - } - } - } -#endif - /* END CYGNUS LOCAL */ } /* Expand the preference information by looking for cases where one allocno dies in an insn that sets an allocno. If those two allocnos don't conflict, @@ -1353,11 +976,8 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying) reg_class_contents[(int) CLASS_CANNOT_CHANGE_SIZE]); #endif - /* CYGNUS LOCAL live range */ - /* Try each hard reg to see if it fits. Do this in three passes. - In the first pass, check whether any other copies of the same original - register created by LRS have been allocated to a hadr register. - In the second pass, skip registers that are preferred by some other pseudo + /* Try each hard reg to see if it fits. Do this in two passes. + In the first pass, skip registers that are preferred by some other pseudo to give it a better chance of getting one of those registers. Only if we can not get a register when excluding those do we take one of them. However, we never allocate a register for the first time in pass 0. */ @@ -1368,17 +988,10 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying) best_reg = -1; for (i = FIRST_PSEUDO_REGISTER, pass = 0; - pass <= 2 && i >= FIRST_PSEUDO_REGISTER; + pass <= 1 && i >= FIRST_PSEUDO_REGISTER; pass++) { if (pass == 0) - { - if (!reg_live_ranges || !reg_live_ranges[pseudo]) - continue; - COPY_HARD_REG_SET (used, *reg_live_ranges[pseudo]); - IOR_HARD_REG_SET (used, used_nopref); - } - else if (pass == 1) COPY_HARD_REG_SET (used, used_nopref); else COPY_HARD_REG_SET (used, used1); @@ -1413,7 +1026,6 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying) } } } - /* END CYGNUS LOCAL */ /* See if there is a preferred register with the same class as the register we allocated above. Making this restriction prevents register @@ -1606,13 +1218,6 @@ find_reg (allocno, losers, alt_regs_p, accept_call_clobbered, retrying) if (reg_allocno[j] == allocno) reg_renumber[j] = best_reg; - /* CYGNUS LOCAL live range */ - /* If this is a live range copy, update the register mask so that - other distinct ranges can try to allocate the same register. */ - if (reg_live_ranges && reg_live_ranges[pseudo] != NULL) - CLEAR_HARD_REG_BIT (*reg_live_ranges[pseudo], best_reg); - /* END CYGNUS LOCAL */ - /* Make a set of the hard regs being allocated. */ CLEAR_HARD_REG_SET (this_reg); lim = best_reg + HARD_REGNO_NREGS (best_reg, mode); diff --git a/gcc/range.c b/gcc/range.c deleted file mode 100755 index 1a76b43..0000000 --- a/gcc/range.c +++ /dev/null @@ -1,1931 +0,0 @@ -/* CYGNUS LOCAL LRS */ -/* Allocate registers within a basic block, for GNU compiler. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. - -This file is part of GNU CC. - -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. - -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. - -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. */ - -/* Live range support that splits a variable that is spilled to the stack into - smaller ranges so that at least the middle of small loops the variable will - be run in registers. This is run after global allocation if one or more - variables were denied a register, and then global allocation is done once - again. */ - -#include "config.h" -#include "system.h" -#include "rtl.h" -#include "tree.h" -#include "flags.h" -#include "basic-block.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "insn-config.h" -#include "recog.h" -#include "output.h" -#include "expr.h" -#include "except.h" -#include "function.h" -#include "obstack.h" -#include "range.h" -#include "toplev.h" - -extern struct obstack *rtl_obstack; - -/* Information that we gather about registers */ -typedef struct rinfo_def { - rtx reg; /* Register insn */ - int refs; /* # of register references */ - int sets; /* # of register sets/clobbers */ - int deaths; /* # of register deaths */ - int live_length; /* # of insns in range value is live */ - int n_calls; /* # of calls this reg crosses */ - int copy_flags; /* copy {in,out} flags */ -} rinfo; - -/* Basic blocks expressed as a linked list */ -typedef struct bb_link_def { - int block; /* block number or -1 */ - rtx first_insn; /* first insn in block */ - rtx last_insn; /* last insn in block */ - regset live_at_start; /* live information */ -} bb_link; - -/* Symbol/block node that a variable is declared in and whether a register - only holds constants. */ -typedef struct var_info_def { - tree symbol; /* DECL_NODE of the symbol */ - tree block; /* BLOCK_NODE variable is declared in */ - rtx constant_value; /* what value a register always holds */ -} var_info; - -int range_max_unique; /* Range #, monotonically increasing */ - -static rinfo *range_info; /* Register information */ -static var_info *range_vars; /* Map regno -> variable */ -static int *range_regs; /* Registers used in the loop */ -static int range_num_regs; /* # of registers in range_regs */ -static int range_loop_depth; /* current loop depth */ -static int range_update_used_p; /* whether range_used should be set */ -static regset range_used; /* regs used in the current range */ -static regset range_set; /* regs set in the current range */ -static regset range_live; /* regs currently live */ -static regset range_mixed_mode; /* regs that use different modes */ -static regset range_no_move; /* regs that don't have simple moves */ -static unsigned range_max_uid; /* Size of UID->basic block mapping */ -static bb_link **range_block_insn; /* Map INSN # to basic block # */ -static bb_link *range_block_orig; /* original basic blocks */ - -/* Linked list of live ranges to try allocating registers in first before - allocating all of the remaining registers. */ -rtx live_range_list; - -#define RANGE_BLOCK_NUM(INSN) \ -(((unsigned)INSN_UID (INSN) < (unsigned)range_max_uid \ - && range_block_insn[INSN_UID (INSN)]) \ - ? range_block_insn[INSN_UID (INSN)]->block : -1) - -/* Forward references */ -static void range_mark PROTO((rtx, int, rtx)); -static void range_basic_mark PROTO((rtx, regset, rtx)); -static void range_basic_insn PROTO((rtx, regset, int)); -static void range_bad_insn PROTO((FILE *, char *, rtx)); -static void range_print_flags PROTO((FILE *, int, char *)); -static void print_blocks_internal PROTO((FILE *, tree, int)); -static int range_inner PROTO((FILE *, rtx, rtx, rtx, rtx, - regset, regset, int)); -static void range_update_basic_block PROTO((FILE *, rtx, bb_link *, - int, int)); -static void range_finish PROTO((FILE *, rtx, int, int)); -static void range_scan_blocks PROTO((tree, tree)); -static int range_compare PROTO((const GENERIC_PTR, - const GENERIC_PTR)); - - -/* Determine which registers are used/set */ - -static void -range_mark (x, set_p, insn) - rtx x; - int set_p; - rtx insn; -{ - register RTX_CODE code = GET_CODE (x); - register int i, regno; - register char *fmt; - -restart: - - switch (code) - { - default: - break; - - /* Make sure we mark the registers that are set */ - case SET: - range_mark (SET_DEST (x), TRUE, insn); - range_mark (SET_SRC (x), FALSE, insn); - return; - - /* Treat clobber like a set. */ - /* Pre-increment and friends always update as well as reference. */ - case CLOBBER: - case PRE_INC: - case PRE_DEC: - case POST_INC: - case POST_DEC: - range_mark (XEXP (x, 0), TRUE, insn); - return; - - /* Memory addresses just reference the register, even if this is a SET */ - case MEM: - range_mark (XEXP (x, 0), FALSE, insn); - return; - - /* Treat subregs as using/modifying the whole register. */ - case SUBREG: - x = SUBREG_REG (x); - code = GET_CODE (x); - goto restart; - - /* Actual registers, skip hard registers */ - case REG: - regno = REGNO (x); - if (regno >= FIRST_PSEUDO_REGISTER) - { - if (!range_info[regno].reg) - range_info[regno].reg = x; - else if (GET_MODE (x) != GET_MODE (range_info[regno].reg)) - SET_REGNO_REG_SET (range_mixed_mode, regno); - - range_info[regno].refs += 2*range_loop_depth; - SET_REGNO_REG_SET (range_live, regno); - if (range_update_used_p) - SET_REGNO_REG_SET (range_used, regno); - - /* If there isn't a simple move pattern for the mode, skip it */ - if (mov_optab->handlers[(int) GET_MODE (x)].insn_code - == CODE_FOR_nothing) - SET_REGNO_REG_SET (range_no_move, regno); - - if (set_p) - { - range_info[regno].sets++; - SET_REGNO_REG_SET (range_set, regno); - } - } - - return; - } - - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - range_mark (XEXP (x, i), set_p, insn); - - else if (fmt[i] == 'E') - { - register unsigned j; - for (j = 0; j < XVECLEN (x, i); j++) - range_mark (XVECEXP (x, i, j), set_p, insn); - } - } -} - - -/* Like range_mark, except more stripped down, to just care about what - registers are currently live. */ - -static void -range_basic_mark (x, live, insn) - rtx x; - regset live; - rtx insn; -{ - register RTX_CODE code = GET_CODE (x); - register int i, regno, lim; - register char *fmt; - -restart: - switch (code) - { - default: - break; - - /* Treat subregs as using/modifying the whole register. */ - case SUBREG: - x = SUBREG_REG (x); - code = GET_CODE (x); - goto restart; - - /* Actual registers */ - case REG: - regno = REGNO (x); - lim = regno + ((regno >= FIRST_PSEUDO_REGISTER) - ? 1 - : HARD_REGNO_NREGS (regno, GET_MODE (x))); - - for (i = regno; i < lim; i++) - SET_REGNO_REG_SET (live, i); - return; - } - - fmt = GET_RTX_FORMAT (code); - for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) - { - if (fmt[i] == 'e') - range_basic_mark (XEXP (x, i), live, insn); - - else if (fmt[i] == 'E') - { - register unsigned j; - for (j = 0; j < XVECLEN (x, i); j++) - range_basic_mark (XVECEXP (x, i, j), live, insn); - } - } -} - -/* For an INSN, CALL_INSN, or JUMP_INSN, update basic live/dead information. */ - -static void -range_basic_insn (insn, live, range_max_regno) - rtx insn; - regset live; - int range_max_regno; -{ - rtx note, x; - int i; - - range_basic_mark (PATTERN (insn), live, insn); - - /* Remember if the value is only set to one constant. */ - if (GET_CODE (insn) == INSN - && (x = single_set (insn)) != NULL_RTX - && (GET_CODE (SET_DEST (x)) == REG - && REG_N_SETS (REGNO (SET_DEST (x))) == 1 - && CONSTANT_P (SET_SRC (x))) - && REGNO (SET_DEST (x)) < range_max_regno) - range_vars[ REGNO (SET_DEST (x))].constant_value = SET_SRC (x); - - /* figure out which registers are now dead. */ - for (note = REG_NOTES (insn); note != NULL_RTX; note = XEXP (note, 1)) - { - if (REG_NOTE_KIND (note) == REG_DEAD - && GET_CODE (XEXP (note, 0)) == REG) - { - rtx reg = XEXP (note, 0); - int regno = REGNO (reg); - int lim = regno + ((regno >= FIRST_PSEUDO_REGISTER) - ? 1 - : HARD_REGNO_NREGS (regno, GET_MODE (reg))); - - for (i = regno; i < lim; i++) - CLEAR_REGNO_REG_SET (live, i); - } - } -} - - -/* Sort the registers by number of uses */ - -static int -range_compare (v1p, v2p) - const GENERIC_PTR v1p; - const GENERIC_PTR v2p; -{ - int i1 = *(int *)v1p; - int i2 = *(int *)v2p; - int r1 = range_info[i1].refs; - int r2 = range_info[i2].refs; - - if (r2 - r1) - return r2 - r1; - - /* Make sure that range_compare always is stable, so if the values are equal, - compare based on pseduo register number. */ - return REGNO (range_info[i2].reg) - REGNO (range_info[i1].reg); -} - - -/* If writing a .range file, print a message and an rtl. */ - -static void -range_bad_insn (stream, msg, insn) - FILE *stream; - char *msg; - rtx insn; -{ - if (stream) - { - fputs (msg, stream); - print_rtl (stream, PATTERN (insn)); - putc ('\n', stream); - } -} - - -/* Print out to STREAM the copyin/copyout flags. */ - -static void -range_print_flags (stream, flags, prefix) - FILE *stream; - int flags; - char *prefix; -{ - if ((flags & LIVE_RANGE_COPYIN) != 0) - { - fprintf (stream, "%scopyin", prefix); - prefix = ", "; - } - - if ((flags & LIVE_RANGE_COPYIN_CONST) != 0) - { - fprintf (stream, "%sconst", prefix); - prefix = ", "; - } - - if ((flags & LIVE_RANGE_COPYOUT) != 0) - fprintf (stream, "%scopyout", prefix); - -} - - -/* Print out range information to STREAM, using RANGE as the range_info rtx, - printing TAB and COMMENT at the beginning of each line. */ - -void -live_range_print (stream, range, tab, comment) - FILE *stream; - rtx range; - char *tab; - char *comment; -{ - int i; - - fprintf (stream, - "%s%s range #%d start, %d calls, basic block {start/end} %d/%d, loop depth %d\n", - tab, comment, - RANGE_INFO_UNIQUE (range), RANGE_INFO_NCALLS (range), - RANGE_INFO_BB_START (range), RANGE_INFO_BB_END (range), - RANGE_INFO_LOOP_DEPTH (range)); - - for (i = 0; i < (int)RANGE_INFO_NUM_REGS (range); i++) - { - int pseudo = RANGE_REG_PSEUDO (range, i); - int copy = RANGE_REG_COPY (range, i); - - fprintf (stream, "%s%s reg %d", tab, comment, pseudo); - if (reg_renumber) - { - if ((unsigned)pseudo >= (unsigned)max_regno) - fprintf (stream, " (illegal)"); - else if (reg_renumber[pseudo] >= 0) - fprintf (stream, " (%s)", reg_names[ reg_renumber[pseudo]]); - } - - fprintf (stream, ", copy %d", copy); - if (reg_renumber) - { - if ((unsigned)copy >= (unsigned)max_regno) - fprintf (stream, " (illegal)"); - else if (reg_renumber[copy] >= 0) - fprintf (stream, " (%s)", reg_names[ reg_renumber[copy]]); - } - - fprintf (stream, - ", %d ref(s), %d set(s), %d death(s), %d live length, %d calls", - RANGE_REG_REFS (range, i), - RANGE_REG_SETS (range, i), - RANGE_REG_DEATHS (range, i), - RANGE_REG_LIVE_LENGTH (range, i), - RANGE_REG_N_CALLS (range, i)); - - range_print_flags (stream, RANGE_REG_COPY_FLAGS (range, i), ", "); - if (REG_USERVAR_P (regno_reg_rtx[pseudo])) - { - fprintf (stream, ", user"); - if (RANGE_REG_SYMBOL_NODE (range, i)) - { - tree name = DECL_NAME (RANGE_REG_SYMBOL_NODE (range, i)); - if (name) - fprintf (stream, " [%s]", IDENTIFIER_POINTER (name)); - } - } - - if (REGNO_POINTER_FLAG (pseudo)) - fprintf (stream, ", ptr"); - - putc ('\n', stream); - } -} - - -/* CYGNUS LOCAL -- meissner/live range */ -/* Print the scoping blocks in the current function */ - -static void -print_blocks_internal (stream, block, level) - FILE *stream; - tree block; - int level; -{ - /* Loop over all blocks */ - for (; block != NULL_TREE; block = BLOCK_CHAIN (block)) - { - int i; - tree vars_types[2]; - static char *vars_types_name[] = {"vars: ", "types:"}; - - fprintf (stream, "%*sBlock ", level*4, ""); - fprintf (stream, HOST_WIDE_INT_PRINT_HEX, (HOST_WIDE_INT) block); - - if (BLOCK_CHAIN (block)) - { - fprintf (stream, ", chain "); - fprintf (stream, HOST_WIDE_INT_PRINT_HEX, - (HOST_WIDE_INT) BLOCK_CHAIN (block)); - } - - if (BLOCK_VARS (block)) - { - fprintf (stream, ", vars "); - fprintf (stream, HOST_WIDE_INT_PRINT_HEX, - (HOST_WIDE_INT) BLOCK_VARS (block)); - } - - if (BLOCK_TYPE_TAGS (block)) - { - fprintf (stream, ", types "); - fprintf (stream, HOST_WIDE_INT_PRINT_HEX, - (HOST_WIDE_INT) BLOCK_TYPE_TAGS (block)); - } - - if (BLOCK_SUBBLOCKS (block)) - { - fprintf (stream, ", subblocks "); - fprintf (stream, HOST_WIDE_INT_PRINT_HEX, - (HOST_WIDE_INT) BLOCK_SUBBLOCKS (block)); - } - - if (BLOCK_ABSTRACT_ORIGIN (block)) - { - fprintf (stream, ", abstract origin "); - fprintf (stream, HOST_WIDE_INT_PRINT_HEX, - (HOST_WIDE_INT) BLOCK_ABSTRACT_ORIGIN (block)); - } - - if (BLOCK_ABSTRACT (block)) - fprintf (stream, ", abstract"); - - if (BLOCK_LIVE_RANGE_FLAG (block)) - fprintf (stream, ", live-range"); - - if (BLOCK_LIVE_RANGE_VAR_FLAG (block)) - fprintf (stream, ", live-range-vars"); - - if (BLOCK_HANDLER_BLOCK (block)) - fprintf (stream, ", handler"); - - if (TREE_USED (block)) - fprintf (stream, ", used"); - - if (TREE_ASM_WRITTEN (block)) - fprintf (stream, ", asm-written"); - - fprintf (stream, "\n"); - vars_types[0] = BLOCK_VARS (block); - vars_types[1] = BLOCK_TYPE_TAGS (block); - for (i = 0; i < 2; i++) - if (vars_types[i]) - { - tree vars; - int indent = ((level < 4) ? 16 : (level*4) + 4) - 1; - int len = 0; - - for (vars = BLOCK_VARS (block); - vars != NULL_TREE; - vars = TREE_CHAIN (vars)) - { - if (DECL_NAME (vars) && IDENTIFIER_POINTER (DECL_NAME (vars))) - { - if (len == 0) - { - len = indent + 1 + strlen (vars_types_name[i]); - fprintf (stream, "%*s%s", indent+1, "", - vars_types_name[i]); - } - - len += IDENTIFIER_LENGTH (DECL_NAME (vars)) + 1; - if (len >= 80 && len > indent) - { - len = indent; - fprintf (stream, "\n%*s", indent, ""); - } - - fprintf (stream, " %.*s", - IDENTIFIER_LENGTH (DECL_NAME (vars)), - IDENTIFIER_POINTER (DECL_NAME (vars))); - } - } - - fprintf (stream, "\n\n"); - } - - print_blocks_internal (stream, BLOCK_SUBBLOCKS (block), level+1); - } -} - -void -print_all_blocks () -{ - fprintf (stderr, "\n"); - print_blocks_internal (stderr, DECL_INITIAL (current_function_decl), 0); -} - - -/* Function with debugging output to STREAM that handles a sequence of insns - that goes from RANGE_START to RANGE_END, splitting the range of variables - used between INNER_START and INNER_END. Registers in LIVE_AT_START are live - at the first insn. BB_{START,END} holds the basic block numbers of the - first and last insns. Return the number of variables that had their ranges - split into a new pseudo variable used only within the loop. */ - -static int -range_inner (stream, range_start, range_end, inner_start, inner_end, - live_at_start, live_at_end, loop_depth) - FILE *stream; - rtx range_start; - rtx range_end; - rtx inner_start; - rtx inner_end; - regset live_at_start; - regset live_at_end; - int loop_depth; -{ - rtx insn; - rtx pattern; - rtx label_ref; - rtx label_chain; - rtx start; - rtx end; - rtx *regs; - rtvec regs_rtvec; - rtx note; - int first_label = get_first_label_num (); - int last_label = max_label_num (); - unsigned num_labels = last_label - first_label + 1; - unsigned indx; - int i; - int regno; - int block; - int *loop_label_ref = (int *) alloca (sizeof (int) * num_labels); - int *all_label_ref = (int *) alloca (sizeof (int) * num_labels); - char *found_label_ref = (char *) alloca (sizeof (char) * num_labels); - int ok_p = TRUE; - int n_insns; - int n_calls; - regset live_at_start_copy; - regset live_at_end_copy; - int bb_start; - int bb_end; - char *nl; - rtx ri; - - bzero ((char *)loop_label_ref, sizeof (int) * num_labels); - bzero ((char *)all_label_ref, sizeof (int) * num_labels); - bzero ((char *) range_info, sizeof (rinfo) * max_reg_num ()); - CLEAR_REG_SET (range_used); - CLEAR_REG_SET (range_set); - CLEAR_REG_SET (range_mixed_mode); - CLEAR_REG_SET (range_no_move); - COPY_REG_SET (range_live, live_at_start); - range_num_regs = 0; - range_loop_depth = loop_depth; - - if (stream) - fprintf (stream, "\nPossible range from %d to %d (inner range %d to %d)\nLive at start: ", - INSN_UID (range_start), INSN_UID (range_end), - INSN_UID (inner_start), INSN_UID (inner_end)); - - /* Mark the live registers as needing copies to the tmp register from the - original value. */ - EXECUTE_IF_SET_IN_REG_SET (live_at_start, FIRST_PSEUDO_REGISTER, i, - { - range_info[i].copy_flags |= LIVE_RANGE_COPYIN; - if (stream) - fprintf (stream, " %d", i); - if (range_vars[i].constant_value) - { - range_info[i].copy_flags - |= LIVE_RANGE_COPYIN_CONST; - - if (stream) - fprintf (stream, " [constant]"); - } - }); - - if (stream) - { - fprintf (stream, "\nLive at end: "); - EXECUTE_IF_SET_IN_REG_SET (live_at_end, FIRST_PSEUDO_REGISTER, i, - { - fprintf (stream, " %d", i); - }); - - putc ('\n', stream); - } - - /* Calculate basic block start and end */ - bb_start = -1; - for (insn = range_start; - insn && insn != range_end && (bb_start = RANGE_BLOCK_NUM (insn)) < 0; - insn = NEXT_INSN (insn)) - ; - - bb_end = -1; - for (insn = range_end; - insn && insn != range_start && (bb_end = RANGE_BLOCK_NUM (insn)) < 0; - insn = PREV_INSN (insn)) - ; - - if (bb_start < 0) - { - ok_p = FALSE; - if (stream) - fprintf (stream, "Cannot find basic block start\n"); - } - - if (bb_end < 0) - { - ok_p = FALSE; - if (stream) - fprintf (stream, "Cannot find basic block end\n"); - } - - /* Scan the loop, looking for jumps outside/inside of the loop. If the - loop has such jumps, we ignore it. */ - n_insns = n_calls = block = 0; - range_update_used_p = FALSE; - for (insn = range_start; insn && insn != range_end; insn = NEXT_INSN (insn)) - { - enum rtx_code code = GET_CODE (insn); - int block_tmp = RANGE_BLOCK_NUM (insn); - if (block_tmp >= 0 && block != block_tmp) - { - block = block_tmp; - COPY_REG_SET (range_live, basic_block_live_at_start[block]); - } - - /* Only mark registers that appear between INNER_START and INNER_END */ - if (insn == inner_start) - range_update_used_p = TRUE; - else if (insn == inner_end) - range_update_used_p = FALSE; - - if (GET_RTX_CLASS (code) == 'i') - { - n_insns++; - /* Mark used registers */ - range_mark (PATTERN (insn), FALSE, insn); - - /* Update live length, & number of calls that the insn crosses */ - EXECUTE_IF_SET_IN_REG_SET (range_live, FIRST_PSEUDO_REGISTER, i, - { - range_info[i].live_length++; - if (GET_CODE (insn) == CALL_INSN) - range_info[i].n_calls++; - }); - - /* figure out which ones will be dead by the end of the region */ - for (note = REG_NOTES (insn); note != NULL_RTX; note = XEXP (note, 1)) - { - if (REG_NOTE_KIND (note) == REG_DEAD - && GET_CODE (XEXP (note, 0)) == REG - && REGNO (XEXP (note, 0)) > FIRST_PSEUDO_REGISTER) - { - CLEAR_REGNO_REG_SET (range_live, REGNO (XEXP (note, 0))); - range_info[ REGNO (XEXP (note, 0)) ].deaths++; - } - } - } - - switch (code) - { - default: - break; - - /* Update loop_depth */ - case NOTE: - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) - range_loop_depth++; - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) - range_loop_depth++; - break; - - /* Record whether there was a call. */ - case CALL_INSN: - n_calls++; - break; - - /* Found a label, record the number of uses */ - case CODE_LABEL: - indx = CODE_LABEL_NUMBER (insn) - first_label; - if (indx >= num_labels) - { - if (stream) - fprintf (stream, "Code label %d doesn't fit in label table", - CODE_LABEL_NUMBER (insn)); - - ok_p = FALSE; - continue; - } - - all_label_ref[indx] = LABEL_NUSES (insn); - break; - - /* Found a jump of some sort, see where the jump goes. */ - case JUMP_INSN: - pattern = PATTERN (insn); - - /* Switch statement, process all labels */ - if (GET_CODE (pattern) == ADDR_VEC - || GET_CODE (pattern) == ADDR_DIFF_VEC) - { - int vec_num = (GET_CODE (PATTERN (insn)) == ADDR_VEC) ? 0 : 1; - int len = XVECLEN (pattern, vec_num); - bzero ((char *)found_label_ref, sizeof (char) * num_labels); - - for (i = 0; i < len; i++) - { - label_ref = XEXP (XVECEXP (pattern, vec_num, i), 0); - indx = CODE_LABEL_NUMBER (label_ref) - first_label; - - if (indx >= num_labels) - { - range_bad_insn (stream, - "Label ref doesn't fit in label table\n", - label_ref); - ok_p = FALSE; - } - - /* Only process duplicated labels once, since the LABEL_REF - chain only includes it once. */ - else if (!found_label_ref[indx]) - { - found_label_ref[indx] = TRUE; - loop_label_ref[indx]++; - } - } - } - - else - { - label_ref = JUMP_LABEL (insn); - if (!label_ref) - { - rtx sset; - range_bad_insn - (stream, - (((sset = single_set (insn)) != NULL_RTX - && (GET_CODE (SET_SRC (sset)) == REG - || GET_CODE (SET_SRC (sset)) == SUBREG - || GET_CODE (SET_SRC (sset)) == MEM)) - ? "Jump to indeterminate label in inner loop\n" - : "JUMP_LABEL (insn) is null.\n"), - insn); - - ok_p = FALSE; - continue; - } - - if (GET_CODE (label_ref) != CODE_LABEL) - { - range_bad_insn (stream, - "JUMP_LABEL (insn) is not a CODE_LABEL.\n", - insn); - - ok_p = FALSE; - continue; - } - - indx = CODE_LABEL_NUMBER (label_ref) - first_label; - if (indx >= num_labels) - { - range_bad_insn (stream, - "Label ref doesn't fit in label table\n", - insn); - - ok_p = FALSE; - continue; - } - - loop_label_ref[indx]++; - } - - break; - } - } - - /* Now that we've scanned the loop, check for any jumps into or out of - the loop, and if we've found them, don't do live range splitting. - If there are no registers used in the loop, there is nothing to do. */ - nl = (char *)0; - if (ok_p) - { - for (i = 0; i < (int)num_labels; i++) - if (loop_label_ref[i] != all_label_ref[i]) - { - ok_p = FALSE; - if (stream) - { - nl = "\n"; - if (!all_label_ref[i]) - fprintf (stream, "label %d was outside of the loop.\n", i+first_label); - else - fprintf (stream, "label %d had %d references, only %d were in loop.\n", - i+first_label, all_label_ref[i], loop_label_ref[i]); - } - } - - /* ignore any registers that use different modes, or that don't have simple - move instructions. */ - if (stream) - { - EXECUTE_IF_SET_IN_REG_SET (range_mixed_mode, FIRST_PSEUDO_REGISTER, regno, - { - nl = "\n"; - fprintf (stream, - "Skipping register %d used with different types\n", - regno); - }); - - EXECUTE_IF_SET_IN_REG_SET (range_no_move, FIRST_PSEUDO_REGISTER, regno, - { - nl = "\n"; - fprintf (stream, - "Skipping register %d that needs complex moves\n", - regno); - }); - } - - IOR_REG_SET (range_mixed_mode, range_no_move); - AND_COMPL_REG_SET (range_used, range_mixed_mode); - AND_COMPL_REG_SET (range_set, range_mixed_mode); - EXECUTE_IF_SET_IN_REG_SET(range_used, FIRST_PSEUDO_REGISTER, regno, - { - /* If the register isn't live at the end, - indicate that it must have died. */ - if (REGNO_REG_SET_P (live_at_end, regno)) - range_info[regno].copy_flags - |= LIVE_RANGE_COPYOUT; - - /* If the register is only used in a single - basic block, let local-alloc allocate - a register for it. */ - if (REG_BASIC_BLOCK (regno) >= 0) - { - nl = "\n"; - if (stream) - fprintf (stream, - "Skipping %d due to being used in a single basic block\n", - regno); - continue; - } - - /* If the register is live only within the - range, don't bother with it. */ - if (REG_LIVE_LENGTH (regno) - <= range_info[regno].live_length) - { - nl = "\n"; - if (stream) - fprintf (stream, - "Skipping %d due to being used only in range\n", - regno); - continue; - } - - range_regs[range_num_regs++] = regno; - }); - - if (range_num_regs == 0) - { - ok_p = FALSE; - if (stream) - fprintf (stream, "No registers found in loop\n"); - } - } - - if (stream && nl) - fputs (nl, stream); - - if (!ok_p) - return 0; - - qsort (range_regs, range_num_regs, sizeof (int), range_compare); - - CLEAR_REG_SET (range_used); - for (i = 0; i < range_num_regs; i++) - SET_REGNO_REG_SET (range_used, range_regs[i]); - -#if 0 - /* Narrow down range_start so that we include only those insns that reference - one of the live range variables. */ - regs_ref = ALLOCA_REG_SET (); - regs_set = ALLOCA_REG_SET (); - regs_tmp = ALLOCA_REG_SET (); - - uses_regs = inner_start; - for (insn = inner_start; insn; insn = PREV_INSN (insn)) - { - if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' - && regset_mentioned_p (range_used, PATTERN (insn), FALSE, regs_ref, - regs_set)) - { - uses_regs = insn; - } - - if (insn == range_start) - break; - } - range_start = uses_regs; - - /* Narrow down range_end so that we include only those insns that reference - one of the live range variables. */ - CLEAR_REG_SET (regs_ref); - uses_regs = inner_end; - for (insn = inner_end; insn; insn = NEXT_INSN (insn)) - { - if (GET_RTX_CLASS (GET_CODE (insn)) == 'i' - && regset_mentioned_p (range_used, PATTERN (insn), FALSE, regs_ref, - regs_set)) - { - uses_regs = insn; - } - - if (insn == range_end) - break; - } - range_end = uses_regs; - - FREE_REG_SET (regs_ref); - FREE_REG_SET (regs_set); - FREE_REG_SET (regs_tmp); -#endif - - /* Mark the live range region. */ - regs = (rtx *) alloca (sizeof (rtx) * range_num_regs); - for (i = 0; i < range_num_regs; i++) - { - int r = range_regs[i]; - rinfo *ri = &range_info[r]; - - if (range_vars[r].block) - BLOCK_LIVE_RANGE_VAR_FLAG (range_vars[r].block) = TRUE; - - REG_N_RANGE_CANDIDATE_P (r) = 1; - regs[i] = gen_rtx (RANGE_REG, VOIDmode, - r, -1, ri->refs, ri->sets, ri->deaths, - ri->copy_flags, ri->live_length, ri->n_calls, - range_vars[r].symbol, range_vars[r].block); - } - - live_at_start_copy = OBSTACK_ALLOC_REG_SET (rtl_obstack); - live_at_end_copy = OBSTACK_ALLOC_REG_SET (rtl_obstack); - COPY_REG_SET (live_at_start_copy, live_at_start); - COPY_REG_SET (live_at_end_copy, live_at_end); - - regs_rtvec = gen_rtvec_v (range_num_regs, regs); - start = emit_note_before (NOTE_INSN_RANGE_START, range_start); - end = emit_note_after (NOTE_INSN_RANGE_END, range_end); - - ri = gen_rtx (RANGE_INFO, VOIDmode, start, end, regs_rtvec, n_calls, n_insns, - range_max_unique++, bb_start, bb_end, loop_depth, - live_at_start_copy, live_at_end_copy, 0, 0); - - NOTE_RANGE_INFO (start) = ri; - NOTE_RANGE_INFO (end) = ri; - - live_range_list = gen_rtx (INSN_LIST, VOIDmode, start, live_range_list); - return range_num_regs; -} - - -/* Scan all blocks looking for user variables so that we can map from - register number back to the appropriate DECL_NODE and BLOCK_NODE. */ - -static void -range_scan_blocks (block, args) - tree block; - tree args; -{ - tree var; - - /* Scan arguments */ - for (var = args; var != NULL_TREE; var = TREE_CHAIN (var)) - { - if (DECL_RTL (var) && GET_CODE (DECL_RTL (var)) == REG) - { - int regno = REGNO (DECL_RTL (var)); - if ((unsigned)regno >= (unsigned)max_regno) - abort (); - - range_vars[regno].symbol = var; - range_vars[regno].block = block; - } - } - - /* Loop over all blocks */ - for (; block != NULL_TREE; block = BLOCK_CHAIN (block)) - if (TREE_USED (block)) - { - /* Record all symbols in the block */ - for (var = BLOCK_VARS (block); var != NULL_TREE; var = TREE_CHAIN (var)) - { - if (DECL_RTL (var) && GET_CODE (DECL_RTL (var)) == REG) - { - int regno = REGNO (DECL_RTL (var)); - if ((unsigned)regno >= (unsigned)max_regno) - abort (); - - range_vars[regno].symbol = var; - range_vars[regno].block = block; - } - } - - /* Record the subblocks, and their subblocks... */ - range_scan_blocks (BLOCK_SUBBLOCKS (block), NULL_TREE); - } -} - - -/* Recalculate the basic blocks due to adding copyins and copyouts. */ - -static void -range_update_basic_block (stream, first_insn, new_bb, - new_bb_count, range_max_regno) - FILE *stream; - rtx first_insn; - bb_link *new_bb; - int new_bb_count; - int range_max_regno; -{ - int i; - rtx insn; - rtx range; - rtx block_end; - rtx block_start; - int block; - int in_block_p; - int old_n_basic_blocks = n_basic_blocks; - int *map_bb = (int *) alloca (sizeof (int) * n_basic_blocks); - regset live = ALLOCA_REG_SET (); - - COPY_REG_SET (live, basic_block_live_at_start[0]); - - /* Go through and add NOTE_INSN_LIVE notes for each current basic block. */ - for (i = 0; i < old_n_basic_blocks; i++) - { - rtx p = emit_note_before (NOTE_INSN_LIVE, BLOCK_HEAD (i)); - NOTE_LIVE_INFO (p) = gen_rtx (RANGE_LIVE, VOIDmode, - basic_block_live_at_start[i], i); - map_bb[i] = -1; - - if (stream) - { - fprintf (stream, - "Old basic block #%d, first insn %d, last insn %d, live", - i, - INSN_UID (BLOCK_HEAD (i)), - INSN_UID (BLOCK_END (i))); - bitmap_print (stream, basic_block_live_at_start[i], " {", "}\n"); - } - } - - if (stream) - putc ('\n', stream); - - /* Recalculate the basic blocks. */ - free ((char *)x_basic_block_head); - free ((char *)x_basic_block_end); - x_basic_block_head = x_basic_block_end = (rtx *)0; - find_basic_blocks (first_insn, max_regno, stream); - free_basic_block_vars (TRUE); - - /* Restore the live information. We assume that flow will find either a - previous start of a basic block, or the newly created insn blocks as - the start of the new basic blocks. */ - - if (old_n_basic_blocks != n_basic_blocks) - basic_block_live_at_start - = (regset *) oballoc (sizeof (regset) * n_basic_blocks); - - init_regset_vector (basic_block_live_at_start, n_basic_blocks, - rtl_obstack); - - block = 0; - in_block_p = FALSE; - block_start = BLOCK_HEAD (0); - block_end = BLOCK_END (0); - for (insn = first_insn; insn; insn = NEXT_INSN (insn)) - { - /* If this is the start of a basic block update live information. */ - if (insn == block_start) - { - int i; - in_block_p = TRUE; - - /* See if this was the start of one of the "new" basic - blocks. If so, get register livetime information from - the data we saved when we created the range. */ - for (i = 0; i < new_bb_count; i++) - if (new_bb[i].first_insn == insn) - break; - - if (i < new_bb_count) - COPY_REG_SET (live, new_bb[i].live_at_start); - - COPY_REG_SET (basic_block_live_at_start[block], live); - } - - if (GET_CODE (insn) == NOTE) - { - /* Is this where an old basic block began? */ - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LIVE) - { - rtx info = NOTE_LIVE_INFO (insn); - COPY_REG_SET (live, RANGE_LIVE_BITMAP (info)); - map_bb[RANGE_LIVE_ORIG_BLOCK (info)] = block; - FREE_REG_SET (RANGE_LIVE_BITMAP (info)); - NOTE_LIVE_INFO (insn) = NULL_RTX; - if (stream) - fprintf (stream, "Old basic block #%d is now %d.\n", - RANGE_LIVE_ORIG_BLOCK (info), block); - } - - /* If a range start/end, use stored live information. */ - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_START) - { - rtx ri = NOTE_RANGE_INFO (insn); - int old_block = RANGE_INFO_BB_START (ri); - - RANGE_INFO_BB_START (ri) = block; - COPY_REG_SET (live, RANGE_INFO_LIVE_START (ri)); - if (stream) - fprintf (stream, - "Changing range start basic block from %d to %d\n", - old_block, block); - } - - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_RANGE_END) - { - rtx ri = NOTE_RANGE_INFO (insn); - int old_block = RANGE_INFO_BB_END (ri); - int new_block = (in_block_p) ? block : block-1; - - RANGE_INFO_BB_END (ri) = new_block; - COPY_REG_SET (live, RANGE_INFO_LIVE_END (ri)); - if (stream) - fprintf (stream, - "Changing range end basic block from %d to %d\n", - old_block, new_block); - } - } - - /* Update live/dead information. */ - if (GET_RTX_CLASS (GET_CODE (insn)) == 'i') - range_basic_insn (insn, live, range_max_regno); - - /* Advance basic block if at end. */ - if (insn == block_end) - { - block++; - in_block_p = FALSE; - if (block < n_basic_blocks) - { - block_start = BLOCK_HEAD (block); - block_end = BLOCK_END (block); - } - else - block_start = block_end = NULL_RTX; - } - } - - if (stream) - { - putc ('\n', stream); - fflush (stream); - } - - /* Update REG_BASIC_BLOCK field now. */ - for (i = 0; i < max_regno; i++) - { - if (REG_BASIC_BLOCK (i) >= 0) - REG_BASIC_BLOCK (i) = map_bb[REG_BASIC_BLOCK (i)]; - } -} - - -/* Allocate the new registers for live range splitting. Do this after we've - scanned all of the insns, so that we grow the tables only once. */ - -static void -range_finish (stream, first_insn, count, range_max_regno) - FILE *stream; - rtx first_insn; - int count; - int range_max_regno; -{ - rtx range; - int new_max_regno = max_reg_num () + count; - rtx *replacements = (rtx *) alloca (new_max_regno * sizeof (rtx)); - regset old_dead = ALLOCA_REG_SET (); - regset new_live = ALLOCA_REG_SET (); - regset copyouts = ALLOCA_REG_SET (); - rtx insn; - int i; - tree *block_list /* set up NOTE_BLOCK_NUM field */ - = ((write_symbols == NO_DEBUG) - ? (tree *)0 - : identify_blocks (DECL_INITIAL (current_function_decl), first_insn)); - - bb_link *new_bb; - int new_bb_count = 0; - int max_bb_count = 0; - - no_new_pseudos = 0; - for (range = live_range_list; range; range = XEXP (range, 1)) - max_bb_count += 2; - - new_bb = (bb_link *) alloca (sizeof (bb_link) * max_bb_count); - bzero ((char *)new_bb, sizeof (bb_link) * max_bb_count); - - if (stream) - putc ('\n', stream); - - /* Grow the register tables */ - allocate_reg_info (new_max_regno, FALSE, FALSE); - - for (range = live_range_list; range; range = XEXP (range, 1)) - { - rtx range_start = XEXP (range, 0); - rtx ri = NOTE_RANGE_INFO (range_start); - rtx range_end = RANGE_INFO_NOTE_END (ri); - int bb_start = RANGE_INFO_BB_START (ri); - int bb_end = RANGE_INFO_BB_END (ri); - int bb = (bb_start >= 0 && bb_start == bb_end) ? bb_start : -2; - rtx after; - rtx before; - int new_scope_p = (write_symbols != NO_DEBUG /* create new scope */ - && flag_live_range_scope /* block for vars? */ - ); - - after = range_start; - before = range_end; - - bzero ((char *)replacements, new_max_regno * sizeof (rtx)); - CLEAR_REG_SET (old_dead); - CLEAR_REG_SET (copyouts); - - /* Allocate new registers, set up the fields needed. */ - for (i = 0; i < (int)RANGE_INFO_NUM_REGS (ri); i++) - { - int old_regno = RANGE_REG_PSEUDO (ri, i); - rtx old_reg = regno_reg_rtx[old_regno]; - enum machine_mode mode = GET_MODE (old_reg); - rtx new_reg = gen_reg_rtx (mode); - int new_regno = REGNO (new_reg); - - replacements[old_regno] = new_reg; - - RANGE_REG_COPY (ri, i) = new_regno; - REG_N_RANGE_COPY_P (new_regno) = TRUE; - REG_N_REFS (new_regno) = RANGE_REG_REFS (ri, i); - REG_N_SETS (new_regno) = RANGE_REG_SETS (ri, i); - REG_N_DEATHS (new_regno) = RANGE_REG_DEATHS (ri, i); - REG_LIVE_LENGTH (new_regno) = RANGE_REG_LIVE_LENGTH (ri, i); - REG_N_CALLS_CROSSED (new_regno) = RANGE_REG_N_CALLS (ri, i); - REG_CHANGES_SIZE (new_regno) = 0; - REG_BASIC_BLOCK (new_regno) = bb; - REGNO_POINTER_FLAG (new_regno) = REGNO_POINTER_FLAG (old_regno); - REGNO_POINTER_ALIGN (new_regno) = REGNO_POINTER_ALIGN (old_regno); - REG_FUNCTION_VALUE_P (new_reg) = REG_FUNCTION_VALUE_P (old_reg); - REG_USERVAR_P (new_reg) = REG_USERVAR_P (old_reg); - REG_LOOP_TEST_P (new_reg) = REG_LOOP_TEST_P (old_reg); - RTX_UNCHANGING_P (new_reg) = RTX_UNCHANGING_P (old_reg); - -#if 0 - /* Until we can make sure we get this right, don't update the - reference counts on the old register. */ - REG_N_REFS (old_regno) -= REG_N_REFS (new_regno); - REG_N_SETS (old_regno) -= REG_N_SETS (new_regno); - REG_N_DEATHS (old_regno) -= REG_N_DEATHS (new_regno); - REG_N_CALLS_CROSSED (old_regno) -= REG_N_CALLS_CROSSED (new_regno); - REG_LIVE_LENGTH (old_regno) -= REG_LIVE_LENGTH (new_regno); - - if (REG_N_REFS (old_regno) <= 0) - error ("Setting # references of register %d to %d\n", - old_regno, REG_N_REFS (old_regno)); - - if (REG_N_SETS (old_regno) < 0) - error ("Setting # sets of register %d to %d\n", - old_regno, REG_N_SETS (old_regno)); - - if (REG_N_CALLS_CROSSED (old_regno) < 0) - error ("Setting # calls crossed of register %d to %d\n", - old_regno, REG_N_CALLS_CROSSED (old_regno)); - - if (REG_N_DEATHS (old_regno) < 0) - error ("Setting # deaths of register %d to %d\n", - old_regno, REG_N_SETS (old_regno)); - - if (REG_LIVE_LENGTH (old_regno) <= 0) - error ("Setting live length of register %d to %d\n", - old_regno, REG_LIVE_LENGTH (old_regno)); -#endif - - SET_REGNO_REG_SET (old_dead, old_regno); - - /* If this is a user variable, add the range into the list of - different ranges the variable spans. */ - if (RANGE_REG_SYMBOL_NODE (ri, i)) - { - tree sym = RANGE_REG_SYMBOL_NODE (ri, i); - rtx var = DECL_LIVE_RANGE_RTL (sym); - - if (!var) - DECL_LIVE_RANGE_RTL (sym) = var - = gen_rtx (RANGE_VAR, VOIDmode, NULL_RTX, - RANGE_REG_BLOCK_NODE (ri, i), 0); - - RANGE_VAR_NUM (var)++; - RANGE_VAR_LIST (var) = gen_rtx (EXPR_LIST, VOIDmode, ri, - RANGE_VAR_LIST (var)); - } - -#if 0 - /* global.c implements regs_may_share as requiring the registers - to share the same hard register. */ - regs_may_share = gen_rtx (EXPR_LIST, VOIDmode, old_reg, - gen_rtx (EXPR_LIST, VOIDmode, new_reg, - regs_may_share)); -#endif - - /* Create a new scoping block for debug information if needed. */ - if (new_scope_p - && RANGE_REG_SYMBOL_NODE (ri, i) != NULL_TREE - && RANGE_REG_BLOCK_NODE (ri, i) != NULL_TREE) - { - new_scope_p = FALSE; - range_start = emit_note_after (NOTE_INSN_BLOCK_BEG, range_start); - NOTE_BLOCK_NUMBER (range_start) = NOTE_BLOCK_LIVE_RANGE_BLOCK; - - range_end = emit_note_before (NOTE_INSN_BLOCK_END, range_end); - NOTE_BLOCK_NUMBER (range_end) = NOTE_BLOCK_LIVE_RANGE_BLOCK; - - if (stream) - fprintf (stream, "Creating new scoping block\n"); - } - - /* If needed, generate the appropriate copies into and out of - the new register. Tell global.c that we want to share registers - if possible. Since we might be creating a new basic block - for the copyin or copyout, tell local alloc to keep its grubby - paws off of the registers that need copies. */ - if ((RANGE_REG_COPY_FLAGS (ri, i) & LIVE_RANGE_COPYIN) != 0) - { - after - = emit_insn_after (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) - (new_reg, old_reg), after); - - RANGE_REG_LIVE_LENGTH (ri, i)++; - REG_LIVE_LENGTH (old_regno)++; - REG_LIVE_LENGTH (new_regno)++; - REG_N_REFS (old_regno)++; - REG_N_REFS (new_regno)++; - REG_N_SETS (new_regno)++; - REG_N_DEATHS (old_regno)++; - REG_BASIC_BLOCK (new_regno) = REG_BLOCK_GLOBAL; - REG_NOTES (after) = gen_rtx (EXPR_LIST, REG_EQUAL /* REG_EQUIV */, old_reg, - gen_rtx (EXPR_LIST, REG_DEAD, - old_reg, - REG_NOTES (after))); - } - - if ((RANGE_REG_COPY_FLAGS (ri, i) & LIVE_RANGE_COPYOUT) != 0) - { - before - = emit_insn_before (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) - (old_reg, new_reg), before); - - RANGE_REG_LIVE_LENGTH (ri, i)++; - REG_LIVE_LENGTH (old_regno)++; - REG_LIVE_LENGTH (new_regno)++; - REG_N_REFS (old_regno)++; - REG_N_REFS (new_regno)++; - REG_N_SETS (old_regno)++; - REG_N_DEATHS (new_regno)++; - REG_BASIC_BLOCK (new_regno) = REG_BLOCK_GLOBAL; - REG_NOTES (before) = gen_rtx (EXPR_LIST, REG_DEAD, new_reg, - REG_NOTES (before)); - SET_REGNO_REG_SET (copyouts, new_regno); - } - } - - /* Add insns created for copyins to new basic block list, if new copyins - were created, and the insns aren't already part of a basic block. */ - if (range_start != after) - { - int in_bb_p; - rtx end; - - /* If the insns created are the first, add them to the beginning - of the basic block. */ - if (bb_start == 0) - { - rtx temp = get_insns (); - /* Search forward until we hit a CODE_LABEL or real insn. */ - while (! (GET_CODE (temp) == CODE_LABEL - || GET_RTX_CLASS (GET_CODE (temp)) == 'i')) - temp = NEXT_INSN (temp); - BLOCK_HEAD (0) = temp; - } - - - /* Check if the insns are already in the basic block */ - in_bb_p = FALSE; - end = BLOCK_END (bb_start); - for (insn = BLOCK_HEAD (bb_start); - insn && insn != end; - insn = NEXT_INSN (insn)) - { - if (insn == after) - { - in_bb_p = TRUE; - break; - } - } - - /* If needed, create a new basic block. */ - if (!in_bb_p) - { - bb_link *p = &new_bb[new_bb_count++]; - p->first_insn = NEXT_INSN (range_start); - p->last_insn = after; - p->live_at_start = RANGE_INFO_LIVE_START (ri); - } - } - - /* Add insns created for copyouts to new basic block list, if new - copyouts were created, and the insns aren't already part of a basic - block, or can be added to a basic block trivally. */ - if (range_end != before) - { - int in_bb_p = FALSE; - rtx end = BLOCK_END (bb_end); - - /* Check if the insns are already in the basic block */ - for (insn = BLOCK_HEAD (bb_end); - insn && insn != end; - insn = NEXT_INSN (insn)) - { - if (insn == before) - { - in_bb_p = TRUE; - break; - } - } - - /* If needed, create a new basic block. */ - if (!in_bb_p) - { - bb_link *p = &new_bb[new_bb_count++]; - p->first_insn = before; - p->last_insn = PREV_INSN (range_end); - p->live_at_start = OBSTACK_ALLOC_REG_SET (rtl_obstack); - IOR_REG_SET (p->live_at_start, RANGE_INFO_LIVE_END (ri)); - IOR_REG_SET (p->live_at_start, copyouts); - AND_COMPL_REG_SET (p->live_at_start, old_dead); - } - } - - /* Replace the registers */ - for (insn = NEXT_INSN (after); - insn != NULL_RTX && insn != before; - insn = NEXT_INSN (insn)) - { - enum rtx_code code = GET_CODE (insn); - - if (GET_RTX_CLASS (code) == 'i') - { - rtx note; - PATTERN (insn) = replace_regs (PATTERN (insn), replacements, - new_max_regno, TRUE); - - for (note = REG_NOTES (insn); - note != NULL_RTX; - note = XEXP (note, 1)) - { - if ((REG_NOTE_KIND (note) == REG_DEAD - || REG_NOTE_KIND (note) == REG_UNUSED) - && GET_CODE (XEXP (note, 0)) == REG - && replacements[ REGNO (XEXP (note, 0))] != NULL_RTX) - XEXP (note, 0) = replacements[ REGNO (XEXP (note, 0))]; - } - } - } - } - - if (stream) - fflush (stream); - - /* Update # registers */ - max_regno = new_max_regno; - - /* Recalculate basic blocks if we need to. */ - if (new_bb_count) - range_update_basic_block (stream, first_insn, new_bb, - new_bb_count, range_max_regno); - - /* After recreating the basic block, update the live information, - replacing the old registers with the new copies. */ - for (range = live_range_list; range; range = XEXP (range, 1)) - { - rtx range_start = XEXP (range, 0); - rtx ri = NOTE_RANGE_INFO (range_start); - int bb_start = RANGE_INFO_BB_START (ri); - int bb_end = RANGE_INFO_BB_END (ri); - int block; - - bzero ((char *)replacements, new_max_regno * sizeof (rtx)); - CLEAR_REG_SET (old_dead); - for (i = 0; i < (int)RANGE_INFO_NUM_REGS (ri); i++) - { - int old_regno = RANGE_REG_PSEUDO (ri, i); - int new_regno = RANGE_REG_COPY (ri, i); - if (new_regno >= 0) - { - replacements[old_regno] = regno_reg_rtx[new_regno]; - SET_REGNO_REG_SET (old_dead, old_regno); - } - } - - /* Update live information */ - for (block = bb_start+1; block <= bb_end; block++) - { - regset bits = basic_block_live_at_start[block]; - - CLEAR_REG_SET (new_live); - EXECUTE_IF_AND_IN_REG_SET (bits, old_dead, - FIRST_PSEUDO_REGISTER, i, - { - int n = REGNO (replacements[i]); - SET_REGNO_REG_SET (new_live, n); - }); - - AND_COMPL_REG_SET (bits, old_dead); - IOR_REG_SET (bits, new_live); - basic_block_live_at_start[block] = bits; - } - - if (stream) - { - putc ('\n', stream); - live_range_print (stream, ri, "::", ""); - } - } - - /* Add new scoping blocks and reset NOTE_BLOCK_NUMBER field. */ - if (write_symbols != NO_DEBUG) - { - reorder_blocks (block_list, DECL_INITIAL (current_function_decl), - first_insn); - free ((char *)block_list); - } - - /* Release any storage allocated */ - FREE_REG_SET (old_dead); - FREE_REG_SET (new_live); - FREE_REG_SET (copyouts); - - if (stream) - { - putc ('\n', stream); - print_blocks_internal (stream, DECL_INITIAL (current_function_decl), 0); - putc ('\n', stream); - fflush (stream); - } - no_new_pseudos = 1; -} - -/* Main function for live_range support. Return the number of variables that - were spilled to the stack were used in small loops and were copied into new - pseudo registers for the run of that loop. Since we are run after - flow_analysis and local_alloc, we have to set up the appropriate tables for - any new pseudo variables we create. */ - -int -live_range (first_insn, stream) - rtx first_insn; - FILE *stream; -{ - rtx insn; - rtx prev; - rtx next; - rtx loop_start = NULL_RTX; - rtx loop_prefix = NULL_RTX; - int count = 0; - int i; - int basic_block; - int user_block; - int loop_user_block; - int loop_depth; - int range_max_regno; - regset live; - regset simple_insns_live; - regset loop_live; - rtx simple_insns = NULL_RTX; - int *insn_ruid; - int ruid; - - struct skip_flags { - int *flag; - char *reason; - }; - - /* Awkward cases we don't want to handle. */ - static struct skip_flags skip[] = { - { ¤t_function_has_nonlocal_label, "nonlocal label" }, - { ¤t_function_has_nonlocal_goto, "nonlocal goto" }, - { ¤t_function_calls_setjmp, "calls setjmp" }, - { ¤t_function_calls_longjmp, "calls longjmp" } - }; - - for (i = 0; i < (int)(sizeof (skip) / sizeof (skip[0])); i++) - if (*skip[i].flag) - { - if (stream) - fprintf (stream, "Function has %s, skipping live range splitting\n", - skip[i].reason); - - return 0; - } - - if (n_basic_blocks <= 0) - { - if (stream) - fprintf (stream, "Function has no more than 1 basic block, skipping live range splitting\n"); - - return 0; - } - - live_range_list = NULL_RTX; - range_set = ALLOCA_REG_SET (); - range_used = ALLOCA_REG_SET (); - range_mixed_mode = ALLOCA_REG_SET (); - range_no_move = ALLOCA_REG_SET (); - range_live = ALLOCA_REG_SET (); - live = ALLOCA_REG_SET (); - simple_insns_live = ALLOCA_REG_SET (); - loop_live = ALLOCA_REG_SET (); - range_max_regno = max_regno; - range_info = (rinfo *) alloca (sizeof (rinfo) * max_regno); - range_regs = (int *) alloca (sizeof (int) * max_regno); - range_max_uid = (unsigned)get_max_uid (); - range_vars = (var_info *) alloca (sizeof (var_info) * max_regno); - range_block_insn = (bb_link **) alloca (sizeof (bb_link *) * range_max_uid); - range_block_orig = (bb_link *) alloca (sizeof (bb_link) * n_basic_blocks); - bzero ((char *)range_vars, sizeof (var_info) * max_regno); - bzero ((char *)range_block_insn, sizeof (bb_link *) * range_max_uid); - bzero ((char *)range_block_orig, sizeof (bb_link) * n_basic_blocks); - - /* Figure out which basic block things are in. */ - for (i = 0; i < n_basic_blocks; i++) - { - rtx end = BLOCK_END (i); - rtx head = BLOCK_HEAD (i); - range_block_orig[i].block = i; - range_block_orig[i].first_insn = head; - range_block_orig[i].last_insn = end; - range_block_orig[i].live_at_start = basic_block_live_at_start[i]; - - range_block_insn[INSN_UID (end)] = &range_block_orig[i]; - for (insn = head; insn && insn != end; insn = NEXT_INSN (insn)) - range_block_insn[INSN_UID (insn)] = &range_block_orig[i]; - } - - /* Map user variables to their pseudo register */ - range_scan_blocks (DECL_INITIAL (current_function_decl), - DECL_ARGUMENTS (current_function_decl)); - - /* Search for inner loops that do not span logical block boundaries. - Include an non-jump INSNs before the loop to include any setup for the - loop that is not included within the LOOP_BEG note. */ - basic_block = loop_user_block = loop_depth = 0; - user_block = 0; - COPY_REG_SET (live, basic_block_live_at_start[0]); - - insn_ruid = (int *) alloca ((range_max_uid + 1) * sizeof (int)); - bzero ((char *) insn_ruid, (range_max_uid + 1) * sizeof (int)); - ruid = 0; - - for (insn = first_insn; insn; insn = NEXT_INSN (insn)) - { - int block_tmp; - enum rtx_code code = GET_CODE (insn); - - /* This might be a note insn emitted by range_inner, in which case we - can't put it in insn_ruid because that will give an out-of-range - array access. Since we only use it for JUMP_INSNs this should be - OK. */ - - if (INSN_UID (insn) <= range_max_uid) - insn_ruid[INSN_UID (insn)] = ++ruid; - - /* If this is a different basic block, update live variables. */ - block_tmp = RANGE_BLOCK_NUM (insn); - if (block_tmp >= 0 && basic_block != block_tmp) - { - basic_block = block_tmp; - COPY_REG_SET (live, basic_block_live_at_start[basic_block]); - } - - /* Keep track of liveness for simple insns that might preceed LOOP_BEG */ - if (GET_CODE (insn) == INSN && simple_insns == NULL_RTX) - { -#ifdef HAVE_cc0 - if (reg_referenced_p (cc0_rtx, PATTERN (insn))) - simple_insns = NULL_RTX; - else -#endif - { - simple_insns = insn; - COPY_REG_SET (simple_insns_live, live); - } - } - else if (GET_CODE (insn) != INSN) - { - /* Allow simple notes to not zap the simple_insns block */ - if (GET_CODE (insn) != NOTE - || (NOTE_LINE_NUMBER (insn) < 0 - && NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_BEG - && NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)) - simple_insns = NULL_RTX; - } - - /* Update live/dead information. */ - if (GET_RTX_CLASS (code) == 'i') - range_basic_insn (insn, live, range_max_regno); - - /* Look for inner loops */ - else if (code == NOTE) - { - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) - { - /* Add simple insns that occur before the loop begins */ - if (simple_insns) - { - loop_prefix = simple_insns; - COPY_REG_SET (loop_live, simple_insns_live); - } - else - { - loop_prefix = insn; - COPY_REG_SET (loop_live, live); - } - - loop_start = insn; - loop_user_block = user_block; - loop_depth++; - } - - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) - { - loop_depth--; - if (loop_start && loop_user_block == user_block) - { - rtx scan_start; - - /* See whether a new basic block begins with the - next insn -- if so, use its live information. */ - rtx follow_insn, p; - for (follow_insn = NEXT_INSN (insn); - (follow_insn - && ((block_tmp = RANGE_BLOCK_NUM (follow_insn)) < 0 - || block_tmp == basic_block) - && GET_CODE (follow_insn) == NOTE); - follow_insn = NEXT_INSN (follow_insn)) - ; - - if (!follow_insn) - CLEAR_REG_SET (live); - else if (block_tmp >= 0 && block_tmp != basic_block) - COPY_REG_SET (live, basic_block_live_at_start[block_tmp]); - - /* Do not create live ranges for phony loops. The code to - detect phony loops was mostly lifted from scan_loop. - - Try to find the label for the start of the loop. */ - for (p = NEXT_INSN (loop_start); - (p != insn - && GET_CODE (p) != CODE_LABEL - && GET_RTX_CLASS (GET_CODE (p)) != 'i' - && (GET_CODE (p) != NOTE - || (NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_BEG - && NOTE_LINE_NUMBER (p) != NOTE_INSN_LOOP_END))); - p = NEXT_INSN (p)) - ; - - scan_start = p; - - /* Detect a jump to the bottom of the loop. */ - if (GET_CODE (p) == JUMP_INSN) - { - if (simplejump_p (p) - && JUMP_LABEL (p) != 0 - /* Check to see whether the jump actually - jumps out of the loop (meaning it's no loop). - This case can happen for things like do - do {..} while (0). */ - && insn_ruid[INSN_UID (JUMP_LABEL (p))] > 0 - && (insn_ruid[INSN_UID (loop_start)] - <= insn_ruid[INSN_UID (JUMP_LABEL (p))]) - && (insn_ruid[INSN_UID (insn)] - >= insn_ruid[INSN_UID (JUMP_LABEL (p))])) - scan_start = JUMP_LABEL (p); - } - - /* If we did not find the CODE_LABEL for the start of this - loop, then we either have a phony loop or something very - strange has happened. Do not perform LRS opts on such - a loop. */ - if (GET_CODE (scan_start) == CODE_LABEL) - count += range_inner (stream, loop_prefix, insn, loop_start, - insn, loop_live, live, loop_depth); - } - - loop_start = NULL_RTX; - loop_prefix = NULL_RTX; - } - - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) - user_block++; - - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END) - user_block--; - } - } - - /* Reverse list of live ranges so that it goes forwards, not backwards. */ - prev = next = NULL_RTX; - for (insn = live_range_list; insn != NULL_RTX; insn = next) - { - next = XEXP (insn, 1); - XEXP (insn, 1) = prev; - prev = insn; - } - live_range_list = prev; - - /* If we discovered any live ranges, create them now */ - if (count) - range_finish (stream, first_insn, count, range_max_regno); - - FREE_REG_SET (range_set); - FREE_REG_SET (range_used); - FREE_REG_SET (range_live); - FREE_REG_SET (range_mixed_mode); - FREE_REG_SET (range_no_move); - FREE_REG_SET (simple_insns_live); - FREE_REG_SET (loop_live); - FREE_REG_SET (live); - range_block_insn = (bb_link **)0; - range_block_orig = (bb_link *)0; - range_info = (rinfo *)0; - range_regs = (int *)0; - - return count; -} - - -/* Initialize live_range information */ - -void -init_live_range () -{ - live_range_list = NULL_RTX; -} -/* END CYGNUS LOCAL */ diff --git a/gcc/range.h b/gcc/range.h deleted file mode 100755 index 9a48458..0000000 --- a/gcc/range.h +++ /dev/null @@ -1,49 +0,0 @@ -/* CYGNUS LOCAL LRS */ -/* Allocate registers within a basic block, for GNU compiler. - Copyright (C) 1997, 1998 Free Software Foundation, Inc. - -This file is part of GNU CC. - -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. - -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. - -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. */ - -/* Global declarations for live range support. */ -/* Linked list of live ranges to try allocating registers in first before - allocating all of the remaining registers. */ -extern rtx live_range_list; - -/* # of distinct ranges seen so far */ -extern int range_max_unique; - -/* Bits for the different live range copy options. */ -/* Allow copys from original register into new register */ -#define LIVE_RANGE_COPYIN 0x1 - -/* Allow copys from new register back into original register */ -#define LIVE_RANGE_COPYOUT 0x2 - -/* Allow copies from constant integers */ -#define LIVE_RANGE_COPYIN_CONST 0x4 - -/* Default value for creating scoping blocks for live ranges */ -#define LIVE_RANGE_SCOPE_DEFAULT 0 - -/* Live range functions */ -#ifdef BUFSIZ -extern void live_range_print PROTO((FILE *, rtx, char *, char *)); -extern int live_range PROTO((rtx, FILE *)); -#endif -extern void init_live_range PROTO((void)); -/* END CYGNUS LOCAL LRS */ @@ -54,11 +54,7 @@ typedef struct reg_info_def { int live_length; /* # of instructions (REG n) is live */ int calls_crossed; /* # of calls (REG n) is live across */ int basic_block; /* # of basic blocks (REG n) is used in */ - /* CYGNUS LOCAL LRS */ - unsigned range_candidate : 1; /* register is candidate for LRS */ - unsigned range_copy : 1; /* register is a copy generated by LRS */ unsigned changes_size : 1; /* whether (SUBREG (REG n)) changes size */ - /* END CYGNUS LOCAL */ } reg_info; extern varray_type reg_n_info; @@ -90,19 +86,6 @@ extern unsigned int reg_n_max; #define REG_CHANGES_SIZE(N) (VARRAY_REG (reg_n_info, N)->changes_size) -/* CYGNHUS LOCAL LRS */ -/* Indexed by N; says whether a pseudo register is a candidate for - live range splitting. */ - -#define REG_N_RANGE_CANDIDATE_P(N) \ - (VARRAY_REG (reg_n_info, N)->range_candidate) - -/* Indexed by N; says whether a pseudo register is a copy of a register - found during live range splitting. */ - -#define REG_N_RANGE_COPY_P(N) (VARRAY_REG (reg_n_info, N)->range_copy) -/* END CYGNUS LOCAL */ - /* Get the number of consecutive words required to hold pseudo-reg N. */ #define PSEUDO_REGNO_SIZE(N) \ diff --git a/gcc/toplev.c b/gcc/toplev.c index 12dc26c..83437d6 100755 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -51,9 +51,6 @@ Boston, MA 02111-1307, USA. */ #include "except.h" #include "toplev.h" #include "expr.h" -/* CYGNUS LOCAL LRS */ -#include "range.h" -/* END CYGNUS LOCAL */ #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) #include "dwarf2out.h" @@ -231,9 +228,6 @@ int stack_reg_dump = 0; #ifdef MACHINE_DEPENDENT_REORG int mach_dep_reorg_dump = 0; #endif -/* CYGNUS LOCAL LRS */ -int live_range_dump = 0; -/* END CYGNUS LOCAL */ enum graph_dump_types graph_dump_format; /* Name for output file of assembly code, specified with -o. */ @@ -643,14 +637,6 @@ int flag_unaligned_struct_hack = 0; int flag_unaligned_pointers = 0; /* END CYGNUS LOCAL */ -/* CYGNUS LOCAL LRS */ -/* Enable live range splitting. */ -int flag_live_range = 0; - -/* Create scoping blocks for live ranges when debugging. */ -int flag_live_range_scope = LIVE_RANGE_SCOPE_DEFAULT; -/* END CYGNUS LOCAL */ - /* Tag all structures with __attribute__(packed) */ int flag_pack_struct = 0; @@ -855,12 +841,6 @@ lang_independent_options f_options[] = "Enables a register move optimisation"}, {"optimize-register-move", &flag_regmove, 1, "Do the full regmove optimization pass"}, - /* CYGNUS LOCAL LRS */ - {"live-range", &flag_live_range, 1, - "Enable live range splitting" }, - {"live-range-scope", &flag_live_range_scope, 1, - "Create scope blocks for debugging live ranges"}, - /* END CYGNUS LOCAL */ {"pack-struct", &flag_pack_struct, 1, "Pack structure members together without holes" }, {"stack-check", &flag_stack_check, 1, @@ -1175,10 +1155,7 @@ int stack_reg_time; int final_time; int symout_time; int dump_time; -/* CYGNUS LOCAL LRS */ -int live_range_time; -/* END CYGNUS LOCAL */ - + /* Return time used so far, in microseconds. */ long @@ -2503,12 +2480,6 @@ compile_file (name) if (flag_caller_saves) init_caller_save (); - /* CYGNUS LOCAL LRS */ - /* Clear out live range data if needed */ - if (flag_live_range) - init_live_range (); - /* END CYGNUS LOCAL */ - /* If auxiliary info generation is desired, open the output file. This goes in the same directory as the source file--unlike all the other output files. */ @@ -2639,10 +2610,6 @@ compile_file (name) clean_graph_dump_file (dump_base_name, ".mach"); } #endif - /* CYGNUS LOCAL LRS */ - if (live_range_dump) - clean_dump_file (".range"); - /* END CYGNUS LOCAL */ /* Open assembler code output file. */ @@ -3094,9 +3061,6 @@ compile_file (name) print_time ("combine", combine_time); print_time ("regmove", regmove_time); print_time ("sched", sched_time); - /* CYGNUS LOCAL LRS */ - print_time ("live-range", live_range_time); - /* END CYGNUS LOCAL */ print_time ("local-alloc", local_alloc_time); print_time ("global-alloc", global_alloc_time); print_time ("sched2", sched2_time); @@ -3726,38 +3690,13 @@ rest_of_compilation (decl) } } - /* CYGNUS LOCAL LRS */ - if (optimize > 0 && flag_live_range && !obey_regdecls) - { - if (live_range_dump) - open_dump_file (".range", decl_printable_name (decl, 2)); - - /* Get accurate register usage information. */ - TIMEVAR (live_range_time, recompute_reg_usage (insns, !optimize_size)); - TIMEVAR (live_range_time, live_range (insns, rtl_dump_file)); - - if (live_range_dump) - close_dump_file (print_rtl_with_bb, insns); - } - /* END CYGNUS LOCAL */ - /* Unless we did stupid register allocation, allocate pseudo-regs that are used only within 1 basic block. */ if (!obey_regdecls) TIMEVAR (local_alloc_time, { - /* CYGNUS LOCAL LRS */ - /* If we are splitting live ranges, then we want to get the - register usage information accurate before splitting. - - ??? We must leave it inaccurate after splitting for now - as undo_live_range assumes that it does not need to update - the usage information for the LRS candidate after undoing - a live range. */ - if (!flag_live_range) - recompute_reg_usage (insns, !optimize_size); - /* END CYGNUS LOCAL */ + recompute_reg_usage (insns, !optimize_size); regclass (insns, max_reg_num ()); local_alloc (); }); @@ -4040,11 +3979,6 @@ rest_of_compilation (decl) /* Show no temporary slots allocated. */ init_temp_slots (); - /* CYGNUS LOCAL LRS */ - /* Clear out live range data if needed. */ - if (flag_live_range) - init_live_range (); - /* Release all memory held by regsets. */ regset_release_memory (); /* END CYGNUS LOCAL */ @@ -4434,15 +4368,6 @@ main (argc, argv) flag_rerun_loop_opt = 1; flag_caller_saves = 1; flag_force_mem = 1; - /* CYGNUS LOCAL LRS */ - /* Right now we can only support deubgging of LRS code using stabs - extensions. So LRS is enabled by default only for targets which - prefer stabs debug symbols. - - If/when we add LRS support to our dwarf2 code we can enable LRS - optimizations for more targets. */ - flag_live_range = (PREFERRED_DEBUGGING_TYPE == DBX_DEBUG); - /* END CYGNUS LOCAL */ #ifdef INSN_SCHEDULING flag_schedule_insns = 1; flag_schedule_insns_after_reload = 1; @@ -4526,9 +4451,6 @@ main (argc, argv) rtl_dump = 1; cse_dump = 1, cse2_dump = 1; gcse_dump = 1; - /* CYGNUS LOCAL LRS/law */ - live_range_dump = 1; - /* END CYGNUS LOCAL */ sched_dump = 1; sched2_dump = 1; #ifdef STACK_REGS @@ -4567,11 +4489,6 @@ main (argc, argv) case 'J': jump2_opt_dump = 1; break; - /* CYGNUS LOCAL LRS */ - case 'K': - live_range_dump = 1; - break; - /* END CYGNUS LOCAL */ #ifdef STACK_REGS case 'k': stack_reg_dump = 1; |