diff options
author | Bernd Schmidt <bernds@codesourcery.com> | 2012-05-14 12:08:31 +0000 |
---|---|---|
committer | Bernd Schmidt <bernds@gcc.gnu.org> | 2012-05-14 12:08:31 +0000 |
commit | e384e6b59c074ac936f0f3212ca33fe40f3d82f5 (patch) | |
tree | f9965bd4902a6a182ee0908a0ebd8e8bbd34a1cf /gcc/ira-lives.c | |
parent | 92290a187e25ed1b21ff99de259421e7b540349e (diff) | |
download | gcc-e384e6b59c074ac936f0f3212ca33fe40f3d82f5.zip gcc-e384e6b59c074ac936f0f3212ca33fe40f3d82f5.tar.gz gcc-e384e6b59c074ac936f0f3212ca33fe40f3d82f5.tar.bz2 |
attribs.c (decl_attributes): Avoid emitting a warning if ATTR_FLAG_BUILT_IN.
* 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.
From-SVN: r187459
Diffstat (limited to 'gcc/ira-lives.c')
-rw-r--r-- | gcc/ira-lives.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index f639e12..ad451f5 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -241,6 +241,24 @@ dec_register_pressure (enum reg_class pclass, int nregs) } } +/* Determine from the objects_live bitmap whether REGNO is currently live, + and occupies only one object. Return false if we have no information. */ +static bool +pseudo_regno_single_word_and_live_p (int regno) +{ + ira_allocno_t a = ira_curr_regno_allocno_map[regno]; + ira_object_t obj; + + if (a == NULL) + return false; + if (ALLOCNO_NUM_OBJECTS (a) > 1) + return false; + + obj = ALLOCNO_OBJECT (a, 0); + + return sparseset_bit_p (objects_live, OBJECT_CONFLICT_ID (obj)); +} + /* Mark the pseudo register REGNO as live. Update all information about live ranges and register pressure. */ static void @@ -1043,6 +1061,67 @@ bb_has_abnormal_call_pred (basic_block bb) return false; } +/* Look through the CALL_INSN_FUNCTION_USAGE of a call insn INSN, and see if + we find a SET rtx that we can use to deduce that a register can be cheaply + caller-saved. Return such a register, or NULL_RTX if none is found. */ +static rtx +find_call_crossed_cheap_reg (rtx insn) +{ + rtx cheap_reg = NULL_RTX; + rtx exp = CALL_INSN_FUNCTION_USAGE (insn); + + while (exp != NULL) + { + rtx x = XEXP (exp, 0); + if (GET_CODE (x) == SET) + { + exp = x; + break; + } + exp = XEXP (exp, 1); + } + if (exp != NULL) + { + basic_block bb = BLOCK_FOR_INSN (insn); + rtx reg = SET_SRC (exp); + rtx prev = PREV_INSN (insn); + while (prev && !(INSN_P (prev) + && BLOCK_FOR_INSN (prev) != bb)) + { + if (NONDEBUG_INSN_P (prev)) + { + rtx set = single_set (prev); + + if (set && rtx_equal_p (SET_DEST (set), reg)) + { + rtx src = SET_SRC (set); + if (!REG_P (src) || HARD_REGISTER_P (src) + || !pseudo_regno_single_word_and_live_p (REGNO (src))) + break; + if (!modified_between_p (src, prev, insn)) + cheap_reg = src; + break; + } + if (set && rtx_equal_p (SET_SRC (set), reg)) + { + rtx dest = SET_DEST (set); + if (!REG_P (dest) || HARD_REGISTER_P (dest) + || !pseudo_regno_single_word_and_live_p (REGNO (dest))) + break; + if (!modified_between_p (dest, prev, insn)) + cheap_reg = dest; + break; + } + + if (reg_overlap_mentioned_p (reg, PATTERN (prev))) + break; + } + prev = PREV_INSN (prev); + } + } + return cheap_reg; +} + /* Process insns of the basic block given by its LOOP_TREE_NODE to update allocno live ranges, allocno hard register conflicts, intersected calls, and register pressure info for allocnos for the @@ -1185,6 +1264,13 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) if (call_p) { + /* Try to find a SET in the CALL_INSN_FUNCTION_USAGE, and from + there, try to find a pseudo that is live across the call but + can be cheaply reconstructed from the return value. */ + rtx cheap_reg = find_call_crossed_cheap_reg (insn); + if (cheap_reg != NULL_RTX) + add_reg_note (insn, REG_RETURNED, cheap_reg); + last_call_num++; sparseset_clear (allocnos_processed); /* The current set of live allocnos are live across the call. */ @@ -1226,6 +1312,9 @@ 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)++; + if (cheap_reg != NULL_RTX + && ALLOCNO_REGNO (a) == (int) REGNO (cheap_reg)) + ALLOCNO_CHEAP_CALLS_CROSSED_NUM (a)++; } } |