summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rwxr-xr-xgcc/Makefile.in23
-rwxr-xr-xgcc/final.c23
-rwxr-xr-xgcc/flags.h11
-rwxr-xr-xgcc/global.c531
-rwxr-xr-xgcc/range.c1931
-rwxr-xr-xgcc/range.h49
-rwxr-xr-xgcc/regs.h17
-rwxr-xr-xgcc/toplev.c87
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[] = {
- { &current_function_has_nonlocal_label, "nonlocal label" },
- { &current_function_has_nonlocal_goto, "nonlocal goto" },
- { &current_function_calls_setjmp, "calls setjmp" },
- { &current_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 */
diff --git a/gcc/regs.h b/gcc/regs.h
index 5f5c38b..2b72a44 100755
--- a/gcc/regs.h
+++ b/gcc/regs.h
@@ -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;