diff options
author | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-13 09:55:11 +0000 |
---|---|---|
committer | ebotcazou <ebotcazou@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-11-13 09:55:11 +0000 |
commit | aadbaa4023fe0e7b1ee073f33ca0a6cccd5c2e55 (patch) | |
tree | 19b659552e41d64e2cf5e934a33e7119dada4c08 /gcc | |
parent | 16de8065baf08ed0e7bec8a7bc488e8d037d912b (diff) | |
download | gcc-aadbaa4023fe0e7b1ee073f33ca0a6cccd5c2e55.tar.gz |
PR middle-end/24003
* calls.c (expand_call): If TARGET is a MEM and some part of the
argument area has been saved, force TARGET to a register.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@106860 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/calls.c | 47 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/nested-calls-1.c | 42 |
4 files changed, 88 insertions, 12 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 85753792d85..dcd74dae752 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2005-11-13 Eric Botcazou <ebotcazou@adacore.com> + Ian Lance Taylor <ian@airs.com> + + PR middle-end/24003 + * calls.c (expand_call): If TARGET is a MEM and some part of the + argument area has been saved, force TARGET to a register. + 2005-11-13 Razya Ladelsky <razya@il.ibm.com> * ipa-prop.c (ipa_callsite_compute_param ): Removed obsolete type diff --git a/gcc/calls.c b/gcc/calls.c index 920c81575e0..2cc15fc2e81 100644 --- a/gcc/calls.c +++ b/gcc/calls.c @@ -2857,6 +2857,8 @@ expand_call (tree exp, rtx target, int ignore) && GET_MODE (target) == TYPE_MODE (TREE_TYPE (exp)) && GET_MODE (target) == GET_MODE (valreg)) { + bool may_overlap = false; + /* We have to copy a return value in a CLASS_LIKELY_SPILLED hard reg to a plain register. */ if (REG_P (valreg) @@ -2865,19 +2867,40 @@ expand_call (tree exp, rtx target, int ignore) && !(REG_P (target) && !HARD_REGISTER_P (target))) valreg = copy_to_reg (valreg); - /* TARGET and VALREG cannot be equal at this point because the - latter would not have REG_FUNCTION_VALUE_P true, while the - former would if it were referring to the same register. - - If they refer to the same register, this move will be a no-op, - except when function inlining is being done. */ - emit_move_insn (target, valreg); + /* If TARGET is a MEM in the argument area, and we have + saved part of the argument area, then we can't store + directly into TARGET as it may get overwritten when we + restore the argument save area below. Don't work too + hard though and simply force TARGET to a register if it + is a MEM; the optimizer is quite likely to sort it out. */ + if (ACCUMULATE_OUTGOING_ARGS && pass && MEM_P (target)) + for (i = 0; i < num_actuals; i++) + if (args[i].save_area) + { + may_overlap = true; + break; + } - /* If we are setting a MEM, this code must be executed. Since it is - emitted after the call insn, sibcall optimization cannot be - performed in that case. */ - if (MEM_P (target)) - sibcall_failure = 1; + if (may_overlap) + target = copy_to_reg (valreg); + else + { + /* TARGET and VALREG cannot be equal at this point + because the latter would not have + REG_FUNCTION_VALUE_P true, while the former would if + it were referring to the same register. + + If they refer to the same register, this move will be + a no-op, except when function inlining is being + done. */ + emit_move_insn (target, valreg); + + /* If we are setting a MEM, this code must be executed. + Since it is emitted after the call insn, sibcall + optimization cannot be performed in that case. */ + if (MEM_P (target)) + sibcall_failure = 1; + } } else if (TYPE_MODE (TREE_TYPE (exp)) == BLKmode) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ae3265f36e1..e6f9757c0ea 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2005-11-13 Eric Botcazou <ebotcazou@adacore.com> + + * gcc.dg/nested-calls-1.c: New test. + 2005-11-13 Francois-Xavier Coudert <coudert@clipper.ens.fr> * gfortran.dg/complex_intrinsic_1.f90: New test. diff --git a/gcc/testsuite/gcc.dg/nested-calls-1.c b/gcc/testsuite/gcc.dg/nested-calls-1.c new file mode 100644 index 00000000000..b3f08becac0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/nested-calls-1.c @@ -0,0 +1,42 @@ +/* PR middle-end/24003 */ +/* Contributed by Eric Botcazou <ebotcazou@adacore.com> */ + +/* { dg-do run } */ +/* { dg-options "-std=c99 -O -fno-inline" } */ +/* { dg-options "-std=c99 -O -fno-inline -mtune=i686" { target { i?86-*-* && ilp32 } } } */ + +#include <limits.h> + +typedef unsigned long uns32_t; +typedef unsigned long long uns64_t; + +extern void abort(void); + +uns32_t lo (uns64_t p) +{ + return (uns32_t)p; +} + +uns64_t concat (uns32_t p1, uns32_t p2) +{ +#if LLONG_MAX > 2147483647L + return ((uns64_t)p1 << 32) | p2; +#else + return 0; +#endif +} + +uns64_t lshift32 (uns64_t p1, uns32_t p2) +{ + return concat (lo (p1), p2); +} + +int main(void) +{ +#if LLONG_MAX > 2147483647L + if (lshift32 (0xFFFFFFFF12345678ULL, 0x90ABCDEFUL) != 0x1234567890ABCDEFULL) + abort (); +#endif + + return 0; +} |