summaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-20 06:35:55 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-20 06:35:55 +0000
commitc5dc094f1ed6cfd3cf5770b2eeace9639f79df57 (patch)
tree166cd1ce7322fc29d8e7721de1c5dcbb7dfe0b43 /gcc/calls.c
parentcc7d4acefbbdb69567557525f33eee8b9ebd07f0 (diff)
downloadgcc-c5dc094f1ed6cfd3cf5770b2eeace9639f79df57.tar.gz
PR middle-end/32285
* calls.c (precompute_arguments): Also precompute CALL_EXPR arguments if ACCUMULATE_OUTGOING_ARGS. * gcc.c-torture/execute/20070614-1.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125873 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index b339c04d902..868edfc396d 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -1269,13 +1269,25 @@ precompute_arguments (int flags, int num_actuals, struct arg_data *args)
/* If this is a libcall, then precompute all arguments so that we do not
get extraneous instructions emitted as part of the libcall sequence. */
- if ((flags & ECF_LIBCALL_BLOCK) == 0)
+
+ /* If we preallocated the stack space, and some arguments must be passed
+ on the stack, then we must precompute any parameter which contains a
+ function call which will store arguments on the stack.
+ Otherwise, evaluating the parameter may clobber previous parameters
+ which have already been stored into the stack. (we have code to avoid
+ such case by saving the outgoing stack arguments, but it results in
+ worse code) */
+ if ((flags & ECF_LIBCALL_BLOCK) == 0 && !ACCUMULATE_OUTGOING_ARGS)
return;
for (i = 0; i < num_actuals; i++)
{
enum machine_mode mode;
+ if ((flags & ECF_LIBCALL_BLOCK) == 0
+ && TREE_CODE (args[i].tree_value) != CALL_EXPR)
+ continue;
+
/* If this is an addressable type, we cannot pre-evaluate it. */
gcc_assert (!TREE_ADDRESSABLE (TREE_TYPE (args[i].tree_value)));