#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "machmode.h"
#include "hard-reg-set.h"
1. Assign allocation-numbers (allocnos) to the pseudo-registers
still needing allocations and to the pseudo-registers currently
allocated by local-alloc which may be spilled by reload.
- Set up tables reg_allocno and allocno_reg to map
+ Set up tables reg_allocno and allocno_reg to map
reg numbers to allocnos and vice versa.
max_allocno gets the number of allocnos in use.
/* Set of hard registers that some later allocno has a preference for. */
HARD_REG_SET regs_someone_prefers;
+
+#ifdef STACK_REGS
+ /* Set to true if allocno can't be allocated in the stack register. */
+ bool no_stack_reg;
+#endif
};
static struct allocno *allocno;
(conflicts[(I) * allocno_row_words + (unsigned) (J) / INT_BITS] \
& ((INT_TYPE) 1 << ((unsigned) (J) % INT_BITS)))
-#define SET_CONFLICT(I, J) \
- (conflicts[(I) * allocno_row_words + (unsigned) (J) / INT_BITS] \
- |= ((INT_TYPE) 1 << ((unsigned) (J) % INT_BITS)))
-
/* For any allocno set in ALLOCNO_SET, set ALLOCNO to that allocno,
and execute CODE. */
#define EXECUTE_IF_SET_IN_ALLOCNO_SET(ALLOCNO_SET, ALLOCNO, CODE) \
static int local_reg_live_length[FIRST_PSEUDO_REGISTER];
-/* Test a bit in TABLE, a vector of HARD_REG_SETs,
- for vector element I, and hard register number J. */
-
-#define REGBITP(TABLE, I, J) TEST_HARD_REG_BIT (allocno[I].TABLE, J)
-
-/* Set to 1 a bit in a vector of HARD_REG_SETs. Works like REGBITP. */
+/* Set to 1 a bit in a vector TABLE of HARD_REG_SETs, for vector
+ element I, and hard register number J. */
#define SET_REGBIT(TABLE, I, J) SET_HARD_REG_BIT (allocno[I].TABLE, J)
/* Test, set or clear bit number I in allocnos_live,
a bit vector indexed by allocno. */
-#define ALLOCNO_LIVE_P(I) \
- (allocnos_live[(unsigned) (I) / INT_BITS] \
- & ((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
-
#define SET_ALLOCNO_LIVE(I) \
(allocnos_live[(unsigned) (I) / INT_BITS] \
|= ((INT_TYPE) 1 << ((unsigned) (I) % INT_BITS)))
that need a register window. So prefer the ones that can be used in
a leaf function. */
{
- char *cheap_regs;
- char *leaf_regs = LEAF_REGISTERS;
+ const char *cheap_regs;
+ const char *const leaf_regs = LEAF_REGISTERS;
if (only_leaf_regs_used () && leaf_function_p ())
cheap_regs = leaf_regs;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (regs_ever_live[i])
local_reg_n_refs[i] = 0, local_reg_freq[i] = 0;
-
+
allocno_row_words = (max_allocno + INT_BITS - 1) / INT_BITS;
/* We used to use alloca here, but the size of what it would try to
}
qsort (allocno_order, max_allocno, sizeof (int), allocno_compare);
-
+
prune_preferences ();
if (file)
#if 0 /* We need to eliminate regs even if there is no rtl code,
for the sake of debugging information. */
- if (num_basic_blocks > 0)
+ if (n_basic_blocks > 0)
#endif
{
build_insn_chain (get_insns ());
block_start_allocnos = (int *) xmalloc (max_allocno * sizeof (int));
- FOR_ALL_BB (b)
+ FOR_EACH_BB (b)
{
memset ((char *) allocnos_live, 0, allocno_row_words * sizeof (INT_TYPE));
2. Y is live at some instruction on the path that
evaluates X.
- 3. Either X or Y is not evaluted on the path to P
+ 3. Either X or Y is not evaluated on the path to P
(ie it is used uninitialized) and thus the
conflict can be ignored.
if (e->flags & EDGE_ABNORMAL)
break;
if (e != NULL)
- for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
- record_one_conflict (ax);
+ {
+ EXECUTE_IF_SET_IN_ALLOCNO_SET (allocnos_live, ax,
+ {
+ allocno[ax].no_stack_reg = 1;
+ });
+ for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
+ record_one_conflict (ax);
+ }
}
#endif
}
\f
/* Prune the preferences for global registers to exclude registers that cannot
be used.
-
+
Compute `regs_someone_prefers', which is a bitmask of the hard registers
that are preferred by conflicting registers of lower priority. If possible,
we will avoid using these registers. */
-
+
static void
prune_preferences ()
{
int i;
int num;
int *allocno_to_order = (int *) xmalloc (max_allocno * sizeof (int));
-
+
/* Scan least most important to most important.
For each allocno, remove from preferences registers that cannot be used,
either because of conflicts or register type. Then compute all registers
of a long enough stretch of hard regs none of which conflicts with ALLOCNO.
The registers marked in PREFREGS are tried first.
- LOSERS, if non-zero, is a HARD_REG_SET indicating registers that cannot
+ LOSERS, if nonzero, is a HARD_REG_SET indicating registers that cannot
be used for this allocation.
If ALT_REGS_P is zero, consider only the preferred class of ALLOCNO's reg.
int retrying;
{
int i, best_reg, pass;
-#ifdef HARD_REG_SET
- register /* Declare it register if it's a scalar. */
-#endif
- HARD_REG_SET used, used1, used2;
+ HARD_REG_SET used, used1, used2;
enum reg_class class = (alt_regs_p
? reg_alternate_class (allocno[num].reg)
IOR_HARD_REG_SET (used1, allocno[num].hard_reg_conflicts);
-#ifdef CLASS_CANNOT_CHANGE_MODE
- if (REG_CHANGES_MODE (allocno[num].reg))
- IOR_HARD_REG_SET (used1,
- reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE]);
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ cannot_change_mode_set_regs (&used1, mode, allocno[num].reg);
#endif
/* Try each hard reg to see if it fits. Do this in two passes.
COPY_HARD_REG_SET (used, used1);
IOR_COMPL_HARD_REG_SET (used, regs_used_so_far);
IOR_HARD_REG_SET (used, allocno[num].regs_someone_prefers);
-
+
best_reg = -1;
for (i = FIRST_PSEUDO_REGISTER, pass = 0;
pass <= 1 && i >= FIRST_PSEUDO_REGISTER;
Remove from the preferred registers and conflicting registers. Note that
additional conflicts may have been added after `prune_preferences' was
- called.
+ called.
First do this for those register with copy preferences, then all
preferred registers. */
}
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. */
CLEAR_HARD_REG_SET (new_losers);
else
COPY_HARD_REG_SET (new_losers, losers);
-
+
IOR_HARD_REG_SET(new_losers, losing_caller_save_reg_set);
find_reg (num, new_losers, alt_regs_p, 1, retrying);
if (reg_renumber[allocno[num].reg] >= 0)
/* Don't use a reg no good for this pseudo. */
&& ! TEST_HARD_REG_BIT (used2, regno)
&& HARD_REGNO_MODE_OK (regno, mode)
+ /* The code below assumes that we need only a single
+ register, but the check of allocno[num].size above
+ was not enough. Sometimes we need more than one
+ register for a single-word value. */
+ && HARD_REGNO_NREGS (regno, mode) == 1
&& (allocno[num].calls_crossed == 0
|| accept_call_clobbered
|| ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
-#ifdef CLASS_CANNOT_CHANGE_MODE
- && ! (REG_CHANGES_MODE (allocno[num].reg)
- && (TEST_HARD_REG_BIT
- (reg_class_contents[(int) CLASS_CANNOT_CHANGE_MODE],
- regno)))
+#ifdef CANNOT_CHANGE_MODE_CLASS
+ && ! invalid_mode_change_p (regno, REGNO_REG_CLASS (regno),
+ mode)
+#endif
+#ifdef STACK_REGS
+ && (!allocno[num].no_stack_reg
+ || regno < FIRST_STACK_REG || regno > LAST_STACK_REG)
#endif
)
{
/* We explicitly evaluate the divide results into temporary
variables so as to avoid excess precision problems that occur
on an i386-unknown-sysv4.2 (unixware) host. */
-
+
double tmp1 = ((double) local_reg_freq[regno]
/ local_reg_live_length[regno]);
double tmp2 = ((double) allocno[num].freq
int *allocno_vec;
int len;
{
- int num;
- int ialloc_prod;
-
while (--len >= 0)
- {
- num = allocno_vec[len];
- ialloc_prod = num * allocno_row_words;
- IOR_HARD_REG_SET (allocno[num].hard_reg_conflicts, hard_regs_live);
- }
+ IOR_HARD_REG_SET (allocno[allocno_vec[len]].hard_reg_conflicts,
+ hard_regs_live);
}
/* If CONFLICTP (i, j) is true, make sure CONFLICTP (j, i) is also true. */
that SRC is a register. If SRC or the first operand of SRC is a register,
try to set a preference. If one of the two is a hard register and the other
is a pseudo-register, mark the preference.
-
+
Note that we are not as aggressive as local-alloc in trying to tie a
pseudo-register to a hard register. */
{
basic_block bb;
- FOR_ALL_BB (bb)
+ FOR_EACH_BB (bb)
{
- regset r = bb->global_live_at_start;
+ regset r = bb->global_live_at_start;
if (REGNO_REG_SET_P (r, from))
{
CLEAR_REGNO_REG_SET (r, from);
if (GET_CODE (reg) != REG)
return;
-
+
regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
{
: reg_renumber[i] >= 0)
SET_REGNO_REG_SET (live_relevant_regs, i);
});
- }
+ }
if (GET_CODE (first) != NOTE && GET_CODE (first) != BARRIER)
{
*p = c;
p = &c->next;
c->insn = first;
- c->block = b->sindex;
+ c->block = b->index;
if (INSN_P (first))
{
for (i = 0; i < max_allocno; i++)
{
if (reg_renumber[allocno[allocno_order[i]].reg] >= 0)
- continue;
+ continue;
nregs++;
}
fprintf (file, ";; %d regs to allocate:", nregs);
FILE *file;
{
int i, j;
-
+
fprintf (file, ";; Register dispositions:\n");
for (i = FIRST_PSEUDO_REGISTER, j = 0; i < max_regno; i++)
if (reg_renumber[i] >= 0)
{
fprintf (file, "%d in %d ", i, reg_renumber[i]);
- if (++j % 6 == 0)
+ if (++j % 6 == 0)
fprintf (file, "\n");
}