#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "machmode.h"
#include "hard-reg-set.h"
/* 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;
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;
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.
scan the instruction that makes either X or Y become live. */
record_conflicts (block_start_allocnos, ax);
-#ifdef STACK_REGS
+ /* Pseudos can't go in stack regs at the start of a basic block that
+ is reached by an abnormal edge. Likewise for call clobbered regs,
+ because because caller-save, fixup_abnormal_edges, and possibly
+ the table driven EH machinery are not quite ready to handle such
+ regs live across such edges. */
{
- /* Pseudos can't go in stack regs at the start of a basic block
- that is reached by an abnormal edge. */
-
edge e;
+
for (e = b->pred; e ; e = e->pred_next)
if (e->flags & EDGE_ABNORMAL)
break;
+
if (e != NULL)
- for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
- record_one_conflict (ax);
- }
+ {
+#ifdef STACK_REGS
+ 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
+
+ /* No need to record conflicts for call clobbered regs if we have
+ nonlocal labels around, as we don't ever try to allocate such
+ regs in this case. */
+ if (! current_function_has_nonlocal_label)
+ for (ax = 0; ax < FIRST_PSEUDO_REGISTER; ax++)
+ if (call_used_regs [ax])
+ record_one_conflict (ax);
+ }
+ }
}
insn = b->head;
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.
/* 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
)
{
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. */