This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[3.4 only] PR middle-end/21964: tail recursion and postincrements
- From: Richard Sandiford <richard at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: gdr at integrable-solutions dot net
- Date: Mon, 01 Aug 2005 12:15:23 +0100
- Subject: [3.4 only] PR middle-end/21964: tail recursion and postincrements
This patch fixes a 3.4-only regression from 2.95. We try to apply
tail call optimisations to functions like:
void foo (int n) { ... foo (new_n); }
giving the equivalent of:
void foo (int n) { lab: ... n = new_n'; goto lab; }
However, because of the way the code is expanded, if new_n contains a
post-modification of "n", the post-modification will win. For example,
the tail-recursion optimisers will treat:
void foo (int n) { ... foo (n++); }
like:
void foo (int n) { ... foo (n + 1); }
rather than the correct:
void foo (int n) { ... foo (n); }
I think the problem is simply a missing "emit_queue ()". The assignments
to the argument variables are simulating a function call, and since there's
a sequence point before the call, we should flush all post-modifications
at that point.
Bootstrapped & regression tested on i686-pc-linux-gnu. OK for 3.4?
If so, I'll apply the (working) testcase to 4.0 and 4.1 too.
Richard
PR middle-end/21964
* stmt.c (tail_recursion_args): Insert a call to emit_queue.
testsuite/
PR middle-end/21964
* gcc.c-torture/execute/pr21964-1.c: New test.
Index: stmt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stmt.c,v
retrieving revision 1.342.2.3
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.342.2.3 stmt.c
*** stmt.c 6 May 2004 23:32:47 -0000 1.342.2.3
--- stmt.c 1 Aug 2005 08:54:23 -0000
*************** tail_recursion_args (tree actuals, tree
*** 3353,3358 ****
--- 3353,3364 ----
argvec[i] = copy_to_reg (argvec[i]);
}
+ /* Insert the pre-call sequence point. This is important in cases
+ where the actual values post-modify the formals: we want the final
+ values of the formals to be the ones that we assign below, not the
+ result of the post-modification. */
+ emit_queue ();
+
/* Store the values of the actuals into the formals. */
for (f = formals, a = actuals, i = 0; f;
diff -c /dev/null testsuite/gcc.c-torture/execute/pr21964-1.c
*** /dev/null 2005-06-16 22:49:09.000000000 +0100
--- testsuite/gcc.c-torture/execute/pr21964-1.c 2005-08-01 09:51:02.000000000 +0100
***************
*** 0 ****
--- 1,16 ----
+ void
+ foo (int n, int m)
+ {
+ if (m == 0)
+ exit (0);
+ else if (n != 0)
+ abort ();
+ else
+ foo (n++, m - 1);
+ }
+
+ int
+ main (void)
+ {
+ foo (0, 4);
+ }