aboutsummaryrefslogtreecommitdiff
path: root/gcc/caller-save.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2012-05-14 12:08:31 +0000
committerBernd Schmidt <bernds@codesourcery.com>2012-05-14 12:08:31 +0000
commit2e6ada14099c7c1bb04be11bd876dec80052a710 (patch)
treef9965bd4902a6a182ee0908a0ebd8e8bbd34a1cf /gcc/caller-save.c
parent926ac846146149b278986609b0c868212692fb2d (diff)
* attribs.c (decl_attributes): Avoid emitting a warning if
ATTR_FLAG_BUILT_IN. * doc/rtl.texi (CALL_INSN_FUNCTION_USAGE): Use lowercase for rtx codes. Document meaning of sets inside CALL_INSN_FUNCTION_USAGE. * c-family/c-common.c (DEF_ATTR_STRING): Define and undefine as necessary. * builtin-attrs.def (DEF_ATTR_FOR_STRING): Define. Use it to define a string "1". (ATTR_RET1_NOTHROW_NONNULL_LEAF): New attr definition. * builtins.def (BUILT_IN_MEMCPY, BUILT_IN_MEMMOVE, BUILT_IN_MEMSET, BUILT_IN_STRCPY): Use it for these functions. * postreload.c (reload_combine): Deal with SETs inside CALL_INSN_FUNCTION_USAGE. * caller-save.c (setup_save_areas, save_call_clobbered_regs): Look for REG_RETURNED notes and use a cheap restore if possible. * ira-int.h (struct ira_allocno): New member cheap_calls_crossed_num. (ALLOCNO_CHEAP_CALLS_CROSSED_NUM): New macro. * ira-build.c (ira_create_allocno, create_cap_allocno, propagate_allocno_info, propagate_some_info_from_allocno, copy_info_to_removed_store_destination, ira_flattening): Handle it. * ira-lives.c (pseudo_regno_single_word_and_live_p, find_call_crossed_cheap_reg): New static functions. (process_bb_node_lives): Look for SETs in CALL_INSN_FUNCTION_USAGE, and set ALLOCNO_CHEAP_CALLS_CROSSED_NUM if possible. Also make a REG_RETURNED note in that case. * ira.c (setup_reg_renumber): Change assert to allow cases where allocnos only cross calls for which they are cheap to restore. * ira-costs.c (ira_tune_allocno_costs): Compare ALLOCNO_CALLS_CROSSED_NUM to ALLOCNO_CHEAP_CALLS_CROSSED_NUM rather than 0. * reg-notes.def (REG_RETURNED): New note. * cse.c (cse_insn): Likewise. * sched-deps.c (sched_analyze_insn): Likewise. * expr.c (init_block_move_fn): Set a "fn spec" attribute. * calls.c (decl_return_flags): New static function. (expand_call): Generate a SET in CALL_INSN_FUNCTION_USAGE for functions that return one of their arguments. * lto/lto-lang.c (handle_fnspec_attribute): New static function. (lto_attribute_table): Add "fn spec". (DEF_ATTR_STRING): Define and undefine along with the other macros. * regcprop.c (struct kill_set_value_data): New. (kill_set_value): Interpret data as a pointer to such a struct. Do nothing if the caller wants the register to be ignored. (copyprop_hardreg_forward_1): Handle SETs in CALL_INSN_FUNCTION_USAGE. testsuite/ * gcc.target/i386/retarg.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@187459 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/caller-save.c')
-rw-r--r--gcc/caller-save.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 39bccc4fc8e..c8f3b145946 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -433,6 +433,8 @@ setup_save_areas (void)
/* Create hard reg saved regs. */
for (chain = reload_insn_chain; chain != 0; chain = next)
{
+ rtx cheap;
+
insn = chain->insn;
next = chain->next;
if (!CALL_P (insn)
@@ -466,6 +468,9 @@ setup_save_areas (void)
new_saved_hard_reg (regno, freq);
SET_HARD_REG_BIT (hard_regs_used, regno);
}
+ cheap = find_reg_note (insn, REG_RETURNED, NULL);
+ if (cheap)
+ cheap = XEXP (cheap, 0);
/* Look through all live pseudos, mark their hard registers. */
EXECUTE_IF_SET_IN_REG_SET
(&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno, rsi)
@@ -473,7 +478,7 @@ setup_save_areas (void)
int r = reg_renumber[regno];
int bound;
- if (r < 0)
+ if (r < 0 || regno_reg_rtx[regno] == cheap)
continue;
bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
@@ -508,12 +513,18 @@ setup_save_areas (void)
memset (saved_reg_conflicts, 0, saved_regs_num * saved_regs_num);
for (chain = reload_insn_chain; chain != 0; chain = next)
{
+ rtx cheap;
call_saved_regs_num = 0;
insn = chain->insn;
next = chain->next;
if (!CALL_P (insn)
|| find_reg_note (insn, REG_NORETURN, NULL))
continue;
+
+ cheap = find_reg_note (insn, REG_RETURNED, NULL);
+ if (cheap)
+ cheap = XEXP (cheap, 0);
+
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
COPY_HARD_REG_SET (used_regs, call_used_reg_set);
@@ -546,7 +557,7 @@ setup_save_areas (void)
int r = reg_renumber[regno];
int bound;
- if (r < 0)
+ if (r < 0 || regno_reg_rtx[regno] == cheap)
continue;
bound = r + hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
@@ -796,6 +807,11 @@ save_call_clobbered_regs (void)
unsigned regno;
HARD_REG_SET hard_regs_to_save;
reg_set_iterator rsi;
+ rtx cheap;
+
+ cheap = find_reg_note (insn, REG_RETURNED, NULL);
+ if (cheap)
+ cheap = XEXP (cheap, 0);
/* Use the register life information in CHAIN to compute which
regs are live during the call. */
@@ -817,7 +833,7 @@ save_call_clobbered_regs (void)
int nregs;
enum machine_mode mode;
- if (r < 0)
+ if (r < 0 || regno_reg_rtx[regno] == cheap)
continue;
nregs = hard_regno_nregs[r][PSEUDO_REGNO_MODE (regno)];
mode = HARD_REGNO_CALLER_SAVE_MODE
@@ -851,6 +867,17 @@ save_call_clobbered_regs (void)
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
n_regs_saved++;
+
+ if (cheap
+ && HARD_REGISTER_P (cheap)
+ && TEST_HARD_REG_BIT (call_used_reg_set, REGNO (cheap)))
+ {
+ rtx call_set = single_set (insn);
+ rtx dest = SET_DEST (call_set);
+ rtx pat = gen_rtx_SET (VOIDmode, cheap,
+ copy_rtx (dest));
+ chain = insert_one_insn (chain, 0, -1, pat);
+ }
}
last = chain;
}