summaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-14 12:08:31 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-14 12:08:31 +0000
commitc8010b803d34fa7e096747067e33c650b36ecc06 (patch)
treef9965bd4902a6a182ee0908a0ebd8e8bbd34a1cf /gcc/calls.c
parent1c88e4bc91881bfbd05b30c0f8f372b58e74ab26 (diff)
downloadgcc-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/calls.c')
-rw-r--r--gcc/calls.c53
1 files changed, 52 insertions, 1 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index a01c4233357..03c92168a24 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -574,6 +574,41 @@ special_function_p (const_tree fndecl, int flags)
return flags;
}
+/* Similar to special_function_p; return a set of ERF_ flags for the
+ function FNDECL. */
+static int
+decl_return_flags (tree fndecl)
+{
+ tree attr;
+ tree type = TREE_TYPE (fndecl);
+ if (!type)
+ return 0;
+
+ attr = lookup_attribute ("fn spec", TYPE_ATTRIBUTES (type));
+ if (!attr)
+ return 0;
+
+ attr = TREE_VALUE (TREE_VALUE (attr));
+ if (!attr || TREE_STRING_LENGTH (attr) < 1)
+ return 0;
+
+ switch (TREE_STRING_POINTER (attr)[0])
+ {
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ return ERF_RETURNS_ARG | (TREE_STRING_POINTER (attr)[0] - '1');
+
+ case 'm':
+ return ERF_NOALIAS;
+
+ case '.':
+ default:
+ return 0;
+ }
+}
+
/* Return nonzero when FNDECL represents a call to setjmp. */
int
@@ -2247,8 +2282,9 @@ expand_call (tree exp, rtx target, int ignore)
(on machines that lack push insns), or 0 if space not preallocated. */
rtx argblock = 0;
- /* Mask of ECF_ flags. */
+ /* Mask of ECF_ and ERF_ flags. */
int flags = 0;
+ int return_flags = 0;
#ifdef REG_PARM_STACK_SPACE
/* Define the boundary of the register parm stack space that needs to be
saved, if any. */
@@ -2293,6 +2329,7 @@ expand_call (tree exp, rtx target, int ignore)
{
fntype = TREE_TYPE (fndecl);
flags |= flags_from_decl_or_type (fndecl);
+ return_flags |= decl_return_flags (fndecl);
}
else
{
@@ -3105,6 +3142,20 @@ expand_call (tree exp, rtx target, int ignore)
VOIDmode, void_type_node,
true);
+ if (pass == 1 && (return_flags & ERF_RETURNS_ARG))
+ {
+ int arg_nr = return_flags & ERF_RETURN_ARG_MASK;
+ if (PUSH_ARGS_REVERSED)
+ arg_nr = num_actuals - arg_nr - 1;
+ if (args[arg_nr].reg
+ && valreg
+ && REG_P (valreg)
+ && GET_MODE (args[arg_nr].reg) == GET_MODE (valreg))
+ call_fusage
+ = gen_rtx_EXPR_LIST (TYPE_MODE (TREE_TYPE (args[arg_nr].tree_value)),
+ gen_rtx_SET (VOIDmode, valreg, args[arg_nr].reg),
+ call_fusage);
+ }
/* All arguments and registers used for the call must be set up by
now! */