aboutsummaryrefslogtreecommitdiff
path: root/gcc/calls.c
diff options
context:
space:
mode:
authorEric Botcazou <ebotcazou@adacore.com>2005-11-13 09:55:11 +0000
committerEric Botcazou <ebotcazou@gcc.gnu.org>2005-11-13 09:55:11 +0000
commit51caaefe17ece564e44fdf6c98dba20569c95663 (patch)
tree19b659552e41d64e2cf5e934a33e7119dada4c08 /gcc/calls.c
parent5d723e5434e83d9de5271f6d1c24a694826450a8 (diff)
downloadgcc-51caaefe17ece564e44fdf6c98dba20569c95663.zip
gcc-51caaefe17ece564e44fdf6c98dba20569c95663.tar.gz
gcc-51caaefe17ece564e44fdf6c98dba20569c95663.tar.bz2
re PR middle-end/24003 (17 ACATS regressions (fixed point or decimal artihmetic))
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. Co-Authored-By: Ian Lance Taylor <ian@airs.com> From-SVN: r106860
Diffstat (limited to 'gcc/calls.c')
-rw-r--r--gcc/calls.c47
1 files changed, 35 insertions, 12 deletions
diff --git a/gcc/calls.c b/gcc/calls.c
index 920c8157..2cc15fc 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)
{