/* Allocate registers for pseudo-registers that span basic blocks.
- Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1988, 1991, 1994 Free Software Foundation, Inc.
This file is part of GNU CC.
static rtx *regs_set;
static int n_regs_set;
-/* All register that can be eliminated. */
+/* All registers that can be eliminated. */
static HARD_REG_SET eliminable_regset;
-static int allocno_compare ();
-static void mark_reg_store ();
-static void mark_reg_clobber ();
-static void mark_reg_conflicts ();
-static void mark_reg_live_nc ();
-static void mark_reg_death ();
-static void dump_conflicts ();
-void dump_global_regs ();
-static void find_reg ();
-static void global_conflicts ();
-static void expand_preferences ();
-static void prune_preferences ();
-static void record_conflicts ();
-static void set_preference ();
+static int allocno_compare PROTO((int *, int *));
+static void global_conflicts PROTO((void));
+static void expand_preferences PROTO((void));
+static void prune_preferences PROTO((void));
+static void find_reg PROTO((int, HARD_REG_SET, int, int, int));
+static void record_one_conflict PROTO((int));
+static void record_conflicts PROTO((short *, int));
+static void mark_reg_store PROTO((rtx, rtx));
+static void mark_reg_clobber PROTO((rtx, rtx));
+static void mark_reg_conflicts PROTO((rtx));
+static void mark_reg_death PROTO((rtx));
+static void mark_reg_live_nc PROTO((int, enum machine_mode));
+static void set_preference PROTO((rtx, rtx));
+static void dump_conflicts PROTO((FILE *));
\f
/* Perform allocation of pseudo-registers not allocated by local_alloc.
FILE is a file to output debugging information on,
#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);
+
register int i;
rtx x;
SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
if (! CAN_ELIMINATE (eliminables[i].from, eliminables[i].to)
- || (eliminables[i].from == FRAME_POINTER_REGNUM
- && (! flag_omit_frame_pointer || FRAME_POINTER_REQUIRED)))
+ || (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 we know we will definitely not be eliminating the frame pointer,
- don't allocate it. */
- if (! flag_omit_frame_pointer || FRAME_POINTER_REQUIRED)
+ if (need_fp)
SET_HARD_REG_BIT (no_global_alloc_regs, FRAME_POINTER_REGNUM);
#endif
/* Initialize the shared-hard-reg mapping
from the list of pairs that may share. */
reg_may_share = (int *) alloca (max_regno * sizeof (int));
- bzero (reg_may_share, 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));
allocno_calls_crossed = (int *) alloca (max_allocno * sizeof (int));
allocno_n_refs = (int *) alloca (max_allocno * sizeof (int));
allocno_live_length = (int *) alloca (max_allocno * sizeof (int));
- bzero (allocno_size, max_allocno * sizeof (int));
- bzero (allocno_calls_crossed, max_allocno * sizeof (int));
- bzero (allocno_n_refs, max_allocno * sizeof (int));
- bzero (allocno_live_length, max_allocno * sizeof (int));
+ bzero ((char *) allocno_size, max_allocno * sizeof (int));
+ bzero ((char *) allocno_calls_crossed, max_allocno * sizeof (int));
+ bzero ((char *) allocno_n_refs, max_allocno * sizeof (int));
+ bzero ((char *) allocno_live_length, max_allocno * sizeof (int));
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_allocno[i] >= 0)
/* Calculate amount of usage of each hard reg by pseudos
allocated by local-alloc. This is to see if we want to
override it. */
- bzero (local_reg_live_length, sizeof local_reg_live_length);
- bzero (local_reg_n_refs, sizeof local_reg_n_refs);
+ bzero ((char *) local_reg_live_length, sizeof local_reg_live_length);
+ bzero ((char *) local_reg_n_refs, sizeof local_reg_n_refs);
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_allocno[i] < 0 && reg_renumber[i] >= 0)
{
hard_reg_conflicts
= (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
- bzero (hard_reg_conflicts, max_allocno * sizeof (HARD_REG_SET));
+ bzero ((char *) hard_reg_conflicts, max_allocno * sizeof (HARD_REG_SET));
hard_reg_preferences
= (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
- bzero (hard_reg_preferences, max_allocno * sizeof (HARD_REG_SET));
+ bzero ((char *) hard_reg_preferences, max_allocno * sizeof (HARD_REG_SET));
hard_reg_copy_preferences
= (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
- bzero (hard_reg_copy_preferences, max_allocno * sizeof (HARD_REG_SET));
+ bzero ((char *) hard_reg_copy_preferences,
+ max_allocno * sizeof (HARD_REG_SET));
hard_reg_full_preferences
= (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
- bzero (hard_reg_full_preferences, max_allocno * sizeof (HARD_REG_SET));
+ bzero ((char *) hard_reg_full_preferences,
+ max_allocno * sizeof (HARD_REG_SET));
regs_someone_prefers
= (HARD_REG_SET *) alloca (max_allocno * sizeof (HARD_REG_SET));
- bzero (regs_someone_prefers, max_allocno * sizeof (HARD_REG_SET));
+ bzero ((char *) regs_someone_prefers, max_allocno * sizeof (HARD_REG_SET));
allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
conflicts = (INT_TYPE *) alloca (max_allocno * allocno_row_words
* sizeof (INT_TYPE));
- bzero (conflicts, max_allocno * allocno_row_words
- * sizeof (INT_TYPE));
+ bzero ((char *) conflicts,
+ max_allocno * allocno_row_words * sizeof (INT_TYPE));
allocnos_live = (INT_TYPE *) alloca (allocno_row_words * sizeof (INT_TYPE));
Multiplying this by 10000 can't overflow. */
register int pri1
= (((double) (floor_log2 (allocno_n_refs[*v1]) * allocno_n_refs[*v1])
- / (allocno_live_length[*v1] * allocno_size[*v1]))
- * 10000);
+ / allocno_live_length[*v1])
+ * 10000 * allocno_size[*v1]);
register int pri2
= (((double) (floor_log2 (allocno_n_refs[*v2]) * allocno_n_refs[*v2])
- / (allocno_live_length[*v2] * allocno_size[*v2]))
- * 10000);
+ / allocno_live_length[*v2])
+ * 10000 * allocno_size[*v2]);
if (pri2 - pri1)
return pri2 - pri1;
for (b = 0; b < n_basic_blocks; b++)
{
- bzero (allocnos_live, allocno_row_words * sizeof (INT_TYPE));
+ bzero ((char *) allocnos_live, allocno_row_words * sizeof (INT_TYPE));
/* Initialize table of registers currently live
to the state at the beginning of this basic block.
if (code == INSN || code == CALL_INSN || code == JUMP_INSN)
{
- int i = 0;
#if 0
+ int i = 0;
for (link = REG_NOTES (insn);
link && i < NUM_NO_CONFLICT_PAIRS;
link = XEXP (link, 1))
}
no_prefs:
- /* If we haven't succeeded yet, try with caller-saves. */
+ /* If we haven't succeeded yet, try with caller-saves.
+ We need not check to see if the current function has nonlocal
+ labels because we don't put any pseudos that are live over calls in
+ registers in that case. */
+
if (flag_caller_saves && best_reg < 0)
{
/* Did not find a register. If it would be profitable to
{
/* Count from the end, to find the least-used ones first. */
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
- if (local_reg_n_refs[i] != 0
- /* Don't use a reg no good for this pseudo. */
- && ! TEST_HARD_REG_BIT (used2, i)
- && HARD_REGNO_MODE_OK (i, mode)
- && ((double) local_reg_n_refs[i] / local_reg_live_length[i]
- < ((double) allocno_n_refs[allocno]
- / allocno_live_length[allocno])))
- {
- /* Hard reg I was used less in total by local regs
- than it would be used by this one allocno! */
- int k;
- for (k = 0; k < max_regno; k++)
- if (reg_renumber[k] >= 0)
- {
- int regno = reg_renumber[k];
- int endregno
- = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (k));
+ {
+#ifdef REG_ALLOC_ORDER
+ int regno = reg_alloc_order[i];
+#else
+ int regno = i;
+#endif
- if (i >= regno && i < endregno)
- reg_renumber[k] = -1;
- }
+ if (local_reg_n_refs[regno] != 0
+ /* Don't use a reg no good for this pseudo. */
+ && ! TEST_HARD_REG_BIT (used2, regno)
+ && HARD_REGNO_MODE_OK (regno, mode)
+ && (((double) local_reg_n_refs[regno]
+ / local_reg_live_length[regno])
+ < ((double) allocno_n_refs[allocno]
+ / allocno_live_length[allocno])))
+ {
+ /* Hard reg REGNO was used less in total by local regs
+ than it would be used by this one allocno! */
+ int k;
+ for (k = 0; k < max_regno; k++)
+ if (reg_renumber[k] >= 0)
+ {
+ int r = reg_renumber[k];
+ int endregno
+ = r + HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (k));
- best_reg = i;
- break;
- }
+ if (regno >= r && regno < endregno)
+ reg_renumber[k] = -1;
+ }
+
+ best_reg = regno;
+ break;
+ }
+ }
}
/* Did we find a register? */