X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fregclass.c;h=c022b0a6321e79ece66eaadf9346bb8ad790c99f;hp=41d33533566c46abc668a9a020984f3166c42f78;hb=3461a998f83f6aba603802fcc1031a5898e9956f;hpb=0b387d23327ce63d1f865a1716b346e590061bcb diff --git a/gcc/regclass.c b/gcc/regclass.c index 41d33533566..c022b0a6321 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -1,6 +1,6 @@ /* Compute register class preferences for pseudo-registers. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996 - 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GNU CC. @@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" #include "rtl.h" +#include "expr.h" #include "tm_p.h" #include "hard-reg-set.h" #include "flags.h" @@ -42,7 +43,7 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #ifndef REGISTER_MOVE_COST -#define REGISTER_MOVE_COST(x, y) 2 +#define REGISTER_MOVE_COST(m, x, y) 2 #endif static void init_reg_sets_1 PARAMS ((void)); @@ -115,7 +116,16 @@ int n_non_fixed_regs; and are also considered fixed. */ char global_regs[FIRST_PSEUDO_REGISTER]; - + +/* Contains 1 for registers that are set or clobbered by calls. */ +/* ??? Ideally, this would be just call_used_regs plus global_regs, but + for someone's bright idea to have call_used_regs strictly include + fixed_regs. Which leaves us guessing as to the set of fixed_regs + that are actually preserved. We know for sure that those associated + with the local stack frame are safe, but scant others. */ + +HARD_REG_SET regs_invalidated_by_call; + /* Table of register numbers in the order in which to try to use them. */ #ifdef REG_ALLOC_ORDER int reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER; @@ -140,7 +150,7 @@ static unsigned int_reg_class_contents[N_REG_CLASSES][N_REG_INTS] /* For each reg class, number of regs it contains. */ -int reg_class_size[N_REG_CLASSES]; +unsigned int reg_class_size[N_REG_CLASSES]; /* For each reg class, table listing all the containing classes. */ @@ -160,9 +170,12 @@ enum reg_class reg_class_subunion[N_REG_CLASSES][N_REG_CLASSES]; enum reg_class reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES]; -/* Array containing all of the register names */ +/* Array containing all of the register names. Unless + DEBUG_REGISTER_NAMES is defined, use the copy in print-rtl.c. */ -const char *reg_names[] = REGISTER_NAMES; +#ifdef DEBUG_REGISTER_NAMES +const char * reg_names[] = REGISTER_NAMES; +#endif /* 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 @@ -171,20 +184,24 @@ const char *reg_names[] = REGISTER_NAMES; enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER]; +/* 1 if class does contain register of given mode. */ + +static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE]; + /* Maximum cost of moving from a register in one class to a register in another class. Based on REGISTER_MOVE_COST. */ -static int move_cost[N_REG_CLASSES][N_REG_CLASSES]; +static int move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES]; /* Similar, but here we don't have to move if the first index is a subset of the second so in that case the cost is zero. */ -static int may_move_in_cost[N_REG_CLASSES][N_REG_CLASSES]; +static int may_move_in_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES]; /* Similar, but here we don't have to move if the first index is a superset of the second so in that case the cost is zero. */ -static int may_move_out_cost[N_REG_CLASSES][N_REG_CLASSES]; +static int may_move_out_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES]; #ifdef FORBIDDEN_INC_DEC_CLASSES @@ -200,6 +217,21 @@ static char *in_inc_dec; #endif /* FORBIDDEN_INC_DEC_CLASSES */ +#ifdef CLASS_CANNOT_CHANGE_MODE + +/* These are the classes containing only registers that can be used in + a SUBREG expression that changes the mode of the register in some + way that is illegal. */ + +static int class_can_change_mode[N_REG_CLASSES]; + +/* Registers, including pseudos, which change modes in some way that + is illegal. */ + +static regset reg_changes_mode; + +#endif /* CLASS_CANNOT_CHANGE_MODE */ + #ifdef HAVE_SECONDARY_RELOADS /* Sample MEM values for use by memory_move_secondary_cost. */ @@ -243,15 +275,16 @@ init_reg_sets () { CLEAR_HARD_REG_SET (reg_class_contents[i]); + /* Note that we hard-code 32 here, not HOST_BITS_PER_INT. */ for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) - if (int_reg_class_contents[i][j / HOST_BITS_PER_INT] - & ((unsigned) 1 << (j % HOST_BITS_PER_INT))) + if (int_reg_class_contents[i][j / 32] + & ((unsigned) 1 << (j % 32))) SET_HARD_REG_BIT (reg_class_contents[i], j); } - bcopy (initial_fixed_regs, fixed_regs, sizeof fixed_regs); - bcopy (initial_call_used_regs, call_used_regs, sizeof call_used_regs); - bzero (global_regs, sizeof global_regs); + memcpy (fixed_regs, initial_fixed_regs, sizeof fixed_regs); + memcpy (call_used_regs, initial_call_used_regs, sizeof call_used_regs); + memset (global_regs, 0, sizeof global_regs); /* Do any additional initialization regsets may need */ INIT_ONCE_REG_SET (); @@ -269,6 +302,8 @@ static void init_reg_sets_1 () { register unsigned int i, j; + register unsigned int /* enum machine_mode */ m; + char allocatable_regs_of_mode [MAX_MACHINE_MODE]; /* This macro allows the fixed or call-used registers and the register classes to depend on target flags. */ @@ -279,7 +314,7 @@ init_reg_sets_1 () /* Compute number of hard regs in each class. */ - bzero ((char *) reg_class_size, sizeof reg_class_size); + memset ((char *) reg_class_size, 0, 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)) @@ -385,8 +420,9 @@ init_reg_sets_1 () CLEAR_HARD_REG_SET (fixed_reg_set); CLEAR_HARD_REG_SET (call_used_reg_set); CLEAR_HARD_REG_SET (call_fixed_reg_set); + CLEAR_HARD_REG_SET (regs_invalidated_by_call); - bcopy (fixed_regs, call_fixed_regs, sizeof call_fixed_regs); + memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs); n_non_fixed_regs = 0; @@ -403,44 +439,120 @@ init_reg_sets_1 () 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); + + /* There are a couple of fixed registers that we know are safe to + exclude from being clobbered by calls: + + The frame pointer is always preserved across calls. The arg pointer + is if it is fixed. The stack pointer usually is, unless + RETURN_POPS_ARGS, in which case an explicit CLOBBER will be present. + If we are generating PIC code, the PIC offset table register is + preserved across calls, though the target can override that. */ + + if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM) + ; +#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM + else if (i == HARD_FRAME_POINTER_REGNUM) + ; +#endif +#if ARG_POINTER_REGNUM != FRAME_POINTER_REGNUM + else if (i == ARG_POINTER_REGNUM && fixed_regs[i]) + ; +#endif +#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED + else if (i == PIC_OFFSET_TABLE_REGNUM && flag_pic) + ; +#endif + else if (call_used_regs[i] || global_regs[i]) + SET_HARD_REG_BIT (regs_invalidated_by_call, i); } + memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode)); + memset (allocatable_regs_of_mode, 0, sizeof (allocatable_regs_of_mode)); + for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++) + for (i = 0; i < N_REG_CLASSES; i++) + if (CLASS_MAX_NREGS (i, m) <= reg_class_size[i]) + for (j = 0; j < FIRST_PSEUDO_REGISTER; j++) + if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j) + && HARD_REGNO_MODE_OK (j, m)) + { + contains_reg_of_mode [i][m] = 1; + allocatable_regs_of_mode [m] = 1; + break; + } + /* Initialize the move cost table. Find every subset of each class and take the maximum cost of moving any subset to any other. */ - for (i = 0; i < N_REG_CLASSES; i++) - for (j = 0; j < N_REG_CLASSES; j++) + for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++) + if (allocatable_regs_of_mode [m]) { - int cost = i == j ? 2 : REGISTER_MOVE_COST (i, j); - enum reg_class *p1, *p2; - - for (p2 = ®_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES; p2++) - if (*p2 != i) - cost = MAX (cost, REGISTER_MOVE_COST (i, *p2)); - - for (p1 = ®_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES; p1++) - { - if (*p1 != j) - cost = MAX (cost, REGISTER_MOVE_COST (*p1, j)); - - for (p2 = ®_class_subclasses[j][0]; - *p2 != LIM_REG_CLASSES; p2++) - if (*p1 != *p2) - cost = MAX (cost, REGISTER_MOVE_COST (*p1, *p2)); - } - - move_cost[i][j] = cost; - - if (reg_class_subset_p (i, j)) - may_move_in_cost[i][j] = 0; - else - may_move_in_cost[i][j] = cost; + for (i = 0; i < N_REG_CLASSES; i++) + if (contains_reg_of_mode [i][m]) + for (j = 0; j < N_REG_CLASSES; j++) + { + int cost; + enum reg_class *p1, *p2; + + if (!contains_reg_of_mode [j][m]) + { + move_cost[m][i][j] = 65536; + may_move_in_cost[m][i][j] = 65536; + may_move_out_cost[m][i][j] = 65536; + } + else + { + cost = i == j ? 2 : REGISTER_MOVE_COST (m, i, j); + + for (p2 = ®_class_subclasses[j][0]; + *p2 != LIM_REG_CLASSES; + p2++) + if (*p2 != i && contains_reg_of_mode [*p2][m]) + cost = MAX (cost, move_cost [m][i][*p2]); + + for (p1 = ®_class_subclasses[i][0]; + *p1 != LIM_REG_CLASSES; + p1++) + if (*p1 != j && contains_reg_of_mode [*p1][m]) + cost = MAX (cost, move_cost [m][*p1][j]); + + move_cost[m][i][j] = cost; + + if (reg_class_subset_p (i, j)) + may_move_in_cost[m][i][j] = 0; + else + may_move_in_cost[m][i][j] = cost; + + if (reg_class_subset_p (j, i)) + may_move_out_cost[m][i][j] = 0; + else + may_move_out_cost[m][i][j] = cost; + } + } + else + for (j = 0; j < N_REG_CLASSES; j++) + { + move_cost[m][i][j] = 65536; + may_move_in_cost[m][i][j] = 65536; + may_move_out_cost[m][i][j] = 65536; + } + } - if (reg_class_subset_p (j, i)) - may_move_out_cost[i][j] = 0; - else - may_move_out_cost[i][j] = cost; +#ifdef CLASS_CANNOT_CHANGE_MODE + { + HARD_REG_SET c; + COMPL_HARD_REG_SET (c, reg_class_contents[CLASS_CANNOT_CHANGE_MODE]); + + for (i = 0; i < N_REG_CLASSES; i++) + { + GO_IF_HARD_REG_SUBSET (reg_class_contents[i], c, ok_class); + class_can_change_mode [i] = 0; + continue; + ok_class: + class_can_change_mode [i] = 1; } + } +#endif /* CLASS_CANNOT_CHANGE_MODE */ } /* Compute the table of register modes. @@ -483,6 +595,7 @@ init_regs () /* Make some fake stack-frame MEM references for use in memory_move_secondary_cost. */ int i; + for (i = 0; i < MAX_MACHINE_MODE; i++) top_of_stack[i] = gen_rtx_MEM (i, stack_pointer_rtx); ggc_add_rtx_root (top_of_stack, MAX_MACHINE_MODE); @@ -529,9 +642,9 @@ memory_move_secondary_cost (mode, class, in) return 0; if (in) - partial_cost = REGISTER_MOVE_COST (altclass, class); + partial_cost = REGISTER_MOVE_COST (mode, altclass, class); else - partial_cost = REGISTER_MOVE_COST (class, altclass); + partial_cost = REGISTER_MOVE_COST (mode, class, altclass); if (class == altclass) /* This isn't simply a copy-to-temporary situation. Can't guess @@ -554,9 +667,10 @@ memory_move_secondary_cost (mode, class, in) enum machine_mode choose_hard_reg_mode (regno, nregs) - int regno ATTRIBUTE_UNUSED; - int nregs; + unsigned int regno ATTRIBUTE_UNUSED; + unsigned int nregs; { + unsigned int /* enum machine_mode */ m; enum machine_mode found_mode = VOIDmode, mode; /* We first look for the largest integer mode that can be validly @@ -583,9 +697,14 @@ choose_hard_reg_mode (regno, nregs) if (found_mode != VOIDmode) return found_mode; - if (HARD_REGNO_NREGS (regno, CCmode) == nregs - && HARD_REGNO_MODE_OK (regno, CCmode)) - return CCmode; + /* Iterate over all of the CCmodes. */ + for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m) + { + mode = (enum machine_mode) m; + if (HARD_REGNO_NREGS (regno, mode) == nregs + && HARD_REGNO_MODE_OK (regno, mode)) + return mode; + } /* We can't find a mode valid for this register. */ return VOIDmode; @@ -713,16 +832,15 @@ static struct reg_pref *reg_pref; static struct reg_pref *reg_pref_buffer; -/* Account for the fact that insns within a loop are executed very commonly, - but don't keep doing this as loops go too deep. */ +/* Frequency of executions of current insn. */ -static int loop_cost; +static int frequency; static rtx scan_one_insn PARAMS ((rtx, int)); static void record_operand_costs PARAMS ((rtx, struct costs *, struct reg_pref *)); static void dump_regclass PARAMS ((FILE *)); static void record_reg_classes PARAMS ((int, int, rtx *, enum machine_mode *, - char *, const char **, rtx, + const char **, rtx, struct costs *, struct reg_pref *)); static int copy_cost PARAMS ((rtx, enum machine_mode, enum reg_class, int)); @@ -730,7 +848,7 @@ static void record_address_regs PARAMS ((rtx, enum reg_class, int)); #ifdef FORBIDDEN_INC_DEC_CLASSES static int auto_inc_dec_reg_p PARAMS ((rtx, enum machine_mode)); #endif -static void reg_scan_mark_refs PARAMS ((rtx, rtx, int, int)); +static void reg_scan_mark_refs PARAMS ((rtx, rtx, int, unsigned int)); /* Return the reg_class in which pseudo reg number REGNO is best allocated. This function is sometimes called before the info has been computed. @@ -783,13 +901,23 @@ dump_regclass (dump) int i; for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) { - enum reg_class class; + int /* enum reg_class */ class; if (REG_N_REFS (i)) { fprintf (dump, " Register %i costs:", i); - for (class = 0; class < N_REG_CLASSES; class++) - fprintf (dump, " %s:%i", reg_class_names[(int) class], - costs[i].cost[class]); + for (class = 0; class < (int) N_REG_CLASSES; class++) + if (contains_reg_of_mode [(enum reg_class) class][PSEUDO_REGNO_MODE (i)] +#ifdef FORBIDDEN_INC_DEC_CLASSES + && (!in_inc_dec[i] + || !forbidden_inc_dec_class[(enum reg_class) class]) +#endif +#ifdef CLASS_CANNOT_CHANGE_MODE + && (!REGNO_REG_SET_P (reg_changes_mode, i) + || class_can_change_mode [(enum reg_class) class]) +#endif + ) + fprintf (dump, " %s:%i", reg_class_names[class], + costs[i].cost[(enum reg_class) class]); fprintf (dump, " MEM:%i\n", costs[i].mem_cost); } } @@ -806,7 +934,6 @@ record_operand_costs (insn, op_costs, reg_pref) { const char *constraints[MAX_RECOG_OPERANDS]; enum machine_mode modes[MAX_RECOG_OPERANDS]; - char subreg_changes_size[MAX_RECOG_OPERANDS]; int i; for (i = 0; i < recog_data.n_operands; i++) @@ -814,7 +941,6 @@ record_operand_costs (insn, op_costs, reg_pref) constraints[i] = recog_data.constraints[i]; modes[i] = recog_data.operand_mode[i]; } - memset (subreg_changes_size, 0, sizeof (subreg_changes_size)); /* If we get here, we are set up to record the costs of all the operands for this insn. Start by initializing the costs. @@ -829,17 +955,20 @@ record_operand_costs (insn, op_costs, reg_pref) if (GET_CODE (recog_data.operand[i]) == SUBREG) { rtx inner = SUBREG_REG (recog_data.operand[i]); - if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner))) - subreg_changes_size[i] = 1; +#ifdef CLASS_CANNOT_CHANGE_MODE + if (GET_CODE (inner) == REG + && CLASS_CANNOT_CHANGE_MODE_P (modes[i], GET_MODE (inner))) + SET_REGNO_REG_SET (reg_changes_mode, REGNO (inner)); +#endif recog_data.operand[i] = inner; } if (GET_CODE (recog_data.operand[i]) == MEM) record_address_regs (XEXP (recog_data.operand[i], 0), - BASE_REG_CLASS, loop_cost * 2); + BASE_REG_CLASS, frequency * 2); else if (constraints[i][0] == 'p') record_address_regs (recog_data.operand[i], - BASE_REG_CLASS, loop_cost * 2); + BASE_REG_CLASS, frequency * 2); } /* Check for commutative in a separate loop so everything will @@ -861,12 +990,12 @@ record_operand_costs (insn, op_costs, reg_pref) xconstraints[i] = constraints[i+1]; xconstraints[i+1] = constraints[i]; record_reg_classes (recog_data.n_alternatives, recog_data.n_operands, - recog_data.operand, modes, subreg_changes_size, + recog_data.operand, modes, xconstraints, insn, op_costs, reg_pref); } record_reg_classes (recog_data.n_alternatives, recog_data.n_operands, - recog_data.operand, modes, subreg_changes_size, + recog_data.operand, modes, constraints, insn, op_costs, reg_pref); } @@ -915,9 +1044,9 @@ scan_one_insn (insn, pass) costs[REGNO (SET_DEST (set))].mem_cost -= (MEMORY_MOVE_COST (GET_MODE (SET_DEST (set)), GENERAL_REGS, 1) - * loop_cost); + * frequency); record_address_regs (XEXP (SET_SRC (set), 0), - BASE_REG_CLASS, loop_cost * 2); + BASE_REG_CLASS, frequency * 2); return insn; } @@ -966,11 +1095,19 @@ scan_one_insn (insn, pass) /* This makes one more setting of new insns's dest. */ REG_N_SETS (REGNO (recog_data.operand[0]))++; + REG_N_REFS (REGNO (recog_data.operand[0]))++; + REG_FREQ (REGNO (recog_data.operand[0])) += frequency; *recog_data.operand_loc[1] = recog_data.operand[0]; + REG_N_REFS (REGNO (recog_data.operand[0]))++; + REG_FREQ (REGNO (recog_data.operand[0])) += frequency; for (i = recog_data.n_dups - 1; i >= 0; i--) if (recog_data.dup_num[i] == 1) - *recog_data.dup_loc[i] = recog_data.operand[0]; + { + *recog_data.dup_loc[i] = recog_data.operand[0]; + REG_N_REFS (REGNO (recog_data.operand[0]))++; + REG_FREQ (REGNO (recog_data.operand[0])) += frequency; + } return PREV_INSN (newinsn); } @@ -987,9 +1124,9 @@ scan_one_insn (insn, pass) int regno = REGNO (recog_data.operand[i]); struct costs *p = &costs[regno], *q = &op_costs[i]; - p->mem_cost += q->mem_cost * loop_cost; + p->mem_cost += q->mem_cost * frequency; for (j = 0; j < N_REG_CLASSES; j++) - p->cost[j] += q->cost[j] * loop_cost; + p->cost[j] += q->cost[j] * frequency; } return insn; @@ -1014,6 +1151,10 @@ regclass (f, nregs, dump) costs = (struct costs *) xmalloc (nregs * sizeof (struct costs)); +#ifdef CLASS_CANNOT_CHANGE_MODE + reg_changes_mode = BITMAP_XMALLOC(); +#endif + #ifdef FORBIDDEN_INC_DEC_CLASSES in_inc_dec = (char *) xmalloc (nregs); @@ -1080,10 +1221,10 @@ regclass (f, nregs, dump) fprintf (dump, "\n\nPass %i\n\n",pass); /* Zero out our accumulation of the cost of each class for each reg. */ - bzero ((char *) costs, nregs * sizeof (struct costs)); + memset ((char *) costs, 0, nregs * sizeof (struct costs)); #ifdef FORBIDDEN_INC_DEC_CLASSES - bzero (in_inc_dec, nregs); + memset (in_inc_dec, 0, nregs); #endif /* Scan the instructions and record each time it would @@ -1091,7 +1232,7 @@ regclass (f, nregs, dump) if (!optimize) { - loop_cost = 1; + frequency = 1; for (insn = f; insn; insn = NEXT_INSN (insn)) insn = scan_one_insn (insn, pass); } @@ -1105,9 +1246,9 @@ regclass (f, nregs, dump) aggressive than the assumptions made elsewhere and is being tried as an experiment. */ if (optimize_size) - loop_cost = 1; + frequency = 1; else - loop_cost = 1 << (2 * MIN (bb->loop_depth, 5)); + frequency = bb->frequency ? bb->frequency : 1; for (insn = bb->head; ; insn = NEXT_INSN (insn)) { insn = scan_one_insn (insn, pass); @@ -1147,11 +1288,14 @@ regclass (f, nregs, dump) { /* Ignore classes that are too small for this operand or invalid for a operand that was auto-incremented. */ - if (CLASS_MAX_NREGS (class, PSEUDO_REGNO_MODE (i)) - > reg_class_size[class] + if (!contains_reg_of_mode [class][PSEUDO_REGNO_MODE (i)] #ifdef FORBIDDEN_INC_DEC_CLASSES || (in_inc_dec[i] && forbidden_inc_dec_class[class]) #endif +#ifdef CLASS_CANNOT_CHANGE_MODE + || (REGNO_REG_SET_P (reg_changes_mode, i) + && ! class_can_change_mode [class]) +#endif ) ; else if (p->cost[class] < best_cost) @@ -1178,6 +1322,10 @@ regclass (f, nregs, dump) #ifdef FORBIDDEN_INC_DEC_CLASSES && ! (in_inc_dec[i] && forbidden_inc_dec_class[class]) #endif +#ifdef CLASS_CANNOT_CHANGE_MODE + && ! (REGNO_REG_SET_P (reg_changes_mode, i) + && ! class_can_change_mode [class]) +#endif ) alt = reg_class_subunion[(int) alt][class]; @@ -1210,6 +1358,9 @@ regclass (f, nregs, dump) #ifdef FORBIDDEN_INC_DEC_CLASSES free (in_inc_dec); #endif +#ifdef CLASS_CANNOT_CHANGE_MODE + BITMAP_XFREE (reg_changes_mode); +#endif free (costs); } @@ -1238,13 +1389,12 @@ regclass (f, nregs, dump) alternatives. */ static void -record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, +record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn, op_costs, reg_pref) int n_alts; int n_ops; rtx *ops; enum machine_mode *modes; - char *subreg_changes_size ATTRIBUTE_UNUSED; const char **constraints; rtx insn; struct costs *op_costs; @@ -1285,7 +1435,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, if (*p == 0) { if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER) - bzero ((char *) &this_op_costs[i], sizeof this_op_costs[i]); + memset ((char *) &this_op_costs[i], 0, sizeof this_op_costs[i]); continue; } @@ -1351,10 +1501,10 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, for (class = 0; class < N_REG_CLASSES; class++) pp->cost[class] = ((recog_data.operand_type[i] != OP_OUT - ? may_move_in_cost[class][(int) classes[i]] + ? may_move_in_cost[mode][class][(int) classes[i]] : 0) + (recog_data.operand_type[i] != OP_IN - ? may_move_out_cost[(int) classes[i]][class] + ? may_move_out_cost[mode][(int) classes[i]][class] : 0)); /* If the alternative actually allows memory, make things @@ -1376,7 +1526,8 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, if (reg_pref) alt_cost - += (may_move_in_cost[(unsigned char) reg_pref[REGNO (op)].prefclass] + += (may_move_in_cost[mode] + [(unsigned char) reg_pref[REGNO (op)].prefclass] [(int) classes[i]]); if (REGNO (ops[i]) != REGNO (ops[j]) @@ -1509,17 +1660,6 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, win = 1; break; -#ifdef EXTRA_CONSTRAINT - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - if (EXTRA_CONSTRAINT (op, c)) - win = 1; - break; -#endif - case 'g': if (GET_CODE (op) == MEM || (CONSTANT_P (op) @@ -1535,23 +1675,19 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, break; default: - classes[i] - = reg_class_subunion[(int) classes[i]] - [(int) REG_CLASS_FROM_LETTER (c)]; + if (REG_CLASS_FROM_LETTER (c) != NO_REGS) + classes[i] + = reg_class_subunion[(int) classes[i]] + [(int) REG_CLASS_FROM_LETTER (c)]; +#ifdef EXTRA_CONSTRAINT + else if (EXTRA_CONSTRAINT (op, c)) + win = 1; +#endif + break; } constraints[i] = p; -#ifdef CLASS_CANNOT_CHANGE_SIZE - /* If we noted a subreg earlier, and the selected class is a - subclass of CLASS_CANNOT_CHANGE_SIZE, zap it. */ - if (subreg_changes_size[i] - && (reg_class_subunion[(int) CLASS_CANNOT_CHANGE_SIZE] - [(int) classes[i]] - == CLASS_CANNOT_CHANGE_SIZE)) - classes[i] = NO_REGS; -#endif - /* How we account for this operand now depends on whether it is a pseudo register or not. If it is, we first check if any register classes are valid. If not, we ignore this alternative, @@ -1563,13 +1699,13 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, { if (classes[i] == NO_REGS) { - /* We must always fail if the operand is a REG, but - we did not find a suitable class. - - Otherwise we may perform an uninitialized read - from this_op_costs after the `continue' statement - below. */ - alt_fail = 1; + /* We must always fail if the operand is a REG, but + we did not find a suitable class. + + Otherwise we may perform an uninitialized read + from this_op_costs after the `continue' statement + below. */ + alt_fail = 1; } else { @@ -1578,10 +1714,10 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, for (class = 0; class < N_REG_CLASSES; class++) pp->cost[class] = ((recog_data.operand_type[i] != OP_OUT - ? may_move_in_cost[class][(int) classes[i]] + ? may_move_in_cost[mode][class][(int) classes[i]] : 0) + (recog_data.operand_type[i] != OP_IN - ? may_move_out_cost[(int) classes[i]][class] + ? may_move_out_cost[mode][(int) classes[i]][class] : 0)); /* If the alternative actually allows memory, make things @@ -1603,7 +1739,8 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, if (reg_pref) alt_cost - += (may_move_in_cost[(unsigned char) reg_pref[REGNO (op)].prefclass] + += (may_move_in_cost[mode] + [(unsigned char) reg_pref[REGNO (op)].prefclass] [(int) classes[i]]); } } @@ -1681,10 +1818,10 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, for (i = 0; i <= 1; i++) if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER) { - int regno = REGNO (ops[!i]); + unsigned int regno = REGNO (ops[!i]); enum machine_mode mode = GET_MODE (ops[!i]); int class; - int nr; + unsigned int nr; if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0) { @@ -1692,7 +1829,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, if ((reg_class_size[(unsigned char) pref] == CLASS_MAX_NREGS (pref, mode)) - && REGISTER_MOVE_COST (pref, pref) < 10 * 2) + && REGISTER_MOVE_COST (mode, pref, pref) < 10 * 2) op_costs[i].cost[(unsigned char) pref] = -1; } else if (regno < FIRST_PSEUDO_REGISTER) @@ -1704,13 +1841,14 @@ record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size, op_costs[i].cost[class] = -1; else { - for (nr = 0; nr < HARD_REGNO_NREGS(regno, mode); nr++) + for (nr = 0; nr < HARD_REGNO_NREGS (regno, mode); nr++) { - if (!TEST_HARD_REG_BIT (reg_class_contents[class], regno + nr)) + if (! TEST_HARD_REG_BIT (reg_class_contents[class], + regno + nr)) break; } - if (nr == HARD_REGNO_NREGS(regno,mode)) + if (nr == HARD_REGNO_NREGS (regno,mode)) op_costs[i].cost[class] = -1; } } @@ -1759,7 +1897,7 @@ copy_cost (x, mode, class, to_p) #endif if (secondary_class != NO_REGS) - return (move_cost[(int) secondary_class][(int) class] + return (move_cost[mode][(int) secondary_class][(int) class] + copy_cost (x, mode, secondary_class, 2)); #endif /* HAVE_SECONDARY_RELOADS */ @@ -1771,11 +1909,11 @@ copy_cost (x, mode, class, to_p) return MEMORY_MOVE_COST (mode, class, to_p); else if (GET_CODE (x) == REG) - return move_cost[(int) REGNO_REG_CLASS (REGNO (x))][(int) class]; + return move_cost[mode][(int) REGNO_REG_CLASS (REGNO (x))][(int) class]; else /* If this is a constant, we may eventually want to call rtx_cost here. */ - return 2; + return COSTS_N_INSNS (1); } /* Record the pseudo registers we must reload into hard registers @@ -1809,10 +1947,10 @@ record_address_regs (x, class, scale) /* When we have an address that is a sum, we must determine whether registers are "base" or "index" regs. If there is a sum of two registers, we must choose one to be - the "base". Luckily, we can use the REGNO_POINTER_FLAG - to make a good choice most of the time. We only need to do this - on machines that can have two registers in an address and where - the base and index register classes are different. + the "base". Luckily, we can use the REG_POINTER to make a good + choice most of the time. We only need to do this on machines + that can have two registers in an address and where the base + and index register classes are different. ??? This code used to set REGNO_POINTER_FLAG in some cases, but that seems bogus since it should only be set when we are sure @@ -1885,13 +2023,13 @@ record_address_regs (x, class, scale) with the other operand the index. Likewise if the other operand is a MULT. */ - else if ((code0 == REG && REGNO_POINTER_FLAG (REGNO (arg0))) + else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT) { record_address_regs (arg0, BASE_REG_CLASS, scale); record_address_regs (arg1, INDEX_REG_CLASS, scale); } - else if ((code1 == REG && REGNO_POINTER_FLAG (REGNO (arg1))) + else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT) { record_address_regs (arg0, INDEX_REG_CLASS, scale); @@ -1911,6 +2049,17 @@ record_address_regs (x, class, scale) } break; + /* Double the importance of a pseudo register that is incremented + or decremented, since it would take two extra insns + if it ends up in the wrong place. */ + case POST_MODIFY: + case PRE_MODIFY: + record_address_regs (XEXP (x, 0), BASE_REG_CLASS, 2 * scale); + if (REG_P (XEXP (XEXP (x, 1), 1))) + record_address_regs (XEXP (XEXP (x, 1), 1), + INDEX_REG_CLASS, 2 * scale); + break; + case POST_INC: case PRE_INC: case POST_DEC: @@ -1937,7 +2086,7 @@ record_address_regs (x, class, scale) pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2; for (i = 0; i < N_REG_CLASSES; i++) - pp->cost[i] += (may_move_in_cost[i][(int) class] * scale) / 2; + pp->cost[i] += (may_move_in_cost[Pmode][i][(int) class] * scale) / 2; } break; @@ -1982,8 +2131,9 @@ auto_inc_dec_reg_p (reg, mode) } #endif -static short *renumber = (short *)0; -static size_t regno_allocated = 0; +static short *renumber; +static size_t regno_allocated; +static unsigned int reg_n_max; /* Allocate enough space to hold NUM_REGS registers for the tables used for reg_scan and flow_analysis that are indexed by the register number. If @@ -2002,7 +2152,6 @@ allocate_reg_info (num_regs, new_p, renumber_p) size_t size_renumber; size_t min = (new_p) ? 0 : reg_n_max; struct reg_info_data *reg_data; - struct reg_info_data *reg_next; if (num_regs > regno_allocated) { @@ -2055,34 +2204,34 @@ allocate_reg_info (num_regs, new_p, renumber_p) { /* Loop through each of the segments allocated for the actual reg_info pages, and set up the pointers, zero the pages, etc. */ - for (reg_data = reg_info_head; reg_data; reg_data = reg_next) + for (reg_data = reg_info_head; + reg_data && reg_data->max_index >= min; + reg_data = reg_data->next) { size_t min_index = reg_data->min_index; size_t max_index = reg_data->max_index; + size_t max = MIN (max_index, num_regs); + size_t local_min = min - min_index; + size_t i; - reg_next = reg_data->next; - if (min <= max_index) - { - size_t max = max_index; - size_t local_min = min - min_index; - size_t i; - - if (min < min_index) - local_min = 0; - if (!reg_data->used_p) /* page just allocated with calloc */ - reg_data->used_p = 1; /* no need to zero */ - else - bzero ((char *) ®_data->data[local_min], - sizeof (reg_info) * (max - min_index - local_min + 1)); + if (reg_data->min_index > num_regs) + continue; - for (i = min_index+local_min; i <= max; i++) - { - VARRAY_REG (reg_n_info, i) = ®_data->data[i-min_index]; - REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN; - renumber[i] = -1; - reg_pref_buffer[i].prefclass = (char) NO_REGS; - reg_pref_buffer[i].altclass = (char) NO_REGS; - } + if (min < min_index) + local_min = 0; + if (!reg_data->used_p) /* page just allocated with calloc */ + reg_data->used_p = 1; /* no need to zero */ + else + memset ((char *) ®_data->data[local_min], 0, + sizeof (reg_info) * (max - min_index - local_min + 1)); + + for (i = min_index+local_min; i <= max; i++) + { + VARRAY_REG (reg_n_info, i) = ®_data->data[i-min_index]; + REG_BASIC_BLOCK (i) = REG_BLOCK_UNKNOWN; + renumber[i] = -1; + reg_pref_buffer[i].prefclass = (char) NO_REGS; + reg_pref_buffer[i].altclass = (char) NO_REGS; } } } @@ -2135,20 +2284,28 @@ free_reg_info () /* Maximum number of parallel sets and clobbers in any insn in this fn. Always at least 3, since the combiner could put that many together - and we want this to remain correct for all the remaining passes. */ + and we want this to remain correct for all the remaining passes. + This corresponds to the maximum number of times note_stores will call + a function for any insn. */ int max_parallel; +/* Used as a temporary to record the largest number of registers in + PARALLEL in a SET_DEST. This is added to max_parallel. */ + +static int max_set_parallel; + void reg_scan (f, nregs, repeat) rtx f; - int nregs; + unsigned int nregs; int repeat ATTRIBUTE_UNUSED; { register rtx insn; allocate_reg_info (nregs, TRUE, FALSE); max_parallel = 3; + max_set_parallel = 0; for (insn = f; insn; insn = NEXT_INSN (insn)) if (GET_CODE (insn) == INSN @@ -2163,6 +2320,8 @@ reg_scan (f, nregs, repeat) if (REG_NOTES (insn)) reg_scan_mark_refs (REG_NOTES (insn), insn, 1, 0); } + + max_parallel += max_set_parallel; } /* Update 'regscan' information by looking at the insns @@ -2171,10 +2330,10 @@ reg_scan (f, nregs, repeat) such a REG. We only update information for those. */ void -reg_scan_update(first, last, old_max_regno) +reg_scan_update (first, last, old_max_regno) rtx first; rtx last; - int old_max_regno; + unsigned int old_max_regno; { register rtx insn; @@ -2205,7 +2364,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno) rtx x; rtx insn; int note_flag; - int min_regno; + unsigned int min_regno; { register enum rtx_code code; register rtx dest; @@ -2227,7 +2386,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno) case REG: { - register int regno = REGNO (x); + unsigned int regno = REGNO (x); if (regno >= min_regno) { @@ -2260,6 +2419,11 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno) dest = XEXP (dest, 0)) ; + /* For a PARALLEL, record the number of things (less the usual one for a + SET) that are set. */ + if (GET_CODE (dest) == PARALLEL) + max_set_parallel = MAX (max_set_parallel, XVECLEN (dest, 0) - 1); + if (GET_CODE (dest) == REG && REGNO (dest) >= min_regno) REG_N_SETS (REGNO (dest))++; @@ -2282,18 +2446,18 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno) /* If the destination pseudo is set more than once, then other sets might not be to a pointer value (consider access to a union in two threads of control in the presense of global - optimizations). So only set REGNO_POINTER_FLAG on the destination + optimizations). So only set REG_POINTER on the destination pseudo if this is the only set of that pseudo. */ && REG_N_SETS (REGNO (SET_DEST (x))) == 1 && ! REG_USERVAR_P (SET_DEST (x)) - && ! REGNO_POINTER_FLAG (REGNO (SET_DEST (x))) + && ! REG_POINTER (SET_DEST (x)) && ((GET_CODE (SET_SRC (x)) == REG - && REGNO_POINTER_FLAG (REGNO (SET_SRC (x)))) + && REG_POINTER (SET_SRC (x))) || ((GET_CODE (SET_SRC (x)) == PLUS || GET_CODE (SET_SRC (x)) == LO_SUM) && GET_CODE (XEXP (SET_SRC (x), 1)) == CONST_INT && GET_CODE (XEXP (SET_SRC (x), 0)) == REG - && REGNO_POINTER_FLAG (REGNO (XEXP (SET_SRC (x), 0)))) + && REG_POINTER (XEXP (SET_SRC (x), 0))) || GET_CODE (SET_SRC (x)) == CONST || GET_CODE (SET_SRC (x)) == SYMBOL_REF || GET_CODE (SET_SRC (x)) == LABEL_REF @@ -2310,7 +2474,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno) && (GET_CODE (XEXP (note, 0)) == CONST || GET_CODE (XEXP (note, 0)) == SYMBOL_REF || GET_CODE (XEXP (note, 0)) == LABEL_REF)))) - REGNO_POINTER_FLAG (REGNO (SET_DEST (x))) = 1; + REG_POINTER (SET_DEST (x)) = 1; /* ... fall through ... */