diff options
author | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-02 18:54:25 +0000 |
---|---|---|
committer | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-02 18:54:25 +0000 |
commit | a7dcf969769c6cd5f8dbe9f898d6f4ef74ed3605 (patch) | |
tree | 4fff239f690be40be173f6b04a6883338c271d49 /gcc/ira-costs.c | |
parent | 1b9055fcbf86cce61f62555fa731a1ab7552dc74 (diff) | |
download | gcc-a7dcf969769c6cd5f8dbe9f898d6f4ef74ed3605.tar.gz |
2009-09-02 Vladimir Makarov <vmakarov@redhat.com>
* doc/invoke.texi (-fsched-pressure): Document it.
(-fsched-reg-pressure-heuristic): Remove it.
* reload.c (ira.h): Include.
(find_reloads): Add choosing reload on number of small spilled
classes.
* haifa-sched.c (ira.h): Include.
(sched_pressure_p, sched_regno_cover_class, curr_reg_pressure,
saved_reg_pressure, curr_reg_live, saved_reg_live,
region_ref_regs): New variables.
(sched_init_region_reg_pressure_info, mark_regno_birth_or_death,
initiate_reg_pressure_info, setup_ref_regs,
initiate_bb_reg_pressure_info, save_reg_pressure,
restore_reg_pressure, dying_use_p, print_curr_reg_pressure): New
functions.
(setup_insn_reg_pressure_info): New function.
(rank_for_schedule): Add pressure checking and insn issue time.
Remove comparison of insn reg weights.
(ready_sort): Set insn reg pressure info.
(update_register_pressure, setup_insn_max_reg_pressure,
update_reg_and_insn_max_reg_pressure,
sched_setup_bb_reg_pressure_info): New functions.
(schedule_insn): Add code for printing and updating reg pressure
info.
(find_set_reg_weight, find_insn_reg_weight): Remove.
(ok_for_early_queue_removal): Do nothing if pressure_only_p.
(debug_ready_list): Print reg pressure info.
(schedule_block): Ditto. Check insn issue time.
(sched_init): Set up sched_pressure_p. Allocate and set up some
reg pressure related info.
(sched_finish): Free some reg pressure related info.
(fix_tick_ready): Make insn always ready if pressure_p.
(init_h_i_d): Don't call find_insn_reg_weight.
(haifa_finish_h_i_d): Free insn reg pressure info.
* ira-int.h (ira_hard_regno_cover_class, ira_reg_class_nregs,
ira_memory_move_cost, ira_class_hard_regs,
ira_class_hard_regs_num, ira_no_alloc_regs,
ira_available_class_regs, ira_reg_class_cover_size,
ira_reg_class_cover, ira_class_translate): Move to ira.h.
* ira-lives.c (single_reg_class): Check mode to find how many
registers are necessary for operand.
(ira_implicitly_set_insn_hard_regs): New.
* common.opt (fsched-pressure): New options.
(fsched-reg-pressure-heuristic): Remove.
* ira.c (setup_eliminable_regset): Rename to
ira_setup_eliminable_regset. Make it external.
(expand_reg_info): Pass cover class to setup_reg_classes.
(ira): Call resize_reg_info instead of allocate_reg_info.
* sched-deps.c: Include ira.h.
(implicit_reg_pending_clobbers, implicit_reg_pending_uses): New.
(create_insn_reg_use, create_insn_reg_set, setup_insn_reg_uses,
reg_pressure_info, insn_use_p, mark_insn_pseudo_birth,
mark_insn_hard_regno_birth, mark_insn_reg_birth,
mark_pseudo_death, mark_hard_regno_death, mark_reg_death,
mark_insn_reg_store, mark_insn_reg_clobber,
setup_insn_reg_pressure_info): New.
(sched_analyze_1): Update implicit_reg_pending_uses.
(sched_analyze_insn): Find implicit sets, uses, clobbers of regs.
Use them to create dependencies. Set insn reg uses and pressure
info. Process reg_pending_uses in one place.
(free_deps): Free implicit sets.
(remove_from_deps): Remove implicit sets if necessary. Check
implicit sets when clearing reg_last_in_use.
(init_deps_global): Clear implicit_reg_pending_clobbers and
implicit_reg_pending_uses.
* ira.h (ira_hard_regno_cover_class, ira_reg_class_nregs,
ira_memory_move_cost, ira_class_hard_regs,
ira_class_hard_regs_num, ira_no_alloc_regs,
ira_available_class_regs, ira_reg_class_cover_size,
ira_reg_class_cover, ira_class_translate): Move from ira-int.h.
(ira_setup_eliminable_regset, ira_set_pseudo_classes,
ira_implicitly_set_insn_hard_regs): New prototypes.
* ira-costs.c (pseudo_classes_defined_p, allocno_p,
cost_elements_num): New variables.
(allocno_costs, total_costs): Rename to costs and
total_allocno_costs.
(COSTS_OF_ALLOCNO): Rename to COSTS.
(allocno_pref): Rename to pref.
(allocno_pref_buffer): Rename to pref_buffer.
(common_classes): Rename to regno_cover_class.
(COST_INDEX): New.
(record_reg_classes): Set allocno attributes only if allocno_p.
(record_address_regs): Ditto. Use COST_INDEX instead of
ALLOCNO_NUM.
(scan_one_insn): Use COST_INDEX and COSTS instead of ALLOCNO_NUM
and COSTS_OF_ALLOCNO.
(print_costs): Rename to print_allocno_costs.
(print_pseudo_costs): New.
(process_bb_node_for_costs): Split into 2 functions with new
function process_bb_for_costs. Pass BB to process_bb_for_costs.
(find_allocno_class_costs): Rename to find_costs_and_classes. Add
new parameter dump_file. Use cost_elements_num instead of
ira_allocnos_num. Make one iteration if preferred classes were
already calculated for scheduler. Make 2 versions of code
depending on allocno_p.
(setup_allocno_cover_class_and_costs): Check allocno_p. Use
regno_cover_class and COSTS instead of common_classes and
COSTS_OF_ALLOCNO.
(init_costs, finish_costs): New.
(ira_costs): Set up allocno_p and cost_elements_num. Call
init_costs and finish_costs.
(ira_set_pseudo_classes): New.
* rtl.h (allocate_reg_info): Remove.
(resize_reg_info): Change return type.
(reg_cover_class): New.
(setup_reg_classes): Add new parameter.
* sched-int.h (struct deps_reg): New member implicit_sets.
(sched_pressure_p, sched_regno_cover_class): New external
definitions.
(INCREASE_BITS): New macro.
(struct reg_pressure_data, struct reg_use_data): New.
(struct _haifa_insn_data): Remove reg_weight. Add members
reg_pressure, reg_use_list, reg_set_list, and
reg_pressure_excess_cost_change.
(struct deps): New member implicit_sets.
(pressure_p): New variable.
(COVER_CLASS_BITS, INCREASE_BITS): New macros.
(struct reg_pressure_data, struct reg_use_data): New.
(INSN_REG_WEIGHT): Remove.
(INSN_REG_PRESSURE, INSN_MAX_REG_PRESSURE, INSN_REG_USE_LIST,
INSN_REG_SET_LIST, INSN_REG_PRESSURE_EXCESS_COST_CHANGE): New
macros.
(sched_init_region_reg_pressure_info,
sched_setup_bb_reg_pressure_info): New prototypes.
* reginfo.c (struct reg_pref): New member coverclass.
(reg_cover_class): New function.
(reginfo_init, pass_reginfo_init): Move after free_reg_info.
(reg_info_size): New variable.
(allocate_reg_info): Make static. Setup reg_info_size.
(resize_reg_info): Use reg_info_size. Return flag of resizing.
(setup_reg_classes): Add a new parameter. Setup cover class too.
* Makefile.in (reload.o, haifa-sched.o, sched-deps.o): Add ira.h to the
dependencies.
* sched-rgn.c (deps_join): Set up implicit_sets.
(schedule_region): Set up region and basic blocks pressure
relative info.
* passes.c (init_optimization_passes): Move
pass_subregs_of_mode_init before pass_sched.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151348 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ira-costs.c')
-rw-r--r-- | gcc/ira-costs.c | 476 |
1 files changed, 299 insertions, 177 deletions
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index bb51c55bc65..fd756f6de73 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 <vmakarov@redhat.com>. @@ -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) -/* Allocated buffers for allocno_pref. */ -static enum reg_class *allocno_pref_buffer; +/* 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; -/* Record register class of each allocno with the same regno. */ -static enum reg_class *common_classes; +/* Allocated buffers for pref. */ +static enum reg_class *pref_buffer; + +/* 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; @@ -320,12 +335,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 @@ -564,12 +576,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 +646,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 @@ -877,8 +887,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 +901,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 +930,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 +983,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); } @@ -1015,17 +1022,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 +1041,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 +1056,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 +1091,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 +1148,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 +1217,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 +1256,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,35 +1337,42 @@ 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 { @@ -1292,7 +1384,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 +1399,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 @@ -1443,23 +1535,22 @@ setup_allocno_cover_class_and_costs (void) 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 +1558,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 +1573,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 +1660,58 @@ ira_finish_costs_once (void) +/* Common initialization function for ira_costs and + ira_set_pseudo_classes. */ +static void +init_costs (void) +{ + 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 (); } |