From b1896e61038b3c63b567393ba12ddaa99f6f4a43 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 6 Apr 2002 19:42:22 +0000 Subject: [PATCH] re PR rtl-optimization/5120 (tail recursion incorrect using -O2) PR opt/5120 * sibcall.c (optimize_sibling_and_tail_recursive_call): Clear RTX_UNCHANGING_P for the functions arguments when a tail call is made. From-SVN: r51969 --- gcc/ChangeLog | 7 + gcc/sibcall.c | 12 ++ gcc/testsuite/ChangeLog | 5 + .../gcc.c-torture/execute/20020406-1.c | 123 ++++++++++++++++++ 4 files changed, 147 insertions(+) create mode 100644 gcc/testsuite/gcc.c-torture/execute/20020406-1.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6c451f949ab..548caa9c81f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2002-04-06 Mark Mitchell + + PR opt/5120 + * sibcall.c (optimize_sibling_and_tail_recursive_call): Clear + RTX_UNCHANGING_P for the functions arguments when a tail call + is made. + 2002-04-06 Jason Merrill * toplev.c (flag_no_inline, flag_really_no_inline): Default to 2. diff --git a/gcc/sibcall.c b/gcc/sibcall.c index 5a7997cb038..6e753fa2fa9 100644 --- a/gcc/sibcall.c +++ b/gcc/sibcall.c @@ -31,6 +31,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "basic-block.h" #include "output.h" #include "except.h" +#include "tree.h" /* In case alternate_exit_block contains copy from pseudo, to return value, record the pseudo here. In such case the pseudo must be set to function @@ -730,6 +731,7 @@ optimize_sibling_and_tail_recursive_calls () if (successful_sibling_call) { rtx insn; + tree arg; /* A sibling call sequence invalidates any REG_EQUIV notes made for this function's incoming arguments. @@ -754,6 +756,16 @@ optimize_sibling_and_tail_recursive_calls () if (INSN_P (insn)) purge_mem_unchanging_flag (PATTERN (insn)); } + + /* Similarly, invalidate RTX_UNCHANGING_P for any incoming + arguments passed in registers. */ + for (arg = DECL_ARGUMENTS (current_function_decl); + arg; + arg = TREE_CHAIN (arg)) + { + if (REG_P (DECL_RTL (arg))) + RTX_UNCHANGING_P (DECL_RTL (arg)) = false; + } } /* There may have been NOTE_INSN_BLOCK_{BEGIN,END} notes in the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7b92bce96e6..ddd75d41ea8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2002-04-06 Mark Mitchell + + PR c/5120 + * gcc.dg/20020406-1.c: New test. + 2002-04-04 David S. Miller * gcc.c-torture/execute/20020404-1.c: New test. diff --git a/gcc/testsuite/gcc.c-torture/execute/20020406-1.c b/gcc/testsuite/gcc.c-torture/execute/20020406-1.c new file mode 100644 index 00000000000..6d4967eae55 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20020406-1.c @@ -0,0 +1,123 @@ +// Origin: abbott@dima.unige.it +// PR c/5120 + +typedef unsigned int FFelem; + +FFelem FFmul(const FFelem x, const FFelem y) +{ + return x; +} + + +struct DUPFFstruct +{ + int maxdeg; + int deg; + FFelem *coeffs; +}; + +typedef struct DUPFFstruct *DUPFF; + + +int DUPFFdeg(const DUPFF f) +{ + return f->deg; +} + + +DUPFF DUPFFnew(const int maxdeg) +{ + DUPFF ans = (DUPFF)malloc(sizeof(struct DUPFFstruct)); + ans->coeffs = 0; + if (maxdeg >= 0) ans->coeffs = (FFelem*)malloc((maxdeg+1)*sizeof(FFelem)); + ans->maxdeg = maxdeg; + ans->deg = -1; + return ans; +} + +void DUPFFfree(DUPFF x) +{ +} + +void DUPFFswap(DUPFF x, DUPFF y) +{ +} + + +DUPFF DUPFFcopy(const DUPFF x) +{ + return x; +} + + +void DUPFFshift_add(DUPFF f, const DUPFF g, int deg, const FFelem coeff) +{ +} + + +DUPFF DUPFFexgcd(DUPFF *fcofac, DUPFF *gcofac, const DUPFF f, const DUPFF g) +{ + DUPFF u, v, uf, ug, vf, vg; + FFelem q, lcu, lcvrecip, p; + int df, dg, du, dv; + + printf("DUPFFexgcd called on degrees %d and %d\n", DUPFFdeg(f), DUPFFdeg(g)); + if (DUPFFdeg(f) < DUPFFdeg(g)) return DUPFFexgcd(gcofac, fcofac, g, f); /*** BUG IN THIS LINE ***/ + if (DUPFFdeg(f) != 2 || DUPFFdeg(g) != 1) abort(); + if (f->coeffs[0] == 0) return f; + /****** NEVER REACH HERE IN THE EXAMPLE ******/ + p = 2; + + df = DUPFFdeg(f); if (df < 0) df = 0; /* both inputs are zero */ + dg = DUPFFdeg(g); if (dg < 0) dg = 0; /* one input is zero */ + u = DUPFFcopy(f); + v = DUPFFcopy(g); + + uf = DUPFFnew(dg); uf->coeffs[0] = 1; uf->deg = 0; + ug = DUPFFnew(df); + vf = DUPFFnew(dg); + vg = DUPFFnew(df); vg->coeffs[0] = 1; vg->deg = 0; + + while (DUPFFdeg(v) > 0) + { + dv = DUPFFdeg(v); + lcvrecip = FFmul(1, v->coeffs[dv]); + while (DUPFFdeg(u) >= dv) + { + du = DUPFFdeg(u); + lcu = u->coeffs[du]; + q = FFmul(lcu, lcvrecip); + DUPFFshift_add(u, v, du-dv, p-q); + DUPFFshift_add(uf, vf, du-dv, p-q); + DUPFFshift_add(ug, vg, du-dv, p-q); + } + DUPFFswap(u, v); + DUPFFswap(uf, vf); + DUPFFswap(ug, vg); + } + if (DUPFFdeg(v) == 0) + { + DUPFFswap(u, v); + DUPFFswap(uf, vf); + DUPFFswap(ug, vg); + } + DUPFFfree(vf); + DUPFFfree(vg); + DUPFFfree(v); + *fcofac = uf; + *gcofac = ug; + return u; +} + + + +int main() +{ + DUPFF f, g, cf, cg, h; + f = DUPFFnew(1); f->coeffs[1] = 1; f->deg = 1; + g = DUPFFnew(2); g->coeffs[2] = 1; g->deg = 2; + + printf("calling DUPFFexgcd on degrees %d and %d\n", DUPFFdeg(f), DUPFFdeg(g)) ; + h = DUPFFexgcd(&cf, &cg, f, g); + return 0; +}