| Index: gcc/gcc/ira-costs.c
|
| diff --git a/gcc/gcc/ira-costs.c b/gcc/gcc/ira-costs.c
|
| index 58700b75f14940d209fd4d4bcd8f1efd27ddb4d9..9e11219ce0104686d6bd9608be56c14118a18a0f 100644
|
| --- a/gcc/gcc/ira-costs.c
|
| +++ b/gcc/gcc/ira-costs.c
|
| @@ -1,5 +1,5 @@
|
| -/* IRA hard register and memory cost calculation for allocnos.
|
| - Copyright (C) 2006, 2007, 2008
|
| +/* 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;
|
| @@ -205,7 +220,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
| {
|
| enum reg_class classes[MAX_RECOG_OPERANDS];
|
| int allows_mem[MAX_RECOG_OPERANDS];
|
| - int rclass;
|
| + enum reg_class rclass;
|
| int alt_fail = 0;
|
| int alt_cost = 0, op_cost_add;
|
|
|
| @@ -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
|
| @@ -355,7 +367,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
|
| @@ -429,7 +441,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
| break;
|
|
|
| case 's':
|
| - if (GET_CODE (op) == CONST_INT
|
| + if (CONST_INT_P (op)
|
| || (GET_CODE (op) == CONST_DOUBLE
|
| && GET_MODE (op) == VOIDmode))
|
| break;
|
| @@ -441,7 +453,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
| break;
|
|
|
| case 'n':
|
| - if (GET_CODE (op) == CONST_INT
|
| + if (CONST_INT_P (op)
|
| || (GET_CODE (op) == CONST_DOUBLE
|
| && GET_MODE (op) == VOIDmode))
|
| win = 1;
|
| @@ -455,7 +467,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
| case 'N':
|
| case 'O':
|
| case 'P':
|
| - if (GET_CODE (op) == CONST_INT
|
| + if (CONST_INT_P (op)
|
| && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), c, p))
|
| win = 1;
|
| break;
|
| @@ -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
|
| @@ -672,7 +682,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
| {
|
| unsigned int regno = REGNO (ops[!i]);
|
| enum machine_mode mode = GET_MODE (ops[!i]);
|
| - int rclass;
|
| + enum reg_class rclass;
|
| unsigned int nr;
|
|
|
| if (regno < FIRST_PSEUDO_REGISTER)
|
| @@ -693,7 +703,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 +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;
|
| @@ -886,15 +895,15 @@ record_address_regs (enum machine_mode mode, rtx x, int context,
|
| case REG:
|
| {
|
| struct costs *pp;
|
| - int i, k;
|
| + enum reg_class i;
|
| + int k;
|
|
|
| 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++)
|
| {
|
| @@ -921,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];
|
| @@ -975,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);
|
| }
|
|
|
|
|
| @@ -994,7 +1002,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));
|
| @@ -1014,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. */
|
| @@ -1033,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;
|
| @@ -1050,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)
|
| {
|
| @@ -1084,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;
|
| @@ -1112,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. */
|
| @@ -1153,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. */
|
| @@ -1181,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;
|
| @@ -1251,38 +1337,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;
|
| @@ -1291,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
|
| @@ -1306,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
|
| @@ -1383,7 +1476,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)
|
| @@ -1441,24 +1534,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)
|
| @@ -1466,7 +1556,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
|
| {
|
| @@ -1481,7 +1571,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];
|
| }
|
| }
|
| }
|
| @@ -1568,27 +1658,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 ();
|
| }
|
|
|
|
|
|
|