/* Compute register class preferences for pseudo-registers.
- Copyright (C) 1987, 88, 91, 92, 93, 1994 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 91, 92, 93, 94, 1996 Free Software Foundation, Inc.
This file is part of GNU CC.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
/* This file contains two passes of the compiler: reg_scan and reg_class.
/* If we have auto-increment or auto-decrement and we can have secondary
reloads, we are not allowed to use classes requiring secondary
- reloads for psuedos auto-incremented since reload can't handle it. */
+ reloads for pseudos auto-incremented since reload can't handle it. */
#ifdef AUTO_INC_DEC
#if defined(SECONDARY_INPUT_RELOAD_CLASS) || defined(SECONDARY_OUTPUT_RELOAD_CLASS)
HARD_REG_SET call_used_reg_set;
+/* HARD_REG_SET of registers we want to avoid caller saving. */
+HARD_REG_SET losing_caller_save_reg_set;
+
/* Data for initializing the above. */
static char initial_call_used_regs[] = CALL_USED_REGISTERS;
char *reg_names[] = REGISTER_NAMES;
+/* For each hard register, the widest mode object that it can contain.
+ This will be a MODE_INT mode if the register can hold integers. Otherwise
+ it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the
+ register. */
+
+enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
+
/* Indexed by n, gives number of times (REG n) is set or clobbered.
This information remains valid for the rest of the compilation
of the current function; it is used to control register allocation.
/* Compute number of hard regs in each class. */
- bzero (reg_class_size, sizeof reg_class_size);
+ bzero ((char *) reg_class_size, sizeof reg_class_size);
for (i = 0; i < N_REG_CLASSES; i++)
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
/* After switches have been processed, which perhaps alter
`fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs. */
-void
+static void
init_reg_sets_1 ()
{
register int i;
CLEAR_HARD_REG_SET (call_fixed_reg_set);
bcopy (fixed_regs, call_fixed_regs, sizeof call_fixed_regs);
-#ifdef STRUCT_VALUE_REGNUM
- call_fixed_regs[STRUCT_VALUE_REGNUM] = 1;
-#endif
-#ifdef STATIC_CHAIN_REGNUM
- call_fixed_regs[STATIC_CHAIN_REGNUM] = 1;
-#endif
n_non_fixed_regs = 0;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- if (FUNCTION_VALUE_REGNO_P (i))
- call_fixed_regs[i] = 1;
if (fixed_regs[i])
SET_HARD_REG_BIT (fixed_reg_set, i);
else
SET_HARD_REG_BIT (call_used_reg_set, i);
if (call_fixed_regs[i])
SET_HARD_REG_BIT (call_fixed_reg_set, i);
+ if (CLASS_LIKELY_SPILLED_P (REGNO_REG_CLASS (i)))
+ SET_HARD_REG_BIT (losing_caller_save_reg_set, i);
}
}
+/* Compute the table of register modes.
+ These values are used to record death information for individual registers
+ (as opposed to a multi-register mode). */
+
+static void
+init_reg_modes ()
+{
+ register int i;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ reg_raw_mode[i] = choose_hard_reg_mode (i, 1);
+
+ /* If we couldn't find a valid mode, fall back to `word_mode'.
+ ??? We assume `word_mode' has already been initialized.
+ ??? One situation in which we need to do this is on the mips where
+ HARD_REGNO_NREGS (fpreg, [SD]Fmode) returns 2. Ideally we'd like
+ to use DF mode for the even registers and VOIDmode for the odd
+ (for the cpu models where the odd ones are inaccessible). */
+ if (reg_raw_mode[i] == VOIDmode)
+ reg_raw_mode[i] = word_mode;
+ }
+}
+
+/* Finish initializing the register sets and
+ initialize the register modes. */
+
+void
+init_regs ()
+{
+ /* This finishes what was started by init_reg_sets, but couldn't be done
+ until after register usage was specified. */
+ if (!output_bytecode)
+ init_reg_sets_1 ();
+
+ init_reg_modes ();
+}
+
+/* Return a machine mode that is legitimate for hard reg REGNO and large
+ enough to save nregs. If we can't find one, return VOIDmode. */
+
+enum machine_mode
+choose_hard_reg_mode (regno, nregs)
+ int regno;
+ int nregs;
+{
+ enum machine_mode found_mode = VOIDmode, mode;
+
+ /* We first look for the largest integer mode that can be validly
+ held in REGNO. If none, we look for the largest floating-point mode.
+ If we still didn't find a valid mode, try CCmode. */
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (HARD_REGNO_NREGS (regno, mode) == nregs
+ && HARD_REGNO_MODE_OK (regno, mode))
+ found_mode = mode;
+
+ if (found_mode != VOIDmode)
+ return found_mode;
+
+ for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (HARD_REGNO_NREGS (regno, mode) == nregs
+ && HARD_REGNO_MODE_OK (regno, mode))
+ found_mode = mode;
+
+ if (found_mode != VOIDmode)
+ return found_mode;
+
+ if (HARD_REGNO_NREGS (regno, CCmode) == nregs
+ && HARD_REGNO_MODE_OK (regno, CCmode))
+ return CCmode;
+
+ /* We can't find a mode valid for this register. */
+ return VOIDmode;
+}
+
/* Specify the usage characteristics of the register named NAME.
It should be a fixed register if FIXED and a
call-used register if CALL_USED. */
being used in such addresses. */
if ((0
+#ifdef SECONDARY_RELOAD_CLASS
+ || (SECONDARY_RELOAD_CLASS (BASE_REG_CLASS, m, r)
+ != NO_REGS)
+#else
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
|| (SECONDARY_OUTPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#endif
+#endif
)
&& ! auto_inc_dec_reg_p (r, m))
forbidden_inc_dec_class[i] = 1;
{
/* Zero out our accumulation of the cost of each class for each reg. */
- bzero (costs, nregs * sizeof (struct costs));
+ bzero ((char *) costs, nregs * sizeof (struct costs));
#ifdef FORBIDDEN_INC_DEC_CLASSES
bzero (in_inc_dec, nregs);
basic_block_head[b] = newinsn;
}
- /* This makes one more setting of new insns's dest. */
+ /* This makes one more setting of new insns's dest. */
reg_n_sets[REGNO (recog_operand[0])]++;
*recog_operand_loc[1] = recog_operand[0];
/* If we don't add any classes, nothing to try. */
if (alt == best)
- alt = (int) NO_REGS;
+ alt = NO_REGS;
/* We cast to (int) because (char) hits bugs in some compilers. */
prefclass[i] = (int) best;
int alt;
enum op_type {OP_READ, OP_WRITE, OP_READ_WRITE} op_types[MAX_RECOG_OPERANDS];
int i, j;
+ rtx set;
/* By default, each operand is an input operand. */
break;
case 'E':
+#ifndef REAL_ARITHMETIC
/* Match any floating double constant, but only if
we can examine the bits of it reliably. */
if ((HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
|| HOST_BITS_PER_WIDE_INT != BITS_PER_WORD)
&& GET_MODE (op) != VOIDmode && ! flag_pretend_float)
break;
+#endif
if (GET_CODE (op) == CONST_DOUBLE)
win = 1;
break;
(qq->cost[class] + alt_cost) * scale);
}
}
+
+ /* If this insn is a single set copying operand 1 to operand 0
+ and one is a pseudo with the other a hard reg that is in its
+ own register class, set the cost of that register class to -1. */
+
+ if ((set = single_set (insn)) != 0
+ && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set)
+ && GET_CODE (ops[0]) == REG && GET_CODE (ops[1]) == REG)
+ for (i = 0; i <= 1; i++)
+ if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER)
+ {
+ int regno = REGNO (ops[!i]);
+ enum machine_mode mode = GET_MODE (ops[!i]);
+ int class;
+ int nr;
+
+ if (regno >= FIRST_PSEUDO_REGISTER && prefclass != 0
+ && (reg_class_size[prefclass[regno]]
+ == CLASS_MAX_NREGS (prefclass[regno], mode)))
+ op_costs[i].cost[prefclass[regno]] = -1;
+ else if (regno < FIRST_PSEUDO_REGISTER)
+ for (class = 0; class < N_REG_CLASSES; class++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+ && reg_class_size[class] == CLASS_MAX_NREGS (class, mode))
+ {
+ if (reg_class_size[class] == 1)
+ op_costs[i].cost[class] = -1;
+ else
+ {
+ for (nr = 0; nr < HARD_REGNO_NREGS(regno, mode); nr++)
+ {
+ if (!TEST_HARD_REG_BIT (reg_class_contents[class], regno + nr))
+ break;
+ }
+
+ if (nr == HARD_REGNO_NREGS(regno,mode))
+ op_costs[i].cost[class] = -1;
+ }
+ }
+ }
}
\f
/* Compute the cost of loading X into (if TO_P is non-zero) or from (if
static int highest_regno_in_uid_map;
/* Maximum number of parallel sets and clobbers in any insn in this fn.
- Always at least 3, since the combiner could put that many togetherm
+ Always at least 3, since the combiner could put that many together
and we want this to remain correct for all the remaining passes. */
int max_parallel;
= (short *) oballoc (highest_regno_in_uid_map * sizeof (short));
}
- bzero (regno_first_uid, highest_regno_in_uid_map * sizeof (int));
- bzero (regno_last_uid, highest_regno_in_uid_map * sizeof (int));
- bzero (regno_last_note_uid, highest_regno_in_uid_map * sizeof (int));
- bzero (reg_n_sets, highest_regno_in_uid_map * sizeof (short));
+ bzero ((char *) regno_first_uid, highest_regno_in_uid_map * sizeof (int));
+ bzero ((char *) regno_last_uid, highest_regno_in_uid_map * sizeof (int));
+ bzero ((char *) regno_last_note_uid,
+ highest_regno_in_uid_map * sizeof (int));
+ bzero ((char *) reg_n_sets, highest_regno_in_uid_map * sizeof (short));
max_parallel = 3;
|| GET_CODE (XEXP (note, 0)) == LABEL_REF))))
REGNO_POINTER_FLAG (REGNO (SET_DEST (x))) = 1;
- /* ... fall through ... */
+ /* ... fall through ... */
default:
{