aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRadovan Obradovic <robradovic@mips.com>2014-05-28 09:43:21 +0000
committerTom de Vries <vries@gcc.gnu.org>2014-05-28 09:43:21 +0000
commitc2ba7e7a62c63106e1e811d31b27df26bdae0169 (patch)
tree3fd6226eae59256645e73f80df2f379d2a822117 /gcc
parent27c07cc5d06c0f74d147c14c6a4b0b071266e774 (diff)
downloadgcc-c2ba7e7a62c63106e1e811d31b27df26bdae0169.zip
gcc-c2ba7e7a62c63106e1e811d31b27df26bdae0169.tar.gz
gcc-c2ba7e7a62c63106e1e811d31b27df26bdae0169.tar.bz2
-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog22
-rw-r--r--gcc/caller-save.c9
-rw-r--r--gcc/df-scan.c5
-rw-r--r--gcc/final.c3
-rw-r--r--gcc/ira-build.c10
-rw-r--r--gcc/ira-costs.c26
-rw-r--r--gcc/ira-int.h4
-rw-r--r--gcc/ira-lives.c10
-rw-r--r--gcc/resource.c10
9 files changed, 79 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5264478..7e0f532 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,6 +1,28 @@
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>
+
* cgraph.h (struct cgraph_rtl_info): Add function_used_regs
and function_used_regs_valid fields.
* final.c: Move include of hard-reg-set.h to before rtl.h to declare
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 20421c9..64fd66c 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -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))
diff --git a/gcc/df-scan.c b/gcc/df-scan.c
index 0b5b437..992d0af 100644
--- a/gcc/df-scan.c
+++ b/gcc/df-scan.c
@@ -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
diff --git a/gcc/final.c b/gcc/final.c
index f75edd5..a345fe7 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -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
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 0396f37..000c25c 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -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;
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c
index 46c14ef..4ecf75f 100644
--- a/gcc/ira-costs.c
+++ b/gcc/ira-costs.c
@@ -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
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 19d8601..413c823 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -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)
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c
index ffbca389..0dccee3 100644
--- a/gcc/ira-lives.c
+++ b/gcc/ira-lives.c
@@ -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)++;
diff --git a/gcc/resource.c b/gcc/resource.c
index aed00ed..b555682 100644
--- a/gcc/resource.c
+++ b/gcc/resource.c
@@ -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, &regs, 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,
+ &regs_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