gcc/gcc41-pr32285.patch
Jakub Jelinek 1c109062ac 4.1.2-13
2007-06-15 17:42:21 +00:00

74 lines
2.0 KiB
Diff

2007-06-14 Jakub Jelinek <jakub@redhat.com>
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.
--- gcc/calls.c.jj 2007-06-13 17:38:55.000000000 +0200
+++ gcc/calls.c 2007-06-14 14:50:56.000000000 +0200
@@ -1269,13 +1269,25 @@ precompute_arguments (int flags, int num
/* 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)));
--- gcc/testsuite/gcc.c-torture/execute/20070614-1.c.jj 2007-06-14 15:32:28.000000000 +0200
+++ gcc/testsuite/gcc.c-torture/execute/20070614-1.c 2007-06-11 13:23:19.000000000 +0200
@@ -0,0 +1,33 @@
+extern void abort (void);
+
+_Complex v = 3.0 + 1.0iF;
+
+void
+foo (_Complex z, int *x)
+{
+ if (z != v)
+ abort ();
+}
+
+_Complex bar (_Complex z) __attribute__ ((pure));
+_Complex
+bar (_Complex z)
+{
+ return v;
+}
+
+int
+baz (void)
+{
+ int a, i;
+ for (i = 0; i < 6; i++)
+ foo (bar (1.0iF * i), &a);
+ return 0;
+}
+
+int
+main ()
+{
+ baz ();
+ return 0;
+}