On Fri, May 6, 2011 at 12:44 PM, Zdenek Dvorak <rakd...@kam.mff.cuni.cz> wrote: > Hi, > > when accumulator transformation is performed on a function like > > foo(a) > { > if (a > 0) > return 1 + foo (a - 1) > > return bla(); > } > > this becomes > > foo(a) > { > int tmp = 0; > > while (a > 0) > tm = 1 + tmp; > > return tmp + bla(); > } > > Before, bla was a tail-call, but after the optimization, it is not (since an > addition > has to be performed after the result of bla is known). However, we used to > mark bla > as tail-call, leading to a misscompilation later. Fixed by not marking > tail-calls > when the transformation is performed. Bootstrapped and regtested on i686.
Ok. Thanks, Richard. > Zdenek > > PR tree-optimization/48837 > * tree-tailcall.c (tree_optimize_tail_calls_1): Do not mark tailcalls > when accumulator transformation is performed. > > * gcc.dg/pr48837.c: New testcase. > > Index: tree-tailcall.c > =================================================================== > --- tree-tailcall.c (revision 173354) > +++ tree-tailcall.c (working copy) > @@ -1021,6 +1021,14 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls) > integer_one_node); > } > > + if (a_acc || m_acc) > + { > + /* When the tail call elimination using accumulators is performed, > + statements adding the accumulated value are inserted at all exits. > + This turns all other tail calls to non-tail ones. */ > + opt_tailcalls = false; > + } > + > for (; tailcalls; tailcalls = next) > { > next = tailcalls->next; > Index: testsuite/gcc.dg/pr48837.c > =================================================================== > --- testsuite/gcc.dg/pr48837.c (revision 0) > +++ testsuite/gcc.dg/pr48837.c (revision 0) > @@ -0,0 +1,30 @@ > +/* PR tree-optimization/48837 */ > +/* { dg-do run } */ > +/* { dg-options "-O2" } */ > + > +void abort (void); > + > +__attribute__((noinline)) > +int baz(void) > +{ > + return 1; > +} > + > +inline const int *bar(const int *a, const int *b) > +{ > + return *a ? a : b; > +} > + > +int foo(int a, int b) > +{ > + return a || b ? baz() : foo(*bar(&a, &b), 1) + foo(1, 0); > +} > + > +int main(void) > +{ > + if (foo(0, 0) != 2) > + abort(); > + > + return 0; > +} > + >