X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fira-costs.c;h=491b86bb841ca1ca5e5df3e03601daaf5e694a23;hb=21353ca06d17bd628a639e18b363cad329504afb;hp=4dd7003adebf2b3552421ba73906f99e0947f11e;hpb=971ba038cb2a1622217c016dc0203452f9bc5dcd;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 4dd7003adeb..491b86bb841 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -1,4 +1,4 @@ -/* IRA hard register and memory cost calculation for allocnos. +/* IRA hard register and memory cost calculation for allocnos or pseudos. Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Vladimir Makarov . @@ -38,18 +38,25 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "ira-int.h" -/* The file contains code is similar to one in regclass but the code - works on the allocno basis. */ +/* The flags is set up every time when we calculate pseudo register + classes through function ira_set_pseudo_classes. */ +static bool pseudo_classes_defined_p = false; + +/* TRUE if we work with allocnos. Otherwise we work with pseudos. */ +static bool allocno_p; + +/* Number of elements in arrays `in_inc_dec' and `costs'. */ +static int cost_elements_num; #ifdef FORBIDDEN_INC_DEC_CLASSES -/* Indexed by n, is TRUE if allocno with number N is used in an - auto-inc or auto-dec context. */ +/* Indexed by n, is TRUE if allocno or pseudo with number N is used in + an auto-inc or auto-dec context. */ static bool *in_inc_dec; #endif /* The `costs' struct records the cost of using hard registers of each class considered for the calculation and of using memory for each - allocno. */ + allocno or pseudo. */ struct costs { int mem_cost; @@ -74,8 +81,11 @@ static struct costs *temp_costs; static struct costs *op_costs[MAX_RECOG_OPERANDS]; static struct costs *this_op_costs[MAX_RECOG_OPERANDS]; -/* Original and accumulated costs of each class for each allocno. */ -static struct costs *allocno_costs, *total_costs; +/* Costs of each class for each allocno or pseudo. */ +static struct costs *costs; + +/* Accumulated costs of each class for each allocno. */ +static struct costs *total_allocno_costs; /* Classes used for cost calculation. They may be different on different iterations of the cost calculations or in different @@ -92,21 +102,26 @@ static int cost_class_nums[N_REG_CLASSES]; /* It is the current size of struct costs. */ static int struct_costs_size; -/* Return pointer to structure containing costs of allocno with given - NUM in array ARR. */ -#define COSTS_OF_ALLOCNO(arr, num) \ +/* Return pointer to structure containing costs of allocno or pseudo + with given NUM in array ARR. */ +#define COSTS(arr, num) \ ((struct costs *) ((char *) (arr) + (num) * struct_costs_size)) -/* Record register class preferences of each allocno. Null value - means no preferences. It happens on the 1st iteration of the cost - calculation. */ -static enum reg_class *allocno_pref; +/* Return index in COSTS when processing reg with REGNO. */ +#define COST_INDEX(regno) (allocno_p \ + ? ALLOCNO_NUM (ira_curr_regno_allocno_map[regno]) \ + : (int) regno) + +/* Record register class preferences of each allocno or pseudo. Null + value means no preferences. It happens on the 1st iteration of the + cost calculation. */ +static enum reg_class *pref; -/* Allocated buffers for allocno_pref. */ -static enum reg_class *allocno_pref_buffer; +/* Allocated buffers for pref. */ +static enum reg_class *pref_buffer; -/* Record register class of each allocno with the same regno. */ -static enum reg_class *common_classes; +/* Record cover register class of each allocno with the same regno. */ +static enum reg_class *regno_cover_class; /* Execution frequency of the current insn. */ static int frequency; @@ -189,7 +204,7 @@ static void record_reg_classes (int n_alts, int n_ops, rtx *ops, enum machine_mode *modes, const char **constraints, rtx insn, struct costs **op_costs, - enum reg_class *allocno_pref) + enum reg_class *pref) { int alt; int i, j, k; @@ -209,6 +224,14 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, int alt_fail = 0; int alt_cost = 0, op_cost_add; + if (!recog_data.alternative_enabled_p[alt]) + { + for (i = 0; i < recog_data.n_operands; i++) + constraints[i] = skip_alternative (constraints[i]); + + continue; + } + for (i = 0; i < n_ops; i++) { unsigned char c; @@ -320,12 +343,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, were not in the appropriate class. We could use cover class here but it is less accurate approximation. */ - if (allocno_pref) + if (pref) { - enum reg_class pref_class - = allocno_pref[ALLOCNO_NUM - (ira_curr_regno_allocno_map - [REGNO (op)])]; + enum reg_class pref_class = pref[COST_INDEX (REGNO (op))]; if (pref_class == NO_REGS) alt_cost @@ -355,7 +375,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, continue; } } - + /* Scan all the constraint letters. See if the operand matches any of the constraints. Collect the valid register classes and see if this operand accepts @@ -564,12 +584,9 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, were not in the appropriate class. We could use cover class here but it is less accurate approximation. */ - if (allocno_pref) + if (pref) { - enum reg_class pref_class - = allocno_pref[ALLOCNO_NUM - (ira_curr_regno_allocno_map - [REGNO (op)])]; + enum reg_class pref_class = pref[COST_INDEX (REGNO (op))]; if (pref_class == NO_REGS) alt_cost @@ -637,17 +654,18 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, } } - for (i = 0; i < n_ops; i++) - { - ira_allocno_t a; - rtx op = ops[i]; - - if (! REG_P (op) || REGNO (op) < FIRST_PSEUDO_REGISTER) - continue; - a = ira_curr_regno_allocno_map [REGNO (op)]; - if (! ALLOCNO_BAD_SPILL_P (a) && insn_allows_mem[i] == 0) - ALLOCNO_BAD_SPILL_P (a) = true; - } + if (allocno_p) + for (i = 0; i < n_ops; i++) + { + ira_allocno_t a; + rtx op = ops[i]; + + if (! REG_P (op) || REGNO (op) < FIRST_PSEUDO_REGISTER) + continue; + a = ira_curr_regno_allocno_map [REGNO (op)]; + if (! ALLOCNO_BAD_SPILL_P (a) && insn_allows_mem[i] == 0) + ALLOCNO_BAD_SPILL_P (a) = true; + } /* If this insn is a single set copying operand 1 to operand 0 and one operand is an allocno with the other a hard reg or an allocno @@ -693,7 +711,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], regno + nr)) break; - + if (nr == (unsigned) hard_regno_nregs[regno][mode]) op_costs[i]->cost[k] = -frequency; } @@ -877,8 +895,7 @@ record_address_regs (enum machine_mode mode, rtx x, int context, #ifdef FORBIDDEN_INC_DEC_CLASSES if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER) - in_inc_dec[ALLOCNO_NUM (ira_curr_regno_allocno_map - [REGNO (XEXP (x, 0))])] = true; + in_inc_dec[COST_INDEX (REGNO (XEXP (x, 0)))] = true; #endif record_address_regs (mode, XEXP (x, 0), 0, code, SCRATCH, 2 * scale); break; @@ -892,10 +909,9 @@ record_address_regs (enum machine_mode mode, rtx x, int context, if (REGNO (x) < FIRST_PSEUDO_REGISTER) break; - ALLOCNO_BAD_SPILL_P (ira_curr_regno_allocno_map[REGNO (x)]) = true; - pp = COSTS_OF_ALLOCNO (allocno_costs, - ALLOCNO_NUM (ira_curr_regno_allocno_map - [REGNO (x)])); + if (allocno_p) + ALLOCNO_BAD_SPILL_P (ira_curr_regno_allocno_map[REGNO (x)]) = true; + pp = COSTS (costs, COST_INDEX (REGNO (x))); pp->mem_cost += (ira_memory_move_cost[Pmode][rclass][1] * scale) / 2; for (k = 0; k < cost_classes_num; k++) { @@ -922,8 +938,7 @@ record_address_regs (enum machine_mode mode, rtx x, int context, /* Calculate the costs of insn operands. */ static void -record_operand_costs (rtx insn, struct costs **op_costs, - enum reg_class *allocno_pref) +record_operand_costs (rtx insn, struct costs **op_costs, enum reg_class *pref) { const char *constraints[MAX_RECOG_OPERANDS]; enum machine_mode modes[MAX_RECOG_OPERANDS]; @@ -976,11 +991,11 @@ record_operand_costs (rtx insn, struct costs **op_costs, xconstraints[i+1] = constraints[i]; record_reg_classes (recog_data.n_alternatives, recog_data.n_operands, recog_data.operand, modes, - xconstraints, insn, op_costs, allocno_pref); + xconstraints, insn, op_costs, pref); } record_reg_classes (recog_data.n_alternatives, recog_data.n_operands, recog_data.operand, modes, - constraints, insn, op_costs, allocno_pref); + constraints, insn, op_costs, pref); } @@ -995,7 +1010,7 @@ scan_one_insn (rtx insn) rtx set, note; int i, k; - if (!INSN_P (insn)) + if (!NONDEBUG_INSN_P (insn)) return insn; pat_code = GET_CODE (PATTERN (insn)); @@ -1015,17 +1030,17 @@ scan_one_insn (rtx insn) { enum reg_class cl = GENERAL_REGS; rtx reg = SET_DEST (set); - int num = ALLOCNO_NUM (ira_curr_regno_allocno_map[REGNO (reg)]); + int num = COST_INDEX (REGNO (reg)); - if (allocno_pref) - cl = allocno_pref[num]; - COSTS_OF_ALLOCNO (allocno_costs, num)->mem_cost + if (pref) + cl = pref[num]; + COSTS (costs, num)->mem_cost -= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency; record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0), 0, MEM, SCRATCH, frequency * 2); } - record_operand_costs (insn, op_costs, allocno_pref); + record_operand_costs (insn, op_costs, pref); /* Now add the cost for each operand to the total costs for its allocno. */ @@ -1034,9 +1049,7 @@ scan_one_insn (rtx insn) && REGNO (recog_data.operand[i]) >= FIRST_PSEUDO_REGISTER) { int regno = REGNO (recog_data.operand[i]); - struct costs *p - = COSTS_OF_ALLOCNO (allocno_costs, - ALLOCNO_NUM (ira_curr_regno_allocno_map[regno])); + struct costs *p = COSTS (costs, COST_INDEX (regno)); struct costs *q = op_costs[i]; p->mem_cost += q->mem_cost; @@ -1051,12 +1064,13 @@ scan_one_insn (rtx insn) /* Print allocnos costs to file F. */ static void -print_costs (FILE *f) +print_allocno_costs (FILE *f) { int k; ira_allocno_t a; ira_allocno_iterator ai; + ira_assert (allocno_p); fprintf (f, "\n"); FOR_EACH_ALLOCNO (a, ai) { @@ -1085,27 +1099,56 @@ print_costs (FILE *f) ) { fprintf (f, " %s:%d", reg_class_names[rclass], - COSTS_OF_ALLOCNO (allocno_costs, i)->cost[k]); + COSTS (costs, i)->cost[k]); if (flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED) - fprintf (f, ",%d", COSTS_OF_ALLOCNO (total_costs, i)->cost[k]); + fprintf (f, ",%d", COSTS (total_allocno_costs, i)->cost[k]); } } - fprintf (f, " MEM:%i\n", COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost); + fprintf (f, " MEM:%i\n", COSTS (costs, i)->mem_cost); + } +} + +/* Print pseudo costs to file F. */ +static void +print_pseudo_costs (FILE *f) +{ + int regno, k; + int rclass; + + ira_assert (! allocno_p); + fprintf (f, "\n"); + for (regno = max_reg_num () - 1; regno >= FIRST_PSEUDO_REGISTER; regno--) + { + if (regno_reg_rtx[regno] == NULL_RTX) + continue; + fprintf (f, " r%d costs:", regno); + for (k = 0; k < cost_classes_num; k++) + { + rclass = cost_classes[k]; + if (contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (regno)] +#ifdef FORBIDDEN_INC_DEC_CLASSES + && (! in_inc_dec[regno] || ! forbidden_inc_dec_class[rclass]) +#endif +#ifdef CANNOT_CHANGE_MODE_CLASS + && ! invalid_mode_change_p (regno, (enum reg_class) rclass, + PSEUDO_REGNO_MODE (regno)) +#endif + ) + fprintf (f, " %s:%d", reg_class_names[rclass], + COSTS (costs, regno)->cost[k]); + } + fprintf (f, " MEM:%i\n", COSTS (costs, regno)->mem_cost); } } /* Traverse the BB represented by LOOP_TREE_NODE to update the allocno costs. */ static void -process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node) +process_bb_for_costs (basic_block bb) { - basic_block bb; rtx insn; - bb = loop_tree_node->bb; - if (bb == NULL) - return; frequency = REG_FREQ_FROM_BB (bb); if (frequency == 0) frequency = 1; @@ -1113,29 +1156,57 @@ process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node) insn = scan_one_insn (insn); } -/* Find costs of register classes and memory for allocnos and their - best costs. */ +/* Traverse the BB represented by LOOP_TREE_NODE to update the allocno + costs. */ static void -find_allocno_class_costs (void) +process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node) { - int i, k; + basic_block bb; + + bb = loop_tree_node->bb; + if (bb != NULL) + process_bb_for_costs (bb); +} + +/* Find costs of register classes and memory for allocnos or pseudos + and their best costs. Set up preferred, alternative and cover + classes for pseudos. */ +static void +find_costs_and_classes (FILE *dump_file) +{ + int i, k, start; int pass; basic_block bb; init_recog (); #ifdef FORBIDDEN_INC_DEC_CLASSES - in_inc_dec = ira_allocate (sizeof (bool) * ira_allocnos_num); + in_inc_dec = ira_allocate (sizeof (bool) * cost_elements_num); #endif /* FORBIDDEN_INC_DEC_CLASSES */ - allocno_pref = NULL; + pref = NULL; + start = 0; + if (!resize_reg_info () && allocno_p && pseudo_classes_defined_p) + { + ira_allocno_t a; + ira_allocno_iterator ai; + + pref = pref_buffer; + FOR_EACH_ALLOCNO (a, ai) + pref[ALLOCNO_NUM (a)] = reg_preferred_class (ALLOCNO_REGNO (a)); + if (flag_expensive_optimizations) + start = 1; + } + if (allocno_p) + /* Clear the flag for the next compiled function. */ + pseudo_classes_defined_p = false; /* Normally we scan the insns once and determine the best class to use for each allocno. However, if -fexpensive-optimizations are on, we do so twice, the second time using the tentative best classes to guide the selection. */ - for (pass = 0; pass <= flag_expensive_optimizations; pass++) + for (pass = start; pass <= flag_expensive_optimizations; pass++) { - if (internal_flag_ira_verbose > 0 && ira_dump_file) - fprintf (ira_dump_file, "\nPass %i for finding allocno costs\n\n", - pass); + if ((!allocno_p || internal_flag_ira_verbose > 0) && dump_file) + fprintf (dump_file, + "\nPass %i for finding pseudo/allocno costs\n\n", pass); /* We could use only cover classes. Unfortunately it does not work well for some targets where some subclass of cover class is costly and wrong cover class is chosen. */ @@ -1154,20 +1225,31 @@ find_allocno_class_costs (void) = sizeof (struct costs) + sizeof (int) * (cost_classes_num - 1); /* Zero out our accumulation of the cost of each class for each allocno. */ - memset (allocno_costs, 0, ira_allocnos_num * struct_costs_size); + memset (costs, 0, cost_elements_num * struct_costs_size); #ifdef FORBIDDEN_INC_DEC_CLASSES - memset (in_inc_dec, 0, ira_allocnos_num * sizeof (bool)); + memset (in_inc_dec, 0, cost_elements_num * sizeof (bool)); #endif - /* Scan the instructions and record each time it would save code - to put a certain allocno in a certain class. */ - ira_traverse_loop_tree (true, ira_loop_tree_root, - process_bb_node_for_costs, NULL); + if (allocno_p) + { + /* Scan the instructions and record each time it would save code + to put a certain allocno in a certain class. */ + ira_traverse_loop_tree (true, ira_loop_tree_root, + process_bb_node_for_costs, NULL); + + memcpy (total_allocno_costs, costs, + max_struct_costs_size * ira_allocnos_num); + } + else + { + basic_block bb; + + FOR_EACH_BB (bb) + process_bb_for_costs (bb); + } - memcpy (total_costs, allocno_costs, - max_struct_costs_size * ira_allocnos_num); if (pass == 0) - allocno_pref = allocno_pref_buffer; + pref = pref_buffer; /* Now for each allocno look at how desirable each class is and find which class is preferred. */ @@ -1182,41 +1264,52 @@ find_allocno_class_costs (void) int inc_dec_p = false; #endif - if (ira_regno_allocno_map[i] == NULL) - continue; - memset (temp_costs, 0, struct_costs_size); - /* Find cost of all allocnos with the same regno. */ - for (a = ira_regno_allocno_map[i]; - a != NULL; - a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) + if (! allocno_p) { - a_num = ALLOCNO_NUM (a); - if ((flag_ira_region == IRA_REGION_ALL - || flag_ira_region == IRA_REGION_MIXED) - && (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) != NULL - && (parent_a = parent->regno_allocno_map[i]) != NULL - /* There are no caps yet. */ - && bitmap_bit_p (ALLOCNO_LOOP_TREE_NODE (a)->border_allocnos, - ALLOCNO_NUM (a))) + if (regno_reg_rtx[i] == NULL_RTX) + continue; +#ifdef FORBIDDEN_INC_DEC_CLASSES + inc_dec_p = in_inc_dec[i]; +#endif + memcpy (temp_costs, COSTS (costs, i), struct_costs_size); + } + else + { + if (ira_regno_allocno_map[i] == NULL) + continue; + memset (temp_costs, 0, struct_costs_size); + /* Find cost of all allocnos with the same regno. */ + for (a = ira_regno_allocno_map[i]; + a != NULL; + a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { - /* Propagate costs to upper levels in the region - tree. */ - parent_a_num = ALLOCNO_NUM (parent_a); + a_num = ALLOCNO_NUM (a); + if ((flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) + && (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) != NULL + && (parent_a = parent->regno_allocno_map[i]) != NULL + /* There are no caps yet. */ + && bitmap_bit_p (ALLOCNO_LOOP_TREE_NODE + (a)->border_allocnos, + ALLOCNO_NUM (a))) + { + /* Propagate costs to upper levels in the region + tree. */ + parent_a_num = ALLOCNO_NUM (parent_a); + for (k = 0; k < cost_classes_num; k++) + COSTS (total_allocno_costs, parent_a_num)->cost[k] + += COSTS (total_allocno_costs, a_num)->cost[k]; + COSTS (total_allocno_costs, parent_a_num)->mem_cost + += COSTS (total_allocno_costs, a_num)->mem_cost; + } for (k = 0; k < cost_classes_num; k++) - COSTS_OF_ALLOCNO (total_costs, parent_a_num)->cost[k] - += COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k]; - COSTS_OF_ALLOCNO (total_costs, parent_a_num)->mem_cost - += COSTS_OF_ALLOCNO (total_costs, a_num)->mem_cost; - } - for (k = 0; k < cost_classes_num; k++) - temp_costs->cost[k] - += COSTS_OF_ALLOCNO (allocno_costs, a_num)->cost[k]; - temp_costs->mem_cost - += COSTS_OF_ALLOCNO (allocno_costs, a_num)->mem_cost; + temp_costs->cost[k] += COSTS (costs, a_num)->cost[k]; + temp_costs->mem_cost += COSTS (costs, a_num)->mem_cost; #ifdef FORBIDDEN_INC_DEC_CLASSES - if (in_inc_dec[a_num]) - inc_dec_p = true; + if (in_inc_dec[a_num]) + inc_dec_p = true; #endif + } } best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; best = ALL_REGS; @@ -1252,38 +1345,45 @@ find_allocno_class_costs (void) alt_class = reg_class_subunion[alt_class][rclass]; } alt_class = ira_class_translate[alt_class]; - if (pass == flag_expensive_optimizations) - { - if (best_cost > temp_costs->mem_cost) - best = alt_class = NO_REGS; - else if (best == alt_class) - alt_class = NO_REGS; - setup_reg_classes (i, best, alt_class); - if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) - fprintf (ira_dump_file, - " r%d: preferred %s, alternative %s\n", - i, reg_class_names[best], reg_class_names[alt_class]); - } if (best_cost > temp_costs->mem_cost) - common_classes[i] = NO_REGS; + regno_cover_class[i] = NO_REGS; else if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) /* Make the common class the biggest class of best and alt_class. */ - common_classes[i] = alt_class == NO_REGS ? best : alt_class; + regno_cover_class[i] = alt_class == NO_REGS ? best : alt_class; else /* Make the common class a cover class. Remember all allocnos with the same regno should have the same cover class. */ - common_classes[i] = ira_class_translate[best]; + regno_cover_class[i] = ira_class_translate[best]; + if (pass == flag_expensive_optimizations) + { + if (best_cost > temp_costs->mem_cost) + best = alt_class = NO_REGS; + else if (best == alt_class) + alt_class = NO_REGS; + setup_reg_classes (i, best, alt_class, regno_cover_class[i]); + if ((!allocno_p || internal_flag_ira_verbose > 2) + && dump_file != NULL) + fprintf (dump_file, + " r%d: preferred %s, alternative %s, cover %s\n", + i, reg_class_names[best], reg_class_names[alt_class], + reg_class_names[regno_cover_class[i]]); + } + if (! allocno_p) + { + pref[i] = best_cost > temp_costs->mem_cost ? NO_REGS : best; + continue; + } for (a = ira_regno_allocno_map[i]; a != NULL; a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { a_num = ALLOCNO_NUM (a); - if (common_classes[i] == NO_REGS) + if (regno_cover_class[i] == NO_REGS) best = NO_REGS; else - { + { /* Finding best class which is subset of the common class. */ best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; @@ -1292,7 +1392,7 @@ find_allocno_class_costs (void) for (k = 0; k < cost_classes_num; k++) { rclass = cost_classes[k]; - if (! ira_class_subset_p[rclass][common_classes[i]]) + if (! ira_class_subset_p[rclass][regno_cover_class[i]]) continue; /* Ignore classes that are too small for this operand or invalid for an operand that was @@ -1307,50 +1407,50 @@ find_allocno_class_costs (void) #endif ) ; - else if (COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k] + else if (COSTS (total_allocno_costs, a_num)->cost[k] < best_cost) { best_cost - = COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k]; - allocno_cost - = COSTS_OF_ALLOCNO (allocno_costs, a_num)->cost[k]; + = COSTS (total_allocno_costs, a_num)->cost[k]; + allocno_cost = COSTS (costs, a_num)->cost[k]; best = (enum reg_class) rclass; } - else if (COSTS_OF_ALLOCNO (total_costs, a_num)->cost[k] + else if (COSTS (total_allocno_costs, a_num)->cost[k] == best_cost) { best = ira_reg_class_union[best][rclass]; allocno_cost - = MAX (allocno_cost, - COSTS_OF_ALLOCNO (allocno_costs, - a_num)->cost[k]); + = MAX (allocno_cost, COSTS (costs, a_num)->cost[k]); } } ALLOCNO_COVER_CLASS_COST (a) = allocno_cost; } ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY - || ira_class_translate[best] == common_classes[i]); - if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL - && (pass == 0 || allocno_pref[a_num] != best)) + || ira_class_translate[best] == regno_cover_class[i]); + if (internal_flag_ira_verbose > 2 && dump_file != NULL + && (pass == 0 || pref[a_num] != best)) { - fprintf (ira_dump_file, " a%d (r%d,", a_num, i); + fprintf (dump_file, " a%d (r%d,", a_num, i); if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL) - fprintf (ira_dump_file, "b%d", bb->index); + fprintf (dump_file, "b%d", bb->index); else - fprintf (ira_dump_file, "l%d", + fprintf (dump_file, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop->num); - fprintf (ira_dump_file, ") best %s, cover %s\n", + fprintf (dump_file, ") best %s, cover %s\n", reg_class_names[best], - reg_class_names[common_classes[i]]); + reg_class_names[regno_cover_class[i]]); } - allocno_pref[a_num] = best; + pref[a_num] = best; } } - - if (internal_flag_ira_verbose > 4 && ira_dump_file) + + if (internal_flag_ira_verbose > 4 && dump_file) { - print_costs (ira_dump_file); - fprintf (ira_dump_file,"\n"); + if (allocno_p) + print_allocno_costs (dump_file); + else + print_pseudo_costs (dump_file); + fprintf (dump_file,"\n"); } } #ifdef FORBIDDEN_INC_DEC_CLASSES @@ -1384,7 +1484,7 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node) freq = 1; FOR_BB_INSNS (bb, insn) { - if (! INSN_P (insn)) + if (!NONDEBUG_INSN_P (insn)) continue; set = single_set (insn); if (set == NULL_RTX) @@ -1442,24 +1542,21 @@ setup_allocno_cover_class_and_costs (void) int i, j, n, regno, num; int *reg_costs; enum reg_class cover_class, rclass; - enum machine_mode mode; - HARD_REG_SET *pref; ira_allocno_t a; ira_allocno_iterator ai; + ira_assert (allocno_p); FOR_EACH_ALLOCNO (a, ai) { i = ALLOCNO_NUM (a); - mode = ALLOCNO_MODE (a); - cover_class = common_classes[ALLOCNO_REGNO (a)]; - ira_assert (allocno_pref[i] == NO_REGS || cover_class != NO_REGS); - ALLOCNO_MEMORY_COST (a) = COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost; + cover_class = regno_cover_class[ALLOCNO_REGNO (a)]; + ira_assert (pref[i] == NO_REGS || cover_class != NO_REGS); + ALLOCNO_MEMORY_COST (a) = COSTS (costs, i)->mem_cost; ira_set_allocno_cover_class (a, cover_class); if (cover_class == NO_REGS) continue; ALLOCNO_AVAILABLE_REGS_NUM (a) = ira_available_class_regs[cover_class]; - pref = ®_class_contents[allocno_pref[i]]; - if (optimize && ALLOCNO_COVER_CLASS (a) != allocno_pref[i]) + if (optimize && ALLOCNO_COVER_CLASS (a) != pref[i]) { n = ira_class_hard_regs_num[cover_class]; ALLOCNO_HARD_REG_COSTS (a) @@ -1467,7 +1564,7 @@ setup_allocno_cover_class_and_costs (void) for (j = n - 1; j >= 0; j--) { regno = ira_class_hard_regs[cover_class][j]; - if (TEST_HARD_REG_BIT (*pref, regno)) + if (TEST_HARD_REG_BIT (reg_class_contents[pref[i]], regno)) reg_costs[j] = ALLOCNO_COVER_CLASS_COST (a); else { @@ -1482,7 +1579,7 @@ setup_allocno_cover_class_and_costs (void) == cover_class); num = cost_class_nums[cover_class]; } - reg_costs[j] = COSTS_OF_ALLOCNO (allocno_costs, i)->cost[num]; + reg_costs[j] = COSTS (costs, i)->cost[num]; } } } @@ -1569,27 +1666,59 @@ ira_finish_costs_once (void) +/* Common initialization function for ira_costs and + ira_set_pseudo_classes. */ +static void +init_costs (void) +{ + init_subregs_of_mode (); + costs = (struct costs *) ira_allocate (max_struct_costs_size + * cost_elements_num); + pref_buffer + = (enum reg_class *) ira_allocate (sizeof (enum reg_class) + * cost_elements_num); + regno_cover_class + = (enum reg_class *) ira_allocate (sizeof (enum reg_class) + * max_reg_num ()); +} + +/* Common finalization function for ira_costs and + ira_set_pseudo_classes. */ +static void +finish_costs (void) +{ + ira_free (regno_cover_class); + ira_free (pref_buffer); + ira_free (costs); +} + /* Entry function which defines cover class, memory and hard register costs for each allocno. */ void ira_costs (void) { - allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size - * ira_allocnos_num); - total_costs = (struct costs *) ira_allocate (max_struct_costs_size - * ira_allocnos_num); - allocno_pref_buffer - = (enum reg_class *) ira_allocate (sizeof (enum reg_class) - * ira_allocnos_num); - common_classes - = (enum reg_class *) ira_allocate (sizeof (enum reg_class) - * max_reg_num ()); - find_allocno_class_costs (); + allocno_p = true; + cost_elements_num = ira_allocnos_num; + init_costs (); + total_allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size + * ira_allocnos_num); + find_costs_and_classes (ira_dump_file); setup_allocno_cover_class_and_costs (); - ira_free (common_classes); - ira_free (allocno_pref_buffer); - ira_free (total_costs); - ira_free (allocno_costs); + finish_costs (); + ira_free (total_allocno_costs); +} + +/* Entry function which defines classes for pseudos. */ +void +ira_set_pseudo_classes (FILE *dump_file) +{ + allocno_p = false; + internal_flag_ira_verbose = flag_ira_verbose; + cost_elements_num = max_reg_num (); + init_costs (); + find_costs_and_classes (dump_file); + pseudo_classes_defined_p = true; + finish_costs (); } @@ -1644,5 +1773,32 @@ ira_tune_allocno_costs_and_cover_classes (void) } if (min_cost != INT_MAX) ALLOCNO_COVER_CLASS_COST (a) = min_cost; + + /* Some targets allow pseudos to be allocated to unaligned + sequences of hard registers. However, selecting an unaligned + sequence can unnecessarily restrict later allocations. So + increase the cost of unaligned hard regs to encourage the use + of aligned hard regs. */ + { + int nregs, index; + + if ((nregs = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]) > 1) + { + ira_allocate_and_set_costs + (&ALLOCNO_HARD_REG_COSTS (a), cover_class, + ALLOCNO_COVER_CLASS_COST (a)); + reg_costs = ALLOCNO_HARD_REG_COSTS (a); + for (j = n - 1; j >= 0; j--) + { + if (j % nregs != 0) + { + regno = ira_non_ordered_class_hard_regs[cover_class][j]; + index = ira_class_hard_reg_index[cover_class][regno]; + ira_assert (index != -1); + reg_costs[index] += ALLOCNO_FREQ (a); + } + } + } + } } }