Mercurial > hg > CbC > CbC_gcc
diff gcc/ira-costs.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children |
line wrap: on
line diff
--- a/gcc/ira-costs.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/ira-costs.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* 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. @@ -237,7 +237,7 @@ 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]; @@ -254,12 +254,9 @@ /* 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; @@ -343,8 +340,7 @@ 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]; @@ -356,8 +352,7 @@ { /* 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; } @@ -389,8 +384,8 @@ /* 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 @@ -1257,7 +1252,7 @@ add_cost = (move_in_cost[i][rclass] * scale) / 2; if (INT_MAX - add_cost < pp_costs[k]) pp_costs[k] = INT_MAX; - else + else pp_costs[k] += add_cost; } } @@ -1283,10 +1278,112 @@ { const char *constraints[MAX_RECOG_OPERANDS]; machine_mode modes[MAX_RECOG_OPERANDS]; - rtx ops[MAX_RECOG_OPERANDS]; rtx set; int i; + if ((set = single_set (insn)) != NULL_RTX + /* In rare cases the single set insn might have less 2 operands + as the source can be a fixed special reg. */ + && recog_data.n_operands > 1 + && recog_data.operand[0] == SET_DEST (set) + && recog_data.operand[1] == SET_SRC (set)) + { + int regno, other_regno; + rtx dest = SET_DEST (set); + rtx src = SET_SRC (set); + + if (GET_CODE (dest) == SUBREG + && known_eq (GET_MODE_SIZE (GET_MODE (dest)), + GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))) + dest = SUBREG_REG (dest); + if (GET_CODE (src) == SUBREG + && known_eq (GET_MODE_SIZE (GET_MODE (src)), + GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))) + src = SUBREG_REG (src); + if (REG_P (src) && REG_P (dest) + && (((regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER + && (other_regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER) + || ((regno = REGNO (dest)) >= FIRST_PSEUDO_REGISTER + && (other_regno = REGNO (src)) < FIRST_PSEUDO_REGISTER))) + { + 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, 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 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 + ? 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 + were not in the appropriate class. */ + if (pref) + { + if ((pref_class = pref[COST_INDEX (regno)]) == NO_REGS) + op_costs[i]->cost[k] + += ((i == 0 ? ira_memory_move_cost[mode][rclass][0] : 0) + + (i == 1 ? ira_memory_move_cost[mode][rclass][1] : 0) + * frequency); + else if (ira_reg_class_intersect[pref_class][rclass] + == NO_REGS) + op_costs[i]->cost[k] + += (move_costs[pref_class][rclass] + * frequency); + } + /* 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 that prefers a hard + register that is in its own register class then we + may want to adjust the cost of that register class to + -1. + + Avoid the adjustment if the source does not die to + avoid stressing of register allocator by preferencing + two colliding registers into single class. */ + if (dead_p + && TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno) + && (reg_class_size[(int) rclass] + == (ira_reg_class_max_nregs + [(int) rclass][(int) GET_MODE(src)]))) + { + if (reg_class_size[rclass] == 1) + op_costs[i]->cost[k] = -frequency; + else if (in_hard_reg_set_p (reg_class_contents[rclass], + GET_MODE(src), other_regno)) + op_costs[i]->cost[k] = -frequency; + } + } + op_costs[i]->mem_cost + = ira_memory_move_cost[mode][hard_reg_class][i] * frequency; + if (pref && (pref_class = pref[COST_INDEX (regno)]) != NO_REGS) + op_costs[i]->mem_cost + += ira_memory_move_cost[mode][pref_class][i] * frequency; + return; + } + } + for (i = 0; i < recog_data.n_operands; i++) { constraints[i] = recog_data.constraints[i]; @@ -1302,7 +1399,6 @@ { memcpy (op_costs[i], init_cost, struct_costs_size); - ops[i] = recog_data.operand[i]; if (GET_CODE (recog_data.operand[i]) == SUBREG) recog_data.operand[i] = SUBREG_REG (recog_data.operand[i]); @@ -1318,7 +1414,7 @@ recog_data.operand[i], 0, ADDRESS, SCRATCH, frequency * 2); } - + /* Check for commutative in a separate loop so everything will have been initialized. We must do this even if one operand is a constant--see addsi3 in m68k.md. */ @@ -1328,8 +1424,8 @@ const char *xconstraints[MAX_RECOG_OPERANDS]; int j; - /* Handle commutative operands by swapping the constraints. - We assume the modes are the same. */ + /* Handle commutative operands by swapping the + constraints. We assume the modes are the same. */ for (j = 0; j < recog_data.n_operands; j++) xconstraints[j] = constraints[j]; @@ -1342,69 +1438,6 @@ record_reg_classes (recog_data.n_alternatives, recog_data.n_operands, recog_data.operand, modes, constraints, insn, pref); - - /* 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 - that prefers a hard register that is in its own register class - then we may want to adjust the cost of that register class to -1. - - Avoid the adjustment if the source does not die to avoid - stressing of register allocator by preferencing two colliding - registers into single class. - - Also avoid the adjustment if a copy between hard registers of the - class is expensive (ten times the cost of a default copy is - considered arbitrarily expensive). This avoids losing when the - preferred class is very expensive as the source of a copy - instruction. */ - if ((set = single_set (insn)) != NULL_RTX - /* In rare cases the single set insn might have less 2 operands - as the source can be a fixed special reg. */ - && recog_data.n_operands > 1 - && ops[0] == SET_DEST (set) && ops[1] == SET_SRC (set)) - { - int regno, other_regno; - rtx dest = SET_DEST (set); - rtx src = SET_SRC (set); - - if (GET_CODE (dest) == SUBREG - && known_eq (GET_MODE_SIZE (GET_MODE (dest)), - GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))) - dest = SUBREG_REG (dest); - if (GET_CODE (src) == SUBREG - && known_eq (GET_MODE_SIZE (GET_MODE (src)), - GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))) - src = SUBREG_REG (src); - if (REG_P (src) && REG_P (dest) - && find_regno_note (insn, REG_DEAD, REGNO (src)) - && (((regno = REGNO (src)) >= FIRST_PSEUDO_REGISTER - && (other_regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER) - || ((regno = REGNO (dest)) >= FIRST_PSEUDO_REGISTER - && (other_regno = REGNO (src)) < FIRST_PSEUDO_REGISTER))) - { - machine_mode mode = GET_MODE (src); - cost_classes_t cost_classes_ptr = regno_cost_classes[regno]; - enum reg_class *cost_classes = cost_classes_ptr->classes; - reg_class_t rclass; - int k; - - i = regno == (int) REGNO (src) ? 1 : 0; - for (k = cost_classes_ptr->num - 1; k >= 0; k--) - { - rclass = cost_classes[k]; - if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno) - && (reg_class_size[(int) rclass] - == ira_reg_class_max_nregs [(int) rclass][(int) mode])) - { - if (reg_class_size[rclass] == 1) - op_costs[i]->cost[k] = -frequency; - else if (in_hard_reg_set_p (reg_class_contents[rclass], - mode, other_regno)) - op_costs[i]->cost[k] = -frequency; - } - } - } - } } @@ -1444,20 +1477,13 @@ 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); /* If this insn loads a parameter from its stack slot, then it represents a savings, rather than a cost, if the parameter is - stored in memory. Record this fact. + stored in memory. Record this fact. Similarly if we're loading other constants from memory (constant pool, TOC references, small data areas, etc) and this is the only @@ -1468,7 +1494,7 @@ mem_cost might result in it being loaded using the specialized instruction into a register, then stored into stack and loaded again from the stack. See PR52208. - + Don't do this if SET_SRC (set) has side effect. See PR56124. */ if (set != 0 && REG_P (SET_DEST (set)) && MEM_P (SET_SRC (set)) && (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != NULL_RTX @@ -1501,36 +1527,40 @@ /* 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; } @@ -1766,7 +1796,7 @@ a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { int *a_costs, *p_costs; - + a_num = ALLOCNO_NUM (a); if ((flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED) @@ -1936,7 +1966,7 @@ int a_num = ALLOCNO_NUM (a); int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost; int *a_costs = COSTS (costs, a_num)->cost; - + if (aclass == NO_REGS) best = NO_REGS; else @@ -1998,7 +2028,7 @@ } } } - + if (internal_flag_ira_verbose > 4 && dump_file) { if (allocno_p) @@ -2065,6 +2095,13 @@ } 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; @@ -2081,7 +2118,7 @@ int cost; enum reg_class hard_reg_class; machine_mode mode; - + mode = ALLOCNO_MODE (a); hard_reg_class = REGNO_REG_CLASS (hard_regno); ira_init_register_move_cost_if_necessary (mode); @@ -2296,7 +2333,6 @@ ira_allocno_object_iterator oi; ira_object_t obj; bool skip_p; - HARD_REG_SET *crossed_calls_clobber_regs; FOR_EACH_ALLOCNO (a, ai) { @@ -2331,14 +2367,7 @@ 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]));