X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fregclass.c;h=ca4cbd6907a0b852157e2831a27cbf69f329a4e1;hb=1515f92ff456e0479c0f4358519f0f1af5aae3d3;hp=f1761206143a442580a478b5d935776b74974fd4;hpb=a8482e91d66166ec082f4240b4192dbc3f294982;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/regclass.c b/gcc/regclass.c index f1761206143..ca4cbd6907a 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -1,5 +1,6 @@ /* Compute register class preferences for pseudo-registers. - Copyright (C) 1987, 88, 91-98, 1999 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996 + 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of GNU CC. @@ -26,23 +27,26 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" #include "rtl.h" +#include "tm_p.h" #include "hard-reg-set.h" #include "flags.h" #include "basic-block.h" #include "regs.h" +#include "function.h" #include "insn-config.h" #include "recog.h" #include "reload.h" #include "real.h" #include "toplev.h" #include "output.h" +#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 PROTO((void)); -static void init_reg_modes PROTO((void)); +static void init_reg_sets_1 PARAMS ((void)); +static void init_reg_modes PARAMS ((void)); /* If we have auto-increment or auto-decrement and we can have secondary reloads, we are not allowed to use classes requiring secondary @@ -115,6 +119,9 @@ char global_regs[FIRST_PSEUDO_REGISTER]; /* 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; + +/* The inverse of reg_alloc_order. */ +int inv_reg_alloc_order[FIRST_PSEUDO_REGISTER]; #endif /* For each reg class, a HARD_REG_SET saying which registers are in it. */ @@ -133,7 +140,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. */ @@ -153,9 +160,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. */ -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 @@ -167,12 +177,17 @@ enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER]; /* 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_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[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES]; #ifdef FORBIDDEN_INC_DEC_CLASSES @@ -188,6 +203,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. */ @@ -210,6 +240,11 @@ struct reg_info_data { static struct reg_info_data *reg_info_head; +/* No more global register variables may be declared; true once + regclass has been initialized. */ + +static int no_global_reg_vars = 0; + /* Function called only once to initialize the above data on reg usage. Once this is done, various switches may override. */ @@ -232,12 +267,17 @@ init_reg_sets () 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 (); + +#ifdef REG_ALLOC_ORDER + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + inv_reg_alloc_order[reg_alloc_order[i]] = i; +#endif } /* After switches have been processed, which perhaps alter @@ -247,6 +287,7 @@ static void init_reg_sets_1 () { register unsigned int i, j; + register unsigned int /* enum machine_mode */ m; /* This macro allows the fixed or call-used registers and the register classes to depend on target flags. */ @@ -257,7 +298,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)) @@ -364,7 +405,7 @@ init_reg_sets_1 () CLEAR_HARD_REG_SET (call_used_reg_set); CLEAR_HARD_REG_SET (call_fixed_reg_set); - 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; @@ -386,34 +427,56 @@ init_reg_sets_1 () /* 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++) - { - int cost = i == j ? 2 : REGISTER_MOVE_COST (i, j); - enum reg_class *p1, *p2; + for (m = 0; m < MAX_MACHINE_MODE; m++) + for (i = 0; i < N_REG_CLASSES; i++) + for (j = 0; j < N_REG_CLASSES; j++) + { + int cost = i == j ? 2 : REGISTER_MOVE_COST (m, 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 (p2 = ®_class_subclasses[j][0]; *p2 != LIM_REG_CLASSES; p2++) + if (*p2 != i) + cost = MAX (cost, REGISTER_MOVE_COST (m, 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 (p1 = ®_class_subclasses[i][0]; *p1 != LIM_REG_CLASSES; p1++) + { + if (*p1 != j) + cost = MAX (cost, REGISTER_MOVE_COST (m, *p1, j)); - for (p2 = ®_class_subclasses[j][0]; - *p2 != LIM_REG_CLASSES; p2++) - if (*p1 != *p2) - cost = MAX (cost, REGISTER_MOVE_COST (*p1, *p2)); - } + for (p2 = ®_class_subclasses[j][0]; + *p2 != LIM_REG_CLASSES; p2++) + if (*p1 != *p2) + cost = MAX (cost, REGISTER_MOVE_COST (m, *p1, *p2)); + } - move_cost[i][j] = cost; + move_cost[m][i][j] = cost; - if (reg_class_subset_p (i, j)) - cost = 0; + if (reg_class_subset_p (i, j)) + may_move_in_cost[m][i][j] = 0; + else + may_move_in_cost[m][i][j] = cost; - may_move_cost[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; + } + +#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. @@ -456,8 +519,10 @@ 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); } #endif } @@ -476,7 +541,9 @@ memory_move_secondary_cost (mode, class, in) enum reg_class altclass; int partial_cost = 0; /* We need a memory reference to feed to SECONDARY... macros. */ - rtx mem = top_of_stack[(int) mode]; + /* mem may be unused even if the SECONDARY_ macros are defined. */ + rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode]; + if (in) { @@ -499,9 +566,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 @@ -524,8 +591,8 @@ memory_move_secondary_cost (mode, class, in) enum machine_mode choose_hard_reg_mode (regno, nregs) - int regno; - int nregs; + unsigned int regno ATTRIBUTE_UNUSED; + unsigned int nregs; { enum machine_mode found_mode = VOIDmode, mode; @@ -553,9 +620,11 @@ 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 (mode = CCmode; mode < NUM_MACHINE_MODES; ++mode) + 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; @@ -567,7 +636,7 @@ choose_hard_reg_mode (regno, nregs) void fix_register (name, fixed, call_used) - char *name; + const char *name; int fixed, call_used; { int i; @@ -586,7 +655,7 @@ fix_register (name, fixed, call_used) ) && (fixed == 0 || call_used == 0)) { - static char* what_option[2][2] = { + static const char * const what_option[2][2] = { { "call-saved", "call-used" }, { "no-such-option", "fixed" }}; @@ -611,6 +680,9 @@ void globalize_reg (i) int i; { + if (fixed_regs[i] == 0 && no_global_reg_vars) + error ("global register variable follows a function definition"); + if (global_regs[i]) { warning ("register used for two global register variables"); @@ -647,6 +719,22 @@ struct costs int mem_cost; }; +/* Structure used to record preferrences of given pseudo. */ +struct reg_pref +{ + /* (enum reg_class) prefclass is the preferred class. */ + char prefclass; + + /* altclass is a register class that we should use for allocating + pseudo if no register in the preferred class is available. + If no register in this class is available, memory is preferred. + + It might appear to be more general to have a bitmask of classes here, + but since it is recommended that there be a class corresponding to the + union of most major pair of classes, that generality is not required. */ + char altclass; +}; + /* Record the cost of each class for each pseudo. */ static struct costs *costs; @@ -655,52 +743,33 @@ static struct costs *costs; static struct costs init_cost; -/* Record the same data by operand number, accumulated for each alternative - in an insn. The contribution to a pseudo is that of the minimum-cost - alternative. */ - -static struct costs op_costs[MAX_RECOG_OPERANDS]; - -/* (enum reg_class) prefclass[R] is the preferred class for pseudo number R. - This is available after `regclass' is run. */ - -static char *prefclass; - -/* altclass[R] is a register class that we should use for allocating - pseudo number R if no register in the preferred class is available. - If no register in this class is available, memory is preferred. - - It might appear to be more general to have a bitmask of classes here, - but since it is recommended that there be a class corresponding to the - union of most major pair of classes, that generality is not required. - +/* Record preferrences of each pseudo. This is available after `regclass' is run. */ -static char *altclass; +static struct reg_pref *reg_pref; -/* Allocated buffers for prefclass and altclass. */ -static char *prefclass_buffer; -static char *altclass_buffer; +/* Allocated buffers for reg_pref. */ -/* Record the depth of loops that we are in. */ - -static int loop_depth; +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. */ static int loop_cost; -static rtx scan_one_insn PROTO((rtx, int)); -static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *, - const char **, rtx)); -static int copy_cost PROTO((rtx, enum machine_mode, +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 *, + const char **, rtx, + struct costs *, struct reg_pref *)); +static int copy_cost PARAMS ((rtx, enum machine_mode, enum reg_class, int)); -static void record_address_regs PROTO((rtx, enum reg_class, int)); +static void record_address_regs PARAMS ((rtx, enum reg_class, int)); #ifdef FORBIDDEN_INC_DEC_CLASSES -static int auto_inc_dec_reg_p PROTO((rtx, enum machine_mode)); +static int auto_inc_dec_reg_p PARAMS ((rtx, enum machine_mode)); #endif -static void reg_scan_mark_refs PROTO((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. @@ -710,19 +779,19 @@ enum reg_class reg_preferred_class (regno) int regno; { - if (prefclass == 0) + if (reg_pref == 0) return GENERAL_REGS; - return (enum reg_class) prefclass[regno]; + return (enum reg_class) reg_pref[regno].prefclass; } enum reg_class reg_alternate_class (regno) int regno; { - if (prefclass == 0) + if (reg_pref == 0) return ALL_REGS; - return (enum reg_class) altclass[regno]; + return (enum reg_class) reg_pref[regno].altclass; } /* Initialize some global data for this pass. */ @@ -738,7 +807,107 @@ regclass_init () /* This prevents dump_flow_info from losing if called before regclass is run. */ - prefclass = 0; + reg_pref = NULL; + + /* No more global register variables may be declared. */ + no_global_reg_vars = 1; +} + +/* Dump register costs. */ +static void +dump_regclass (dump) + FILE *dump; +{ + static const char *const reg_class_names[] = REG_CLASS_NAMES; + int i; + for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) + { + 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]); + fprintf (dump, " MEM:%i\n", costs[i].mem_cost); + } + } +} + + +/* Calculate the costs of insn operands. */ + +static void +record_operand_costs (insn, op_costs, reg_pref) + rtx insn; + struct costs *op_costs; + struct reg_pref *reg_pref; +{ + const char *constraints[MAX_RECOG_OPERANDS]; + enum machine_mode modes[MAX_RECOG_OPERANDS]; + int i; + + for (i = 0; i < recog_data.n_operands; i++) + { + constraints[i] = recog_data.constraints[i]; + modes[i] = recog_data.operand_mode[i]; + } + + /* If we get here, we are set up to record the costs of all the + operands for this insn. Start by initializing the costs. + Then handle any address registers. Finally record the desired + classes for any pseudos, doing it twice if some pair of + operands are commutative. */ + + for (i = 0; i < recog_data.n_operands; i++) + { + op_costs[i] = init_cost; + + if (GET_CODE (recog_data.operand[i]) == SUBREG) + { + rtx inner = SUBREG_REG (recog_data.operand[i]); +#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); + else if (constraints[i][0] == 'p') + record_address_regs (recog_data.operand[i], + BASE_REG_CLASS, loop_cost * 2); + } + + /* Check for commutative in a separate loop so everything will + have been initialized. We must do this even if one operand + is a constant--see addsi3 in m68k.md. */ + + for (i = 0; i < (int) recog_data.n_operands - 1; i++) + if (constraints[i][0] == '%') + { + const char *xconstraints[MAX_RECOG_OPERANDS]; + int j; + + /* Handle commutative operands by swapping the constraints. + We assume the modes are the same. */ + + for (j = 0; j < recog_data.n_operands; j++) + xconstraints[j] = constraints[j]; + + 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, + xconstraints, insn, op_costs, reg_pref); + } + + record_reg_classes (recog_data.n_alternatives, recog_data.n_operands, + recog_data.operand, modes, + constraints, insn, op_costs, reg_pref); } /* Subroutine of regclass, processes one insn INSN. Scan it and record each @@ -755,25 +924,9 @@ scan_one_insn (insn, pass) { enum rtx_code code = GET_CODE (insn); enum rtx_code pat_code; - const char *constraints[MAX_RECOG_OPERANDS]; - enum machine_mode modes[MAX_RECOG_OPERANDS]; rtx set, note; int i, j; - - /* Show that an insn inside a loop is likely to be executed three - times more than insns outside a loop. This is much more aggressive - than the assumptions made elsewhere and is being tried as an - experiment. */ - - if (code == NOTE) - { - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) - loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5)); - else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END) - loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5)); - - return insn; - } + struct costs op_costs[MAX_RECOG_OPERANDS]; if (GET_RTX_CLASS (code) != 'i') return insn; @@ -789,12 +942,6 @@ scan_one_insn (insn, pass) set = single_set (insn); extract_insn (insn); - for (i = 0; i < recog_n_operands; i++) - { - constraints[i] = recog_constraints[i]; - modes[i] = recog_operand_mode[i]; - } - /* If this insn loads a parameter from its stack slot, then it represents a savings, rather than a cost, if the parameter is stored in memory. Record this fact. */ @@ -827,24 +974,22 @@ scan_one_insn (insn, pass) do this during our first pass. */ if (pass == 0 && optimize - && recog_n_operands >= 3 - && recog_constraints[1][0] == '0' - && recog_constraints[1][1] == 0 - && CONSTANT_P (recog_operand[1]) - && ! rtx_equal_p (recog_operand[0], recog_operand[1]) - && ! rtx_equal_p (recog_operand[0], recog_operand[2]) - && GET_CODE (recog_operand[0]) == REG - && MODES_TIEABLE_P (GET_MODE (recog_operand[0]), - recog_operand_mode[1])) + && recog_data.n_operands >= 3 + && recog_data.constraints[1][0] == '0' + && recog_data.constraints[1][1] == 0 + && CONSTANT_P (recog_data.operand[1]) + && ! rtx_equal_p (recog_data.operand[0], recog_data.operand[1]) + && ! rtx_equal_p (recog_data.operand[0], recog_data.operand[2]) + && GET_CODE (recog_data.operand[0]) == REG + && MODES_TIEABLE_P (GET_MODE (recog_data.operand[0]), + recog_data.operand_mode[1])) { rtx previnsn = prev_real_insn (insn); rtx dest - = gen_lowpart (recog_operand_mode[1], - recog_operand[0]); + = gen_lowpart (recog_data.operand_mode[1], + recog_data.operand[0]); rtx newinsn - = emit_insn_before (gen_move_insn (dest, - recog_operand[1]), - insn); + = emit_insn_before (gen_move_insn (dest, recog_data.operand[1]), insn); /* If this insn was the start of a basic block, include the new insn in that block. @@ -860,71 +1005,26 @@ scan_one_insn (insn, pass) } /* This makes one more setting of new insns's dest. */ - REG_N_SETS (REGNO (recog_operand[0]))++; + REG_N_SETS (REGNO (recog_data.operand[0]))++; - *recog_operand_loc[1] = recog_operand[0]; - for (i = recog_n_dups - 1; i >= 0; i--) - if (recog_dup_num[i] == 1) - *recog_dup_loc[i] = recog_operand[0]; + *recog_data.operand_loc[1] = recog_data.operand[0]; + 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]; return PREV_INSN (newinsn); } - /* If we get here, we are set up to record the costs of all the - operands for this insn. Start by initializing the costs. - Then handle any address registers. Finally record the desired - classes for any pseudos, doing it twice if some pair of - operands are commutative. */ - - for (i = 0; i < recog_n_operands; i++) - { - op_costs[i] = init_cost; - - if (GET_CODE (recog_operand[i]) == SUBREG) - recog_operand[i] = SUBREG_REG (recog_operand[i]); - - if (GET_CODE (recog_operand[i]) == MEM) - record_address_regs (XEXP (recog_operand[i], 0), - BASE_REG_CLASS, loop_cost * 2); - else if (constraints[i][0] == 'p') - record_address_regs (recog_operand[i], - BASE_REG_CLASS, loop_cost * 2); - } - - /* Check for commutative in a separate loop so everything will - have been initialized. We must do this even if one operand - is a constant--see addsi3 in m68k.md. */ - - for (i = 0; i < recog_n_operands - 1; i++) - if (constraints[i][0] == '%') - { - const char *xconstraints[MAX_RECOG_OPERANDS]; - int j; - - /* Handle commutative operands by swapping the constraints. - We assume the modes are the same. */ - - for (j = 0; j < recog_n_operands; j++) - xconstraints[j] = constraints[j]; - - xconstraints[i] = constraints[i+1]; - xconstraints[i+1] = constraints[i]; - record_reg_classes (recog_n_alternatives, recog_n_operands, - recog_operand, modes, xconstraints, - insn); - } - - record_reg_classes (recog_n_alternatives, recog_n_operands, recog_operand, - modes, constraints, insn); + record_operand_costs (insn, op_costs, reg_pref); /* Now add the cost for each operand to the total costs for its register. */ - for (i = 0; i < recog_n_operands; i++) - if (GET_CODE (recog_operand[i]) == REG - && REGNO (recog_operand[i]) >= FIRST_PSEUDO_REGISTER) + for (i = 0; i < recog_data.n_operands; i++) + if (GET_CODE (recog_data.operand[i]) == REG + && REGNO (recog_data.operand[i]) >= FIRST_PSEUDO_REGISTER) { - int regno = REGNO (recog_operand[i]); + int regno = REGNO (recog_data.operand[i]); struct costs *p = &costs[regno], *q = &op_costs[i]; p->mem_cost += q->mem_cost * loop_cost; @@ -941,11 +1041,11 @@ scan_one_insn (insn, pass) This pass comes just before local register allocation. */ void -regclass (f, nregs) +regclass (f, nregs, dump) rtx f; int nregs; + FILE *dump; { -#ifdef REGISTER_CONSTRAINTS register rtx insn; register int i; int pass; @@ -954,9 +1054,13 @@ regclass (f, nregs) 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 *) alloca (nregs); + in_inc_dec = (char *) xmalloc (nregs); /* Initialize information about which register classes can be used for pseudos that are auto-incremented or auto-decremented. It would @@ -1014,35 +1118,61 @@ regclass (f, nregs) for (pass = 0; pass <= flag_expensive_optimizations; pass++) { + int index; + + if (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 - loop_depth = 0, loop_cost = 1; - /* Scan the instructions and record each time it would save code to put a certain register in a certain class. */ - for (insn = f; insn; insn = NEXT_INSN (insn)) + if (!optimize) { - insn = scan_one_insn (insn, pass); + loop_cost = 1; + for (insn = f; insn; insn = NEXT_INSN (insn)) + insn = scan_one_insn (insn, pass); } + else + for (index = 0; index < n_basic_blocks; index++) + { + basic_block bb = BASIC_BLOCK (index); + + /* Show that an insn inside a loop is likely to be executed three + times more than insns outside a loop. This is much more + aggressive than the assumptions made elsewhere and is being + tried as an experiment. */ + if (optimize_size) + loop_cost = 1; + else + loop_cost = 1 << (2 * MIN (bb->loop_depth, 5)); + for (insn = bb->head; ; insn = NEXT_INSN (insn)) + { + insn = scan_one_insn (insn, pass); + if (insn == bb->end) + break; + } + } /* Now for each register look at how desirable each class is and find which class is preferred. Store that in - `prefclass[REGNO]'. Record in `altclass[REGNO]' the largest register + `prefclass'. Record in `altclass' the largest register class any of whose registers is better than memory. */ if (pass == 0) - { - prefclass = prefclass_buffer; - altclass = altclass_buffer; - } + reg_pref = reg_pref_buffer; + if (dump) + { + dump_regclass (dump); + fprintf (dump,"\n"); + } for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++) { register int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; @@ -1052,6 +1182,11 @@ regclass (f, nregs) register int class; register struct costs *p = &costs[i]; + /* In non-optimizing compilation REG_N_REFS is not initialized + yet. */ + if (optimize && !REG_N_REFS (i)) + continue; + for (class = (int) ALL_REGS - 1; class > 0; class--) { /* Ignore classes that are too small for this operand or @@ -1061,6 +1196,10 @@ regclass (f, nregs) #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) @@ -1079,7 +1218,7 @@ regclass (f, nregs) should be provided as a register class. Don't do this if we will be doing it again later. */ - if (pass == 1 || ! flag_expensive_optimizations) + if ((pass == 1 || dump) || ! flag_expensive_optimizations) for (class = 0; class < N_REG_CLASSES; class++) if (p->cost[class] < p->mem_cost && (reg_class_size[(int) reg_class_subunion[(int) alt][class]] @@ -1087,6 +1226,10 @@ regclass (f, nregs) #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]; @@ -1094,18 +1237,37 @@ regclass (f, nregs) if (alt == best) alt = NO_REGS; + if (dump + && (reg_pref[i].prefclass != (int) best + || reg_pref[i].altclass != (int) alt)) + { + static const char *const reg_class_names[] = REG_CLASS_NAMES; + fprintf (dump, " Register %i", i); + if (alt == ALL_REGS || best == ALL_REGS) + fprintf (dump, " pref %s\n", reg_class_names[(int) best]); + else if (alt == NO_REGS) + fprintf (dump, " pref %s or none\n", reg_class_names[(int) best]); + else + fprintf (dump, " pref %s, else %s\n", + reg_class_names[(int) best], + reg_class_names[(int) alt]); + } + /* We cast to (int) because (char) hits bugs in some compilers. */ - prefclass[i] = (int) best; - altclass[i] = (int) alt; + reg_pref[i].prefclass = (int) best; + reg_pref[i].altclass = (int) alt; } } -#endif /* REGISTER_CONSTRAINTS */ +#ifdef FORBIDDEN_INC_DEC_CLASSES + free (in_inc_dec); +#endif +#ifdef CLASS_CANNOT_CHANGE_MODE + BITMAP_XFREE (reg_changes_mode); +#endif free (costs); } -#ifdef REGISTER_CONSTRAINTS - /* Record the cost of using memory or registers of various classes for the operands in INSN. @@ -1131,13 +1293,16 @@ regclass (f, nregs) alternatives. */ static void -record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) +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; const char **constraints; rtx insn; + struct costs *op_costs; + struct reg_pref *reg_pref; { int alt; int i, j; @@ -1152,6 +1317,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) int alt_fail = 0; int alt_cost = 0; enum reg_class classes[MAX_RECOG_OPERANDS]; + int allows_mem[MAX_RECOG_OPERANDS]; int class; for (i = 0; i < n_ops; i++) @@ -1159,12 +1325,13 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) const char *p = constraints[i]; rtx op = ops[i]; enum machine_mode mode = modes[i]; - int allows_mem = 0; + int allows_addr = 0; int win = 0; unsigned char c; /* Initially show we know nothing about the register class. */ classes[i] = NO_REGS; + allows_mem[i] = 0; /* If this operand has no constraints at all, we can conclude nothing about it since anything is valid. */ @@ -1172,7 +1339,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) 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; } @@ -1187,8 +1354,12 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) if (p[0] >= '0' && p[0] <= '0' + i && (p[1] == ',' || p[1] == 0)) { + /* Copy class and whether memory is allowed from the matching + alternative. Then perform any needed cost computations + and/or adjustments. */ j = p[0] - '0'; classes[i] = classes[j]; + allows_mem[i] = allows_mem[j]; if (GET_CODE (op) != REG || REGNO (op) < FIRST_PSEUDO_REGISTER) { @@ -1224,12 +1395,45 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) } else { - /* The costs of this operand are the same as that of the - other operand. However, if we cannot tie them, this - alternative needs to do a copy, which is one - instruction. */ + /* The costs of this operand are not the same as the other + operand since move costs are not symmetric. Moreover, + if we cannot tie them, this alternative needs to do a + copy, which is one instruction. */ + + struct costs *pp = &this_op_costs[i]; + + for (class = 0; class < N_REG_CLASSES; class++) + pp->cost[class] + = ((recog_data.operand_type[i] != OP_OUT + ? may_move_in_cost[mode][class][(int) classes[i]] + : 0) + + (recog_data.operand_type[i] != OP_IN + ? may_move_out_cost[mode][(int) classes[i]][class] + : 0)); + + /* If the alternative actually allows memory, make things + a bit cheaper since we won't need an extra insn to + load it. */ + + pp->mem_cost + = ((recog_data.operand_type[i] != OP_IN + ? MEMORY_MOVE_COST (mode, classes[i], 0) + : 0) + + (recog_data.operand_type[i] != OP_OUT + ? MEMORY_MOVE_COST (mode, classes[i], 1) + : 0) - allows_mem[i]); + + /* If we have assigned a class to this register in our + first pass, add a cost to this alternative corresponding + to what we would add if this register were not in the + appropriate class. */ + + if (reg_pref) + alt_cost + += (may_move_in_cost[mode] + [(unsigned char) reg_pref[REGNO (op)].prefclass] + [(int) classes[i]]); - this_op_costs[i] = this_op_costs[j]; if (REGNO (ops[i]) != REGNO (ops[j]) && ! find_reg_note (insn, REG_DEAD, op)) alt_cost += 2; @@ -1262,13 +1466,23 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) case '!': case '#': case '&': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + break; + case 'p': + allows_addr = 1; + win = address_operand (op, GET_MODE (op)); + /* We know this operand is an address, so we want it to be + allocated to a register that can be the base of an + address, ie BASE_REG_CLASS. */ + classes[i] + = reg_class_subunion[(int) classes[i]] + [(int) BASE_REG_CLASS]; break; case 'm': case 'o': case 'V': /* It doesn't seem worth distinguishing between offsettable and non-offsettable addresses here. */ - allows_mem = 1; + allows_mem[i] = 1; if (GET_CODE (op) == MEM) win = 1; break; @@ -1350,17 +1564,6 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) 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) @@ -1369,16 +1572,22 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) #endif )) win = 1; - allows_mem = 1; + allows_mem[i] = 1; case 'r': classes[i] = reg_class_subunion[(int) classes[i]][(int) GENERAL_REGS]; 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; @@ -1393,29 +1602,50 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) if (GET_CODE (op) == REG && REGNO (op) >= FIRST_PSEUDO_REGISTER) { if (classes[i] == NO_REGS) - 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 { struct costs *pp = &this_op_costs[i]; for (class = 0; class < N_REG_CLASSES; class++) - pp->cost[class] = may_move_cost[class][(int) classes[i]]; + pp->cost[class] + = ((recog_data.operand_type[i] != OP_OUT + ? may_move_in_cost[mode][class][(int) classes[i]] + : 0) + + (recog_data.operand_type[i] != OP_IN + ? may_move_out_cost[mode][(int) classes[i]][class] + : 0)); /* If the alternative actually allows memory, make things a bit cheaper since we won't need an extra insn to load it. */ - pp->mem_cost = (MEMORY_MOVE_COST (mode, classes[i], 1) - - allows_mem); + pp->mem_cost + = ((recog_data.operand_type[i] != OP_IN + ? MEMORY_MOVE_COST (mode, classes[i], 0) + : 0) + + (recog_data.operand_type[i] != OP_OUT + ? MEMORY_MOVE_COST (mode, classes[i], 1) + : 0) - allows_mem[i]); /* If we have assigned a class to this register in our first pass, add a cost to this alternative corresponding to what we would add if this register were not in the appropriate class. */ - if (prefclass) + if (reg_pref) alt_cost - += may_move_cost[(unsigned char)prefclass[REGNO (op)]][(int) classes[i]]; + += (may_move_in_cost[mode] + [(unsigned char) reg_pref[REGNO (op)].prefclass] + [(int) classes[i]]); } } @@ -1433,17 +1663,17 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) else if (classes[i] != NO_REGS) { - if (recog_op_type[i] != OP_OUT) + if (recog_data.operand_type[i] != OP_OUT) alt_cost += copy_cost (op, mode, classes[i], 1); - if (recog_op_type[i] != OP_IN) + if (recog_data.operand_type[i] != OP_IN) alt_cost += copy_cost (op, mode, classes[i], 0); } /* The only other way this alternative can be used is if this is a constant that could be placed into memory. */ - else if (CONSTANT_P (op) && allows_mem) + else if (CONSTANT_P (op) && (allows_addr || allows_mem[i])) alt_cost += MEMORY_MOVE_COST (mode, classes[i], 1); else alt_fail = 1; @@ -1460,7 +1690,7 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) && REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER) { struct costs *pp = &op_costs[i], *qq = &this_op_costs[i]; - int scale = 1 + (recog_op_type[i] == OP_INOUT); + int scale = 1 + (recog_data.operand_type[i] == OP_INOUT); pp->mem_cost = MIN (pp->mem_cost, (qq->mem_cost + alt_cost) * scale); @@ -1472,24 +1702,40 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) } /* 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. */ + and one operand is a pseudo with the other a hard reg or a pseudo + that prefers a register that is in its own register class then + we may want to adjust the cost of that register class to -1. + + Avoid the adjustment if the source does not die to avoid stressing of + register allocator by preferrencing two coliding registers into single + class. + + Also avoid the adjustment if a copy between registers of the class + is expensive (ten times the cost of a default copy is considered + arbitrarily expensive). This avoids losing when the preferred class + is very expensive as the source of a copy instruction. */ 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) + && GET_CODE (ops[0]) == REG && GET_CODE (ops[1]) == REG + && find_regno_note (insn, REG_DEAD, REGNO (ops[1]))) 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) + { + enum reg_class pref = reg_pref[regno].prefclass; - if (regno >= FIRST_PSEUDO_REGISTER && prefclass != 0 - && (reg_class_size[(unsigned char)prefclass[regno]] - == CLASS_MAX_NREGS (prefclass[regno], mode))) - op_costs[i].cost[(unsigned char)prefclass[regno]] = -1; + if ((reg_class_size[(unsigned char) pref] + == CLASS_MAX_NREGS (pref, mode)) + && REGISTER_MOVE_COST (mode, pref, pref) < 10 * 2) + op_costs[i].cost[(unsigned char) pref] = -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) @@ -1499,13 +1745,14 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) 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; } } @@ -1520,9 +1767,9 @@ record_reg_classes (n_alts, n_ops, ops, modes, constraints, insn) static int copy_cost (x, mode, class, to_p) rtx x; - enum machine_mode mode; + enum machine_mode mode ATTRIBUTE_UNUSED; enum reg_class class; - int to_p; + int to_p ATTRIBUTE_UNUSED; { #ifdef HAVE_SECONDARY_RELOADS enum reg_class secondary_class = NO_REGS; @@ -1554,7 +1801,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 */ @@ -1566,11 +1813,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 @@ -1604,10 +1851,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 @@ -1680,13 +1927,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); @@ -1706,6 +1953,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: @@ -1732,13 +1990,13 @@ 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_cost[i][(int) class] * scale) / 2; + pp->cost[i] += (may_move_in_cost[Pmode][i][(int) class] * scale) / 2; } break; default: { - register char *fmt = GET_RTX_FORMAT (code); + register const char *fmt = GET_RTX_FORMAT (code); register int i; for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) if (fmt[i] == 'e') @@ -1776,11 +2034,10 @@ auto_inc_dec_reg_p (reg, mode) return 0; } #endif - -#endif /* REGISTER_CONSTRAINTS */ -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 @@ -1799,7 +2056,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) { @@ -1812,8 +2068,8 @@ allocate_reg_info (num_regs, new_p, renumber_p) { VARRAY_REG_INIT (reg_n_info, regno_allocated, "reg_n_info"); renumber = (short *) xmalloc (size_renumber); - prefclass_buffer = (char *) xmalloc (regno_allocated); - altclass_buffer = (char *) xmalloc (regno_allocated); + reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated + * sizeof (struct reg_pref)); } else @@ -1823,21 +2079,18 @@ allocate_reg_info (num_regs, new_p, renumber_p) if (new_p) /* if we're zapping everything, no need to realloc */ { free ((char *)renumber); - free ((char *)prefclass_buffer); - free ((char *)altclass_buffer); + free ((char *)reg_pref); renumber = (short *) xmalloc (size_renumber); - prefclass_buffer = (char *) xmalloc (regno_allocated); - altclass_buffer = (char *) xmalloc (regno_allocated); + reg_pref_buffer = (struct reg_pref *) xmalloc (regno_allocated + * sizeof (struct reg_pref)); } else { renumber = (short *) xrealloc ((char *)renumber, size_renumber); - prefclass_buffer = (char *) xrealloc ((char *)prefclass_buffer, - regno_allocated); - - altclass_buffer = (char *) xrealloc ((char *)altclass_buffer, - regno_allocated); + reg_pref_buffer = (struct reg_pref *) xrealloc ((char *)reg_pref_buffer, + regno_allocated + * sizeof (struct reg_pref)); } } @@ -1855,45 +2108,42 @@ 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; - prefclass_buffer[i] = (char) NO_REGS; - altclass_buffer[i] = (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; } } } /* If {pref,alt}class have already been allocated, update the pointers to the newly realloced ones. */ - if (prefclass) - { - prefclass = prefclass_buffer; - altclass = altclass_buffer; - } + if (reg_pref) + reg_pref = reg_pref_buffer; if (renumber_p) reg_renumber = renumber; @@ -1918,10 +2168,8 @@ free_reg_info () free ((char *)reg_data); } - free (prefclass_buffer); - free (altclass_buffer); - prefclass_buffer = (char *)0; - altclass_buffer = (char *)0; + free (reg_pref_buffer); + reg_pref_buffer = (struct reg_pref *)0; reg_info_head = (struct reg_info_data *)0; renumber = (short *)0; } @@ -1947,8 +2195,8 @@ int max_parallel; void reg_scan (f, nregs, repeat) rtx f; - int nregs; - int repeat; + unsigned int nregs; + int repeat ATTRIBUTE_UNUSED; { register rtx insn; @@ -1976,10 +2224,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; @@ -2010,7 +2258,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; @@ -2032,7 +2280,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) { @@ -2087,18 +2335,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 @@ -2115,13 +2363,13 @@ 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 ... */ default: { - register char *fmt = GET_RTX_FORMAT (code); + register const char *fmt = GET_RTX_FORMAT (code); register int i; for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) { @@ -2189,12 +2437,5 @@ reg_classes_intersect_p (c1, c2) void regset_release_memory () { - if (basic_block_live_at_start) - { - free_regset_vector (basic_block_live_at_start, n_basic_blocks); - basic_block_live_at_start = 0; - } - - FREE_REG_SET (regs_live_at_setjmp); bitmap_release_memory (); }