summaryrefslogtreecommitdiff
path: root/gcc/ira-costs.c
diff options
context:
space:
mode:
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-02 18:54:25 +0000
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2009-09-02 18:54:25 +0000
commita7dcf969769c6cd5f8dbe9f898d6f4ef74ed3605 (patch)
tree4fff239f690be40be173f6b04a6883338c271d49 /gcc/ira-costs.c
parent1b9055fcbf86cce61f62555fa731a1ab7552dc74 (diff)
downloadgcc-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.c476
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 = &reg_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 ();
}