diff options
author | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-05-14 12:08:31 +0000 |
---|---|---|
committer | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-05-14 12:08:31 +0000 |
commit | c8010b803d34fa7e096747067e33c650b36ecc06 (patch) | |
tree | f9965bd4902a6a182ee0908a0ebd8e8bbd34a1cf /gcc/caller-save.c | |
parent | 1c88e4bc91881bfbd05b30c0f8f372b58e74ab26 (diff) | |
download | gcc-c8010b803d34fa7e096747067e33c650b36ecc06.tar.gz |
* 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: svn+ssh://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.c | 33 |
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; } |