diff options
author | Giuseppe Scrivano <gscrivano@gnu.org> | 2009-09-21 16:41:58 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2009-09-21 16:41:58 +0000 |
commit | d9334061eab3d7bab9f85f2b051dd714d62630c9 (patch) | |
tree | d4a8058faf26a3a540090cddd356cfa068c5d8bf /gcc | |
parent | 334738b440a3f7eb2b1b488c2f4fbac88bd85ca9 (diff) | |
download | gcc-d9334061eab3d7bab9f85f2b051dd714d62630c9.zip gcc-d9334061eab3d7bab9f85f2b051dd714d62630c9.tar.gz gcc-d9334061eab3d7bab9f85f2b051dd714d62630c9.tar.bz2 |
tree-tailcall.c (process_assignment): Don't check if a multiplication or an addition are already present.
2009-09-21 Giuseppe Scrivano <gscrivano@gnu.org>
* tree-tailcall.c (process_assignment): Don't check if a multiplication
or an addition are already present.
(find_tail_calls): Combine multiple additions and multiplications.
(adjust_accumulator_values): Emit accumulators.
testsuite:
2009-09-21 Giuseppe Scrivano <gscrivano@gnu.org>
* gcc.dg/tree-ssa/tailrecursion-6.c: New file.
From-SVN: r151935
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c | 12 | ||||
-rw-r--r-- | gcc/tree-tailcall.c | 42 |
4 files changed, 52 insertions, 13 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9dbabcd..f7d6cee 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2009-09-21 Giuseppe Scrivano <gscrivano@gnu.org> + + * tree-tailcall.c (process_assignment): Don't check if a multiplication + or an addition are already present. + (find_tail_calls): Combine multiple additions and multiplications. + (adjust_accumulator_values): Emit accumulators. + 2009-09-21 Kai Tietz <kai.tietz@onevision.com> * config/i386/i386.c (ix86_expand_epilogue): Adjust offset for diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2df641b..8bf9349 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2009-09-21 Giuseppe Scrivano <gscrivano@gnu.org> + + * gcc.dg/tree-ssa/tailrecursion-6.c: New file. + 2009-09-21 Jason Merrill <jason@redhat.com> PR c++/41421 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c new file mode 100644 index 0000000..3794275 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-tailr-details" } */ +int +foo (int a) +{ + if (a) + return a * (2 * (foo (a - 1))) + a + 1; + else + return 0; +} +/* { dg-final { scan-tree-dump-times "Eliminated tail recursion" 1 "tailr1"} } */ +/* { dg-final { cleanup-tree-dump "tailr\[1-2\]" } } */ diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c index d1f6dc1..c29bfc3 100644 --- a/gcc/tree-tailcall.c +++ b/gcc/tree-tailcall.c @@ -326,22 +326,11 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m, switch (code) { case PLUS_EXPR: - /* There should be no previous addition. TODO -- it should be fairly - straightforward to lift this restriction -- just allow storing - more complicated expressions in *A, and gimplify it in - adjust_accumulator_values. */ - if (*a) - return false; *a = non_ass_var; *ass_var = dest; return true; case MULT_EXPR: - /* Similar remark applies here. Handling multiplication after addition - is just slightly more complicated -- we need to multiply both *A and - *M. */ - if (*a || *m) - return false; *m = non_ass_var; *ass_var = dest; return true; @@ -484,6 +473,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret) agsi = gsi; while (1) { + tree tmp_a = NULL_TREE; + tree tmp_m = NULL_TREE; gsi_next (&agsi); while (gsi_end_p (agsi)) @@ -508,8 +499,26 @@ find_tail_calls (basic_block bb, struct tailcall **ret) return; /* This is a gimple assign. */ - if (! process_assignment (stmt, gsi, &m, &a, &ass_var)) + if (! process_assignment (stmt, gsi, &tmp_m, &tmp_a, &ass_var)) return; + + if (tmp_a) + { + if (a) + a = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp_a), a, tmp_a); + else + a = tmp_a; + } + if (tmp_m) + { + if (m) + m = fold_build2 (MULT_EXPR, TREE_TYPE (tmp_m), m, tmp_m); + else + m = tmp_m; + + if (a) + a = fold_build2 (MULT_EXPR, TREE_TYPE (tmp_m), a, tmp_m); + } } /* See if this is a tail call we can handle. */ @@ -605,8 +614,15 @@ update_accumulator_with_ops (enum tree_code code, tree acc, tree op1, static void adjust_accumulator_values (gimple_stmt_iterator gsi, tree m, tree a, edge back) { - tree var, a_acc_arg = a_acc, m_acc_arg = m_acc; + tree var, a_acc_arg, m_acc_arg; + + if (m) + m = force_gimple_operand_gsi (&gsi, m, true, NULL, true, GSI_SAME_STMT); + if (a) + a = force_gimple_operand_gsi (&gsi, a, true, NULL, true, GSI_SAME_STMT); + a_acc_arg = a_acc; + m_acc_arg = m_acc; if (a) { if (m_acc) |