diff options
author | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-20 06:35:55 +0000 |
---|---|---|
committer | jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-06-20 06:35:55 +0000 |
commit | c5dc094f1ed6cfd3cf5770b2eeace9639f79df57 (patch) | |
tree | 166cd1ce7322fc29d8e7721de1c5dcbb7dfe0b43 /gcc/calls.c | |
parent | cc7d4acefbbdb69567557525f33eee8b9ebd07f0 (diff) | |
download | gcc-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.c | 14 |
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))); |