OSDN Git Service

gcc/
authorpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 Sep 2010 23:39:12 +0000 (23:39 +0000)
committerpaolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 5 Sep 2010 23:39:12 +0000 (23:39 +0000)
2010-09-05  Giuseppe Scrivano  <gscrivano@gnu.org>

* tree-tailcall.c (process_assignment): Handle NEGATE_EXPR and
MINUS_EXPR.

gcc/testsuite/
2010-09-05  Giuseppe Scrivano  <gscrivano@gnu.org>

* gcc.dg/tree-ssa/tailrecursion-7.c: New file.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163888 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-7.c [new file with mode: 0644]
gcc/tree-tailcall.c

index 1edae2f..141063e 100644 (file)
@@ -1,3 +1,8 @@
+2010-09-05  Giuseppe Scrivano  <gscrivano@gnu.org>
+
+       * tree-tailcall.c (process_assignment): Handle NEGATE_EXPR and
+       MINUS_EXPR.
+
 2010-09-05  Mark Mitchell  <mark@codesourcery.com>
 
        * doc/invoke.texi: Document -Wdouble-promotion.
@@ -19,7 +24,7 @@
 
        * config/sh/sh.c (sh_option_override): Make static.
        Adjust comments.  Declare.
-       (sh_function_value_regno_p): Likewise. 
+       (sh_function_value_regno_p): Likewise.
        (sh_register_move_cost): Modify the arguments, make static.
        Adjust comments.  Declare.
        (TARGET_OPTION_OVERRIDE, TARGET_REGISTER_MOVE_COST
index 316811e..d72be50 100644 (file)
@@ -1,3 +1,7 @@
+2010-09-05  Giuseppe Scrivano  <gscrivano@gnu.org>
+
+       * gcc.dg/tree-ssa/tailrecursion-7.c: New file.
+
 2010-09-05  Mark Mitchell  <mark@codesourcery.com>
 
        * gcc.dg/Wdouble-promotion.c: New.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-7.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-7.c
new file mode 100644 (file)
index 0000000..875a6aa
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-do run } */
+/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-optimized" } */
+
+extern void abort (void);
+extern void exit (int);
+
+int foo (int n)
+{
+  return n == 0 ? 1 : n * (n - foo (n - 1));
+}
+
+int bar (int n)
+{
+  return n == 0 ? 1 : n * (- bar (n - 1));
+}
+
+int baz (int n, int m)
+{
+  return n == 0 ? 100 : (baz (n - 1, m) - m);
+}
+
+int main (void)
+{
+  if (foo (6) != 726)
+    abort ();
+
+  if (bar (7) != -5040)
+    abort ();
+
+  if (baz (10, 5) != 50)
+    abort ();
+
+  exit (0);
+}
+
+/* { dg-final { scan-tree-dump-times "\\mfoo\\M" 4 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "\\mbar\\M" 4 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "\\mbaz\\M" 4 "optimized"} } */
+
+/* { dg-final { cleanup-tree-dump "optimized" } } */
index 65eaa40..71a273f 100644 (file)
@@ -252,7 +252,7 @@ static bool
 process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
                    tree *a, tree *ass_var)
 {
-  tree op0, op1, non_ass_var;
+  tree op0, op1 = NULL_TREE, non_ass_var = NULL_TREE;
   tree dest = gimple_assign_lhs (stmt);
   enum tree_code code = gimple_assign_rhs_code (stmt);
   enum gimple_rhs_class rhs_class = get_gimple_rhs_class (code);
@@ -278,8 +278,20 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
       return true;
     }
 
-  if (rhs_class != GIMPLE_BINARY_RHS)
-    return false;
+  switch (rhs_class)
+    {
+    case GIMPLE_BINARY_RHS:
+      op1 = gimple_assign_rhs2 (stmt);
+
+      /* Fall through.  */
+
+    case GIMPLE_UNARY_RHS:
+      op0 = gimple_assign_rhs1 (stmt);
+      break;
+
+    default:
+      return false;
+    }
 
   /* Accumulator optimizations will reverse the order of operations.
      We can only do that for floating-point types if we're assuming
@@ -288,20 +300,9 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
     if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
       return false;
 
-  /* We only handle the code like
-
-     x = call ();
-     y = m * x;
-     z = y + a;
-     return z;
-
-     TODO -- Extend it for cases where the linear transformation of the output
-     is expressed in a more complicated way.  */
-
-  op0 = gimple_assign_rhs1 (stmt);
-  op1 = gimple_assign_rhs2 (stmt);
-
-  if (op0 == *ass_var
+  if (rhs_class == GIMPLE_UNARY_RHS)
+    ;
+  else if (op0 == *ass_var
       && (non_ass_var = independent_of_stmt_p (op1, stmt, call)))
     ;
   else if (op1 == *ass_var
@@ -322,8 +323,32 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
       *ass_var = dest;
       return true;
 
-      /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR,
-        POINTER_PLUS_EXPR).  */
+    case NEGATE_EXPR:
+      if (FLOAT_TYPE_P (TREE_TYPE (op0)))
+        *m = build_real (TREE_TYPE (op0), dconstm1);
+      else
+        *m = build_int_cst (TREE_TYPE (op0), -1);
+
+      *ass_var = dest;
+      return true;
+
+    case MINUS_EXPR:
+      if (*ass_var == op0)
+        *a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var);
+      else
+        {
+          if (FLOAT_TYPE_P (TREE_TYPE (non_ass_var)))
+            *m = build_real (TREE_TYPE (non_ass_var), dconstm1);
+          else
+            *m = build_int_cst (TREE_TYPE (non_ass_var), -1);
+
+          *a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var);
+        }
+
+      *ass_var = dest;
+      return true;
+
+      /* TODO -- Handle POINTER_PLUS_EXPR.  */
 
     default:
       return false;