aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiuseppe Scrivano <gscrivano@gnu.org>2009-09-21 16:41:58 +0000
committerPaolo Bonzini <bonzini@gcc.gnu.org>2009-09-21 16:41:58 +0000
commitd9334061eab3d7bab9f85f2b051dd714d62630c9 (patch)
treed4a8058faf26a3a540090cddd356cfa068c5d8bf
parent334738b440a3f7eb2b1b488c2f4fbac88bd85ca9 (diff)
downloadgcc-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
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c12
-rw-r--r--gcc/tree-tailcall.c42
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)