aboutsummaryrefslogtreecommitdiff
path: root/gcc/regcprop.c
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2012-05-14 12:08:31 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2012-05-14 12:08:31 +0000
commite384e6b59c074ac936f0f3212ca33fe40f3d82f5 (patch)
treef9965bd4902a6a182ee0908a0ebd8e8bbd34a1cf /gcc/regcprop.c
parent92290a187e25ed1b21ff99de259421e7b540349e (diff)
downloadgcc-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/regcprop.c')
-rw-r--r--gcc/regcprop.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index ceb4635..4d6ea29 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -254,18 +254,27 @@ kill_clobbered_value (rtx x, const_rtx set, void *data)
kill_value (x, vd);
}
+/* A structure passed as data to kill_set_value through note_stores. */
+struct kill_set_value_data
+{
+ struct value_data *vd;
+ rtx ignore_set_reg;
+};
+
/* Called through note_stores. If X is set, not clobbered, kill its
current value and install it as the root of its own value list. */
static void
kill_set_value (rtx x, const_rtx set, void *data)
{
- struct value_data *const vd = (struct value_data *) data;
+ struct kill_set_value_data *ksvd = (struct kill_set_value_data *) data;
+ if (rtx_equal_p (x, ksvd->ignore_set_reg))
+ return;
if (GET_CODE (set) != CLOBBER)
{
- kill_value (x, vd);
+ kill_value (x, ksvd->vd);
if (REG_P (x))
- set_value_regno (REGNO (x), GET_MODE (x), vd);
+ set_value_regno (REGNO (x), GET_MODE (x), ksvd->vd);
}
}
@@ -743,6 +752,7 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
rtx set;
bool replaced[MAX_RECOG_OPERANDS];
bool changed = false;
+ struct kill_set_value_data ksvd;
if (!NONDEBUG_INSN_P (insn))
{
@@ -976,14 +986,39 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
note_uses (&PATTERN (insn), cprop_find_used_regs, vd);
}
+ ksvd.vd = vd;
+ ksvd.ignore_set_reg = NULL_RTX;
+
/* Clobber call-clobbered registers. */
if (CALL_P (insn))
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i))
- kill_value_regno (i, 1, vd);
+ {
+ int set_regno = INVALID_REGNUM;
+ int set_nregs = 0;
+ rtx exp;
+ for (exp = CALL_INSN_FUNCTION_USAGE (insn); exp; exp = XEXP (exp, 1))
+ {
+ rtx x = XEXP (exp, 0);
+ if (GET_CODE (x) == SET)
+ {
+ rtx dest = SET_DEST (x);
+ kill_value (dest, vd);
+ set_value_regno (REGNO (dest), GET_MODE (dest), vd);
+ copy_value (dest, SET_SRC (x), vd);
+ ksvd.ignore_set_reg = dest;
+ set_regno = REGNO (dest);
+ set_nregs
+ = hard_regno_nregs[set_regno][GET_MODE (dest)];
+ break;
+ }
+ }
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (regs_invalidated_by_call, i)
+ && (i < set_regno || i >= set_regno + set_nregs))
+ kill_value_regno (i, 1, vd);
+ }
/* Notice stores. */
- note_stores (PATTERN (insn), kill_set_value, vd);
+ note_stores (PATTERN (insn), kill_set_value, &ksvd);
/* Notice copies. */
if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))