/* IRA hard register and memory cost calculation for allocnos or pseudos.
- Copyright (C) 2006-2018 Free Software Foundation, Inc.
+ Copyright (C) 2006-2020 Free Software Foundation, Inc.
Contributed by Vladimir Makarov <vmakarov@redhat.com>.
This file is part of GCC.
allocated. */
static cost_classes_t
restrict_cost_classes (cost_classes_t full, machine_mode mode,
- const HARD_REG_SET ®s)
+ const_hard_reg_set regs)
{
static struct cost_classes narrow;
int map[N_REG_CLASSES];
/* Calculate the set of registers in CL that belong to REGS and
are valid for MODE. */
- HARD_REG_SET valid_for_cl;
- COPY_HARD_REG_SET (valid_for_cl, reg_class_contents[cl]);
- AND_HARD_REG_SET (valid_for_cl, regs);
- AND_COMPL_HARD_REG_SET (valid_for_cl,
- ira_prohibited_class_mode_regs[cl][mode]);
- AND_COMPL_HARD_REG_SET (valid_for_cl, ira_no_alloc_regs);
+ HARD_REG_SET valid_for_cl = reg_class_contents[cl] & regs;
+ valid_for_cl &= ~(ira_prohibited_class_mode_regs[cl][mode]
+ | ira_no_alloc_regs);
if (hard_reg_set_empty_p (valid_for_cl))
continue;
if ((classes_ptr = cost_classes_aclass_cache[aclass]) == NULL)
{
- COPY_HARD_REG_SET (temp, reg_class_contents[aclass]);
- AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
+ temp = reg_class_contents[aclass] & ~ira_no_alloc_regs;
/* We exclude classes from consideration which are subsets of
ACLASS only if ACLASS is an uniform class. */
exclude_p = ira_uniform_class_p[aclass];
{
/* Exclude non-uniform classes which are subsets of
ACLASS. */
- COPY_HARD_REG_SET (temp2, reg_class_contents[cl]);
- AND_COMPL_HARD_REG_SET (temp2, ira_no_alloc_regs);
+ temp2 = reg_class_contents[cl] & ~ira_no_alloc_regs;
if (hard_reg_set_subset_p (temp2, temp) && cl != aclass)
continue;
}
/* Setup cost classes for pseudo REGNO with MODE. Usage of MODE can
decrease number of cost classes for the pseudo, if hard registers
- of some important classes can not hold a value of MODE. So the
- pseudo can not get hard register of some important classes and cost
+ of some important classes cannot hold a value of MODE. So the
+ pseudo cannot get hard register of some important classes and cost
calculation for such important classes is only wasting CPU
time. */
static void
machine_mode mode = GET_MODE (SET_SRC (set));
cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
enum reg_class *cost_classes = cost_classes_ptr->classes;
- reg_class_t rclass, hard_reg_class, pref_class;
+ reg_class_t rclass, hard_reg_class, pref_class, bigger_hard_reg_class;
int cost, k;
+ move_table *move_costs;
bool dead_p = find_regno_note (insn, REG_DEAD, REGNO (src));
+ ira_init_register_move_cost_if_necessary (mode);
+ move_costs = ira_register_move_cost[mode];
hard_reg_class = REGNO_REG_CLASS (other_regno);
+ bigger_hard_reg_class = ira_pressure_class_translate[hard_reg_class];
+ /* Target code may return any cost for mode which does not
+ fit the hard reg class (e.g. DImode for AREG on
+ i386). Check this and use a bigger class to get the
+ right cost. */
+ if (bigger_hard_reg_class != NO_REGS
+ && ! ira_hard_reg_in_set_p (other_regno, mode,
+ reg_class_contents[hard_reg_class]))
+ hard_reg_class = bigger_hard_reg_class;
i = regno == (int) REGNO (src) ? 1 : 0;
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
{
rclass = cost_classes[k];
- cost = ((i == 0
- ? ira_register_move_cost[mode][hard_reg_class][rclass]
- : ira_register_move_cost[mode][rclass][hard_reg_class])
- * frequency);
- op_costs[i]->cost[k] = cost;
+ cost = (i == 0
+ ? move_costs[hard_reg_class][rclass]
+ : move_costs[rclass][hard_reg_class]);
+
+ op_costs[i]->cost[k] = cost * frequency;
/* If we have assigned a class to this allocno in our
first pass, add a cost to this alternative
corresponding to what we would add if this allocno
else if (ira_reg_class_intersect[pref_class][rclass]
== NO_REGS)
op_costs[i]->cost[k]
- += (ira_register_move_cost[mode][pref_class][rclass]
+ += (move_costs[pref_class][rclass]
* frequency);
}
/* If this insn is a single set copying operand 1 to
return insn;
}
- if (pat_code == CLOBBER_HIGH)
- {
- gcc_assert (REG_P (XEXP (PATTERN (insn), 0))
- && HARD_REGISTER_P (XEXP (PATTERN (insn), 0)));
- return insn;
- }
-
counted_mem = false;
set = single_set (insn);
extract_insn (insn);
/* Now add the cost for each operand to the total costs for its
allocno. */
for (i = 0; i < recog_data.n_operands; i++)
- if (REG_P (recog_data.operand[i])
- && REGNO (recog_data.operand[i]) >= FIRST_PSEUDO_REGISTER)
- {
- int regno = REGNO (recog_data.operand[i]);
- struct costs *p = COSTS (costs, COST_INDEX (regno));
- struct costs *q = op_costs[i];
- int *p_costs = p->cost, *q_costs = q->cost;
- cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
- int add_cost;
-
- /* If the already accounted for the memory "cost" above, don't
- do so again. */
- if (!counted_mem)
- {
- add_cost = q->mem_cost;
- if (add_cost > 0 && INT_MAX - add_cost < p->mem_cost)
- p->mem_cost = INT_MAX;
- else
- p->mem_cost += add_cost;
- }
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
- {
- add_cost = q_costs[k];
- if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
- p_costs[k] = INT_MAX;
- else
- p_costs[k] += add_cost;
- }
- }
-
+ {
+ rtx op = recog_data.operand[i];
+
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ if (REG_P (op) && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+ {
+ int regno = REGNO (op);
+ struct costs *p = COSTS (costs, COST_INDEX (regno));
+ struct costs *q = op_costs[i];
+ int *p_costs = p->cost, *q_costs = q->cost;
+ cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
+ int add_cost;
+
+ /* If the already accounted for the memory "cost" above, don't
+ do so again. */
+ if (!counted_mem)
+ {
+ add_cost = q->mem_cost;
+ if (add_cost > 0 && INT_MAX - add_cost < p->mem_cost)
+ p->mem_cost = INT_MAX;
+ else
+ p->mem_cost += add_cost;
+ }
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ add_cost = q_costs[k];
+ if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
+ p_costs[k] = INT_MAX;
+ else
+ p_costs[k] += add_cost;
+ }
+ }
+ }
return insn;
}
}
else
continue;
+ if (reg_class_size[(int) REGNO_REG_CLASS (hard_regno)]
+ == (ira_reg_class_max_nregs
+ [REGNO_REG_CLASS (hard_regno)][(int) ALLOCNO_MODE(a)]))
+ /* If the class can provide only one hard reg to the allocno,
+ we processed the insn record_operand_costs already and we
+ actually updated the hard reg cost there. */
+ continue;
rclass = ALLOCNO_CLASS (a);
if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], hard_regno))
continue;
ira_allocno_object_iterator oi;
ira_object_t obj;
bool skip_p;
- HARD_REG_SET *crossed_calls_clobber_regs;
FOR_EACH_ALLOCNO (a, ai)
{
continue;
rclass = REGNO_REG_CLASS (regno);
cost = 0;
- crossed_calls_clobber_regs
- = &(ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
- if (ira_hard_reg_set_intersection_p (regno, mode,
- *crossed_calls_clobber_regs)
- && (ira_hard_reg_set_intersection_p (regno, mode,
- call_used_reg_set)
- || targetm.hard_regno_call_part_clobbered (regno,
- mode)))
+ if (ira_need_caller_save_p (a, regno))
cost += (ALLOCNO_CALL_FREQ (a)
* (ira_memory_move_cost[mode][rclass][0]
+ ira_memory_move_cost[mode][rclass][1]));