/* Allocate registers within a basic block, for GNU compiler.
Copyright (C) 1987, 1988, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of GCC.
#include "output.h"
#include "toplev.h"
#include "except.h"
+#include "integrate.h"
\f
/* Next quantity number available for allocation. */
static int next_qty;
-/* Information we maitain about each quantity. */
+/* Information we maintain about each quantity. */
struct qty
{
/* The number of refs to quantity Q. */
enum machine_mode mode;
int size, birth;
{
- register int qtyno = next_qty++;
+ int qtyno = next_qty++;
reg_qty[regno] = qtyno;
reg_offset[regno] = 0;
int
local_alloc ()
{
- register int b, i;
+ int b, i;
int max_qty;
/* We need to keep track of whether or not we recorded a LABEL_REF so
reg_offset = (char *) xmalloc (max_regno * sizeof (char));
reg_next_in_qty = (int *) xmalloc (max_regno * sizeof (int));
- /* Allocate the reg_renumber array. */
- allocate_reg_info (max_regno, FALSE, TRUE);
-
/* Determine which pseudo-registers can be allocated by local-alloc.
In general, these are the registers used only in a single block and
which only die once.
equiv_init_varies_p (x)
rtx x;
{
- register RTX_CODE code = GET_CODE (x);
- register int i;
- register const char *fmt;
+ RTX_CODE code = GET_CODE (x);
+ int i;
+ const char *fmt;
switch (code)
{
}
\f
/* Return nonzero if the rtx X is invariant over the current function. */
+/* ??? Actually, the places this is used in reload expect exactly what
+ is tested here, and not everything that is function invariant. In
+ particular, the frame pointer and arg pointer are special cased;
+ pic_offset_table_rtx is not, and this will cause aborts when we
+ go to spill these things to memory. */
+
int
function_invariant_p (x)
rtx x;
REG_EQUAL note on the insn. Since this note would be redundant,
there's no point creating it earlier than here. */
if (! note && ! rtx_varies_p (src, 0))
- REG_NOTES (insn)
- = note = gen_rtx_EXPR_LIST (REG_EQUAL, src, REG_NOTES (insn));
+ note = set_unique_reg_note (insn, REG_EQUAL, src);
/* Don't bother considering a REG_EQUAL note containing an EXPR_LIST
since it represents a function call */
remove_death (regno, insn);
REG_N_REFS (regno) = 0;
REG_FREQ (regno) = 0;
- PUT_CODE (equiv_insn, NOTE);
- NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (equiv_insn) = 0;
+ delete_insn (equiv_insn);
reg_equiv[regno].init_insns
= XEXP (reg_equiv[regno].init_insns, 1);
otherwise eliminate_regs_in_insn will abort. */
INSN_CODE (new_insn) = INSN_CODE (equiv_insn);
- PUT_CODE (equiv_insn, NOTE);
- NOTE_LINE_NUMBER (equiv_insn) = NOTE_INSN_DELETED;
- NOTE_SOURCE_FILE (equiv_insn) = 0;
+ delete_insn (equiv_insn);
XEXP (reg_equiv[regno].init_insns, 0) = new_insn;
block_alloc (b)
int b;
{
- register int i, q;
- register rtx insn;
- rtx note;
+ int i, q;
+ rtx insn;
+ rtx note, hard_reg;
int insn_number = 0;
int insn_count = 0;
int max_uid = get_max_uid ();
if (INSN_P (insn))
{
- register rtx link, set;
- register int win = 0;
- register rtx r0, r1 = NULL_RTX;
+ rtx link, set;
+ int win = 0;
+ rtx r0, r1 = NULL_RTX;
int combined_regno = -1;
int i;
for (i = 1; i < recog_data.n_operands; i++)
{
const char *p = recog_data.constraints[i];
- int this_match = (requires_inout (p));
+ int this_match = requires_inout (p);
n_matching_alts += this_match;
if (this_match == recog_data.n_alternatives)
while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
r1 = XEXP (r1, 0);
+ /* Avoid making a call-saved register unnecessarily
+ clobbered. */
+ hard_reg = get_hard_reg_initial_reg (cfun, r1);
+ if (hard_reg != NULL_RTX)
+ {
+ if (GET_CODE (hard_reg) == REG
+ && IN_RANGE (REGNO (hard_reg),
+ 0, FIRST_PSEUDO_REGISTER - 1)
+ && ! call_used_regs[REGNO (hard_reg)])
+ continue;
+ }
+
if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
{
/* We have two priorities for hard register preferences.
discourage the register allocator from creating false
dependencies.
- The adjustment value is choosen to indicate that this qty
+ The adjustment value is chosen to indicate that this qty
conflicts with all the qtys in the instructions immediately
before and after the lifetime of this qty.
const PTR q1p;
const PTR q2p;
{
- register int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
- register int tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
+ int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
+ int tem = QTY_CMP_PRI (q2) - QTY_CMP_PRI (q1);
if (tem != 0)
return tem;
qty_sugg_compare (q1, q2)
int q1, q2;
{
- register int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
+ int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
if (tem != 0)
return tem;
const PTR q1p;
const PTR q2p;
{
- register int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
- register int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
+ int q1 = *(const int *) q1p, q2 = *(const int *) q2p;
+ int tem = QTY_CMP_SUGG (q1) - QTY_CMP_SUGG (q2);
if (tem != 0)
return tem;
rtx insn;
int already_dead;
{
- register int ureg, sreg;
- register int offset = 0;
+ int ureg, sreg;
+ int offset = 0;
int usize, ssize;
- register int sqty;
+ int sqty;
/* Determine the numbers and sizes of registers being used. If a subreg
is present that does not change the entire register, don't consider
while (GET_CODE (usedreg) == SUBREG)
{
- if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (usedreg))) > UNITS_PER_WORD)
- may_save_copy = 0;
- if (REGNO (SUBREG_REG (usedreg)) < FIRST_PSEUDO_REGISTER)
- offset += subreg_regno_offset (REGNO (SUBREG_REG (usedreg)),
- GET_MODE (SUBREG_REG (usedreg)),
- SUBREG_BYTE (usedreg),
- GET_MODE (usedreg));
- else
- offset += (SUBREG_BYTE (usedreg)
- / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
- usedreg = SUBREG_REG (usedreg);
+ rtx subreg = SUBREG_REG (usedreg);
+
+ if (GET_CODE (subreg) == REG)
+ {
+ if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
+ may_save_copy = 0;
+
+ if (REGNO (subreg) < FIRST_PSEUDO_REGISTER)
+ offset += subreg_regno_offset (REGNO (subreg),
+ GET_MODE (subreg),
+ SUBREG_BYTE (usedreg),
+ GET_MODE (usedreg));
+ else
+ offset += (SUBREG_BYTE (usedreg)
+ / REGMODE_NATURAL_SIZE (GET_MODE (usedreg)));
+ }
+
+ usedreg = subreg;
}
+
if (GET_CODE (usedreg) != REG)
return 0;
+
ureg = REGNO (usedreg);
if (ureg < FIRST_PSEUDO_REGISTER)
usize = HARD_REGNO_NREGS (ureg, GET_MODE (usedreg));
while (GET_CODE (setreg) == SUBREG)
{
- if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (setreg))) > UNITS_PER_WORD)
- may_save_copy = 0;
- if (REGNO (SUBREG_REG (setreg)) < FIRST_PSEUDO_REGISTER)
- offset -= subreg_regno_offset (REGNO (SUBREG_REG (setreg)),
- GET_MODE (SUBREG_REG (setreg)),
- SUBREG_BYTE (setreg),
- GET_MODE (setreg));
- else
- offset -= (SUBREG_BYTE (setreg)
- / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
- setreg = SUBREG_REG (setreg);
+ rtx subreg = SUBREG_REG (setreg);
+
+ if (GET_CODE (subreg) == REG)
+ {
+ if (GET_MODE_SIZE (GET_MODE (subreg)) > UNITS_PER_WORD)
+ may_save_copy = 0;
+
+ if (REGNO (subreg) < FIRST_PSEUDO_REGISTER)
+ offset -= subreg_regno_offset (REGNO (subreg),
+ GET_MODE (subreg),
+ SUBREG_BYTE (setreg),
+ GET_MODE (setreg));
+ else
+ offset -= (SUBREG_BYTE (setreg)
+ / REGMODE_NATURAL_SIZE (GET_MODE (setreg)));
+ }
+
+ setreg = subreg;
}
+
if (GET_CODE (setreg) != REG)
return 0;
+
sreg = REGNO (setreg);
if (sreg < FIRST_PSEUDO_REGISTER)
ssize = HARD_REGNO_NREGS (sreg, GET_MODE (setreg));
qty[sqty].freq += REG_FREQ (sreg);
if (usize < ssize)
{
- register int i;
+ int i;
for (i = qty[sqty].first_reg; i >= 0; i = reg_next_in_qty[i])
reg_offset[i] -= offset;
int reg;
enum reg_class class;
{
- register enum reg_class rclass = reg_preferred_class (reg);
+ enum reg_class rclass = reg_preferred_class (reg);
return (reg_class_subset_p (rclass, class)
|| reg_class_subset_p (class, rclass));
}
rtx reg;
int birth;
{
- register int regno;
+ int regno;
if (GET_CODE (reg) == SUBREG)
{
static void
wipe_dead_reg (reg, output_p)
- register rtx reg;
+ rtx reg;
int output_p;
{
- register int regno = REGNO (reg);
+ int regno = REGNO (reg);
/* If this insn has multiple results,
and the dead reg is used in one of the results,
int just_try_suggested;
int born_index, dead_index;
{
- register int i, ins;
+ int i, ins;
#ifdef HARD_REG_SET
/* Declare it register if it's a scalar. */
register
#endif
HARD_REG_SET used, first_used;
#ifdef ELIMINABLE_REGS
- static struct {int from, to; } eliminables[] = ELIMINABLE_REGS;
+ static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
#endif
/* Validate our parameters. */
|| accept_call_clobbered
|| ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
{
- register int j;
- register int size1 = HARD_REGNO_NREGS (regno, mode);
+ int j;
+ int size1 = HARD_REGNO_NREGS (regno, mode);
for (j = 1; j < size1 && ! TEST_HARD_REG_BIT (used, regno + j); j++);
if (j == size1)
{
static void
mark_life (regno, mode, life)
- register int regno;
+ int regno;
enum machine_mode mode;
int life;
{
- register int j = HARD_REGNO_NREGS (regno, mode);
+ int j = HARD_REGNO_NREGS (regno, mode);
if (life)
while (--j >= 0)
SET_HARD_REG_BIT (regs_live, regno + j);
enum machine_mode mode;
int life, birth, death;
{
- register int j = HARD_REGNO_NREGS (regno, mode);
+ int j = HARD_REGNO_NREGS (regno, mode);
#ifdef HARD_REG_SET
/* Declare it register if it's a scalar. */
register
case '=': case '+': case '?':
case '#': case '&': case '!':
case '*': case '%':
- case '1': case '2': case '3': case '4': case '5':
- case '6': case '7': case '8': case '9':
case 'm': case '<': case '>': case 'V': case 'o':
case 'E': case 'F': case 'G': case 'H':
case 's': case 'i': case 'n':
found_zero = 1;
break;
+ case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ /* Skip the balance of the matching constraint. */
+ while (ISDIGIT (*p))
+ p++;
+ break;
+
default:
if (REG_CLASS_FROM_LETTER (c) == NO_REGS)
break;
dump_local_alloc (file)
FILE *file;
{
- register int i;
+ int i;
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (reg_renumber[i] != -1)
fprintf (file, ";; Register %d in %d.\n", i, reg_renumber[i]);