-fuse-caller-save - Use collected register usage information
2014-05-28 Radovan Obradovic <robradovic@mips.com> Tom de Vries <tom@codesourcery.com> * df-scan.c (df_get_call_refs): Use get_call_reg_set_usage. * caller-save.c (setup_save_areas, save_call_clobbered_regs): Use get_call_reg_set_usage. * resource.c (mark_set_resources, mark_target_live_regs): Use get_call_reg_set_usage. * ira-int.h (struct ira_allocno): Add crossed_calls_clobbered_regs field. (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS): Define. * ira-lives.c (process_bb_node_lives): Use get_call_reg_set_usage. Calculate ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS. * ira-build.c (ira_create_allocno): Init ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS. (create_cap_allocno, propagate_allocno_info) (propagate_some_info_from_allocno) (copy_info_to_removed_store_destinations): Handle ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS. * ira-costs.c (ira_tune_allocno_costs): Use ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS to adjust costs. Co-Authored-By: Tom de Vries <tom@codesourcery.com> From-SVN: r211007
This commit is contained in:
parent
27c07cc5d0
commit
c2ba7e7a62
@ -1,3 +1,25 @@
|
||||
2014-05-28 Radovan Obradovic <robradovic@mips.com>
|
||||
Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
* df-scan.c (df_get_call_refs): Use get_call_reg_set_usage.
|
||||
* caller-save.c (setup_save_areas, save_call_clobbered_regs): Use
|
||||
get_call_reg_set_usage.
|
||||
* resource.c (mark_set_resources, mark_target_live_regs): Use
|
||||
get_call_reg_set_usage.
|
||||
* ira-int.h (struct ira_allocno): Add crossed_calls_clobbered_regs
|
||||
field.
|
||||
(ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS): Define.
|
||||
* ira-lives.c (process_bb_node_lives): Use get_call_reg_set_usage.
|
||||
Calculate ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS.
|
||||
* ira-build.c (ira_create_allocno): Init
|
||||
ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS.
|
||||
(create_cap_allocno, propagate_allocno_info)
|
||||
(propagate_some_info_from_allocno)
|
||||
(copy_info_to_removed_store_destinations): Handle
|
||||
ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS.
|
||||
* ira-costs.c (ira_tune_allocno_costs): Use
|
||||
ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS to adjust costs.
|
||||
|
||||
2014-05-28 Radovan Obradovic <robradovic@mips.com>
|
||||
Tom de Vries <tom@codesourcery.com>
|
||||
|
||||
|
@ -441,7 +441,7 @@ setup_save_areas (void)
|
||||
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
|
||||
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
|
||||
&chain->live_throughout);
|
||||
COPY_HARD_REG_SET (used_regs, call_used_reg_set);
|
||||
get_call_reg_set_usage (insn, &used_regs, call_used_reg_set);
|
||||
|
||||
/* Record all registers set in this call insn. These don't
|
||||
need to be saved. N.B. the call insn might set a subreg
|
||||
@ -525,7 +525,7 @@ setup_save_areas (void)
|
||||
|
||||
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
|
||||
&chain->live_throughout);
|
||||
COPY_HARD_REG_SET (used_regs, call_used_reg_set);
|
||||
get_call_reg_set_usage (insn, &used_regs, call_used_reg_set);
|
||||
|
||||
/* Record all registers set in this call insn. These don't
|
||||
need to be saved. N.B. the call insn might set a subreg
|
||||
@ -804,6 +804,7 @@ save_call_clobbered_regs (void)
|
||||
{
|
||||
unsigned regno;
|
||||
HARD_REG_SET hard_regs_to_save;
|
||||
HARD_REG_SET call_def_reg_set;
|
||||
reg_set_iterator rsi;
|
||||
rtx cheap;
|
||||
|
||||
@ -854,7 +855,9 @@ save_call_clobbered_regs (void)
|
||||
AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set);
|
||||
AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets);
|
||||
AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved);
|
||||
AND_HARD_REG_SET (hard_regs_to_save, call_used_reg_set);
|
||||
get_call_reg_set_usage (insn, &call_def_reg_set,
|
||||
call_used_reg_set);
|
||||
AND_HARD_REG_SET (hard_regs_to_save, call_def_reg_set);
|
||||
|
||||
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
|
||||
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
|
||||
|
@ -3385,10 +3385,13 @@ df_get_call_refs (struct df_collection_rec *collection_rec,
|
||||
bool is_sibling_call;
|
||||
unsigned int i;
|
||||
HARD_REG_SET defs_generated;
|
||||
HARD_REG_SET fn_reg_set_usage;
|
||||
|
||||
CLEAR_HARD_REG_SET (defs_generated);
|
||||
df_find_hard_reg_defs (PATTERN (insn_info->insn), &defs_generated);
|
||||
is_sibling_call = SIBLING_CALL_P (insn_info->insn);
|
||||
get_call_reg_set_usage (insn_info->insn, &fn_reg_set_usage,
|
||||
regs_invalidated_by_call);
|
||||
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
{
|
||||
@ -3412,7 +3415,7 @@ df_get_call_refs (struct df_collection_rec *collection_rec,
|
||||
NULL, bb, insn_info, DF_REF_REG_DEF, flags);
|
||||
}
|
||||
}
|
||||
else if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
|
||||
else if (TEST_HARD_REG_BIT (fn_reg_set_usage, i)
|
||||
/* no clobbers for regs that are the result of the call */
|
||||
&& !TEST_HARD_REG_BIT (defs_generated, i)
|
||||
&& (!is_sibling_call
|
||||
|
@ -4781,9 +4781,6 @@ collect_fn_hard_reg_usage (void)
|
||||
|
||||
/* Be conservative - mark fixed and global registers as used. */
|
||||
IOR_HARD_REG_SET (node->function_used_regs, fixed_reg_set);
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (global_regs[i])
|
||||
SET_HARD_REG_BIT (node->function_used_regs, i);
|
||||
|
||||
#ifdef STACK_REGS
|
||||
/* Handle STACK_REGS conservatively, since the df-framework does not
|
||||
|
@ -515,6 +515,7 @@ ira_create_allocno (int regno, bool cap_p,
|
||||
ALLOCNO_CALL_FREQ (a) = 0;
|
||||
ALLOCNO_CALLS_CROSSED_NUM (a) = 0;
|
||||
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a) = 0;
|
||||
CLEAR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
|
||||
#ifdef STACK_REGS
|
||||
ALLOCNO_NO_STACK_REG_P (a) = false;
|
||||
ALLOCNO_TOTAL_NO_STACK_REG_P (a) = false;
|
||||
@ -913,6 +914,8 @@ create_cap_allocno (ira_allocno_t a)
|
||||
|
||||
ALLOCNO_CALLS_CROSSED_NUM (cap) = ALLOCNO_CALLS_CROSSED_NUM (a);
|
||||
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (cap) = ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a);
|
||||
IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (cap),
|
||||
ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
|
||||
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
|
||||
{
|
||||
fprintf (ira_dump_file, " Creating cap ");
|
||||
@ -2048,6 +2051,8 @@ propagate_allocno_info (void)
|
||||
+= ALLOCNO_CALLS_CROSSED_NUM (a);
|
||||
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (parent_a)
|
||||
+= ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a);
|
||||
IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (parent_a),
|
||||
ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
|
||||
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
|
||||
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
|
||||
aclass = ALLOCNO_CLASS (a);
|
||||
@ -2428,6 +2433,9 @@ propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
|
||||
ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a);
|
||||
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a)
|
||||
+= ALLOCNO_CHEAP_CALLS_CROSSED_NUM (from_a);
|
||||
IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a),
|
||||
ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (from_a));
|
||||
|
||||
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
|
||||
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
|
||||
if (! ALLOCNO_BAD_SPILL_P (from_a))
|
||||
@ -3059,6 +3067,8 @@ copy_info_to_removed_store_destinations (int regno)
|
||||
+= ALLOCNO_CALLS_CROSSED_NUM (a);
|
||||
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (parent_a)
|
||||
+= ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a);
|
||||
IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (parent_a),
|
||||
ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
|
||||
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
|
||||
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
|
||||
merged_p = true;
|
||||
|
@ -2238,6 +2238,7 @@ ira_tune_allocno_costs (void)
|
||||
ira_allocno_object_iterator oi;
|
||||
ira_object_t obj;
|
||||
bool skip_p;
|
||||
HARD_REG_SET *crossed_calls_clobber_regs;
|
||||
|
||||
FOR_EACH_ALLOCNO (a, ai)
|
||||
{
|
||||
@ -2272,17 +2273,24 @@ ira_tune_allocno_costs (void)
|
||||
continue;
|
||||
rclass = REGNO_REG_CLASS (regno);
|
||||
cost = 0;
|
||||
if (ira_hard_reg_set_intersection_p (regno, mode, call_used_reg_set)
|
||||
|| HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
|
||||
cost += (ALLOCNO_CALL_FREQ (a)
|
||||
* (ira_memory_move_cost[mode][rclass][0]
|
||||
+ ira_memory_move_cost[mode][rclass][1]));
|
||||
crossed_calls_clobber_regs
|
||||
= &(ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a));
|
||||
if (ira_hard_reg_set_intersection_p (regno, mode,
|
||||
*crossed_calls_clobber_regs))
|
||||
{
|
||||
if (ira_hard_reg_set_intersection_p (regno, mode,
|
||||
call_used_reg_set)
|
||||
|| HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
|
||||
cost += (ALLOCNO_CALL_FREQ (a)
|
||||
* (ira_memory_move_cost[mode][rclass][0]
|
||||
+ ira_memory_move_cost[mode][rclass][1]));
|
||||
#ifdef IRA_HARD_REGNO_ADD_COST_MULTIPLIER
|
||||
cost += ((ira_memory_move_cost[mode][rclass][0]
|
||||
+ ira_memory_move_cost[mode][rclass][1])
|
||||
* ALLOCNO_FREQ (a)
|
||||
* IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2);
|
||||
cost += ((ira_memory_move_cost[mode][rclass][0]
|
||||
+ ira_memory_move_cost[mode][rclass][1])
|
||||
* ALLOCNO_FREQ (a)
|
||||
* IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2);
|
||||
#endif
|
||||
}
|
||||
if (INT_MAX - cost < reg_costs[j])
|
||||
reg_costs[j] = INT_MAX;
|
||||
else
|
||||
|
@ -374,6 +374,8 @@ struct ira_allocno
|
||||
/* The number of calls across which it is live, but which should not
|
||||
affect register preferences. */
|
||||
int cheap_calls_crossed_num;
|
||||
/* Registers clobbered by intersected calls. */
|
||||
HARD_REG_SET crossed_calls_clobbered_regs;
|
||||
/* Array of usage costs (accumulated and the one updated during
|
||||
coloring) for each hard register of the allocno class. The
|
||||
member value can be NULL if all costs are the same and equal to
|
||||
@ -417,6 +419,8 @@ struct ira_allocno
|
||||
#define ALLOCNO_CALL_FREQ(A) ((A)->call_freq)
|
||||
#define ALLOCNO_CALLS_CROSSED_NUM(A) ((A)->calls_crossed_num)
|
||||
#define ALLOCNO_CHEAP_CALLS_CROSSED_NUM(A) ((A)->cheap_calls_crossed_num)
|
||||
#define ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS(A) \
|
||||
((A)->crossed_calls_clobbered_regs)
|
||||
#define ALLOCNO_MEM_OPTIMIZED_DEST(A) ((A)->mem_optimized_dest)
|
||||
#define ALLOCNO_MEM_OPTIMIZED_DEST_P(A) ((A)->mem_optimized_dest_p)
|
||||
#define ALLOCNO_SOMEWHERE_RENAMED_P(A) ((A)->somewhere_renamed_p)
|
||||
|
@ -1263,6 +1263,10 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
|
||||
ira_object_t obj = ira_object_id_map[i];
|
||||
ira_allocno_t a = OBJECT_ALLOCNO (obj);
|
||||
int num = ALLOCNO_NUM (a);
|
||||
HARD_REG_SET this_call_used_reg_set;
|
||||
|
||||
get_call_reg_set_usage (insn, &this_call_used_reg_set,
|
||||
call_used_reg_set);
|
||||
|
||||
/* Don't allocate allocnos that cross setjmps or any
|
||||
call, if this function receives a nonlocal
|
||||
@ -1277,9 +1281,9 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
|
||||
if (can_throw_internal (insn))
|
||||
{
|
||||
IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
|
||||
call_used_reg_set);
|
||||
this_call_used_reg_set);
|
||||
IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
|
||||
call_used_reg_set);
|
||||
this_call_used_reg_set);
|
||||
}
|
||||
|
||||
if (sparseset_bit_p (allocnos_processed, num))
|
||||
@ -1296,6 +1300,8 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
|
||||
/* Mark it as saved at the next call. */
|
||||
allocno_saved_at_call[num] = last_call_num + 1;
|
||||
ALLOCNO_CALLS_CROSSED_NUM (a)++;
|
||||
IOR_HARD_REG_SET (ALLOCNO_CROSSED_CALLS_CLOBBERED_REGS (a),
|
||||
this_call_used_reg_set);
|
||||
if (cheap_reg != NULL_RTX
|
||||
&& ALLOCNO_REGNO (a) == (int) REGNO (cheap_reg))
|
||||
ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a)++;
|
||||
|
@ -655,10 +655,12 @@ mark_set_resources (rtx x, struct resources *res, int in_dest,
|
||||
if (mark_type == MARK_SRC_DEST_CALL)
|
||||
{
|
||||
rtx link;
|
||||
HARD_REG_SET regs;
|
||||
|
||||
res->cc = res->memory = 1;
|
||||
|
||||
IOR_HARD_REG_SET (res->regs, regs_invalidated_by_call);
|
||||
get_call_reg_set_usage (x, ®s, regs_invalidated_by_call);
|
||||
IOR_HARD_REG_SET (res->regs, regs);
|
||||
|
||||
for (link = CALL_INSN_FUNCTION_USAGE (x);
|
||||
link; link = XEXP (link, 1))
|
||||
@ -1011,11 +1013,15 @@ mark_target_live_regs (rtx insns, rtx target, struct resources *res)
|
||||
predicated instruction, or if the CALL is NORETURN. */
|
||||
if (GET_CODE (PATTERN (real_insn)) != COND_EXEC)
|
||||
{
|
||||
HARD_REG_SET regs_invalidated_by_this_call;
|
||||
get_call_reg_set_usage (real_insn,
|
||||
®s_invalidated_by_this_call,
|
||||
regs_invalidated_by_call);
|
||||
/* CALL clobbers all call-used regs that aren't fixed except
|
||||
sp, ap, and fp. Do this before setting the result of the
|
||||
call live. */
|
||||
AND_COMPL_HARD_REG_SET (current_live_regs,
|
||||
regs_invalidated_by_call);
|
||||
regs_invalidated_by_this_call);
|
||||
}
|
||||
|
||||
/* A CALL_INSN sets any global register live, since it may
|
||||
|
Loading…
Reference in New Issue
Block a user