OSDN Git Service

2008-04-30 Paul Thomas <pault@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-tailcall.c
index fa63637..0458c8a 100644 (file)
@@ -5,7 +5,7 @@ This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
 any later version.
 
 GCC is distributed in the hope that it will be useful,
@@ -14,9 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
@@ -35,6 +34,7 @@ Boston, MA 02110-1301, USA.  */
 #include "tree-pass.h"
 #include "flags.h"
 #include "langhooks.h"
+#include "dbgcnt.h"
 
 /* The file implements the tail recursion elimination.  It is also used to
    analyze the tail calls in general, passing the results to the rtl level
@@ -135,7 +135,7 @@ suitable_for_tail_opt_p (void)
   referenced_var_iterator rvi;
   tree var;
 
-  if (current_function_stdarg)
+  if (cfun->stdarg)
     return false;
 
   /* No local variable nor structure field should be call-clobbered.  We
@@ -164,7 +164,7 @@ suitable_for_tail_call_opt_p (void)
 
   /* alloca (until we have stack slot life analysis) inhibits
      sibling call optimizations, but not tail recursion.  */
-  if (current_function_calls_alloca)
+  if (cfun->calls_alloca)
     return false;
 
   /* If we are using sjlj exceptions, we may need to add a call to
@@ -176,7 +176,7 @@ suitable_for_tail_call_opt_p (void)
   /* Any function that calls setjmp might have longjmp called from
      any called function.  ??? We really should represent this
      properly in the CFG so that this needn't be special cased.  */
-  if (current_function_calls_setjmp)
+  if (cfun->calls_setjmp)
     return false;
 
   /* ??? It is OK if the argument of a function is taken in some cases,
@@ -297,7 +297,7 @@ process_assignment (tree ass, tree stmt, block_stmt_iterator call, tree *m,
   /* Accumulator optimizations will reverse the order of operations.
      We can only do that for floating-point types if we're assuming
      that addition and multiplication are associative.  */
-  if (!flag_unsafe_math_optimizations)
+  if (!flag_associative_math)
     if (FLOAT_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
       return false;
 
@@ -346,7 +346,7 @@ process_assignment (tree ass, tree stmt, block_stmt_iterator call, tree *m,
       *ass_var = dest;
       return true;
 
-      /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR).  */
+      /* TODO -- Handle other codes (NEGATE_EXPR, MINUS_EXPR, POINTER_PLUS_EXPR).  */
 
     default:
       return false;
@@ -414,7 +414,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
       /* If the statement has virtual or volatile operands, fail.  */
       ann = stmt_ann (stmt);
       if (!ZERO_SSA_OPERANDS (stmt, (SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS))
-         || ann->has_volatile_ops)
+         || ann->has_volatile_ops
+         || (!gimple_aliases_computed_p (cfun) && ann->references_memory))
        return;
     }
 
@@ -447,8 +448,8 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
                 equivalent types.  The latter requirement could be relaxed if
                 we emitted a suitable type conversion statement.  */
              if (!is_gimple_reg_type (TREE_TYPE (param))
-                 || !lang_hooks.types_compatible_p (TREE_TYPE (param),
-                                                    TREE_TYPE (arg)))
+                 || !useless_type_conversion_p (TREE_TYPE (param),
+                                               TREE_TYPE (arg)))
                break;
 
              /* The parameter should be a real operand, so that phi node
@@ -1007,7 +1008,7 @@ execute_tail_recursion (void)
 static bool
 gate_tail_calls (void)
 {
-  return flag_optimize_sibling_calls != 0;
+  return flag_optimize_sibling_calls != 0 && dbg_cnt (tail_call);
 }
 
 static unsigned int
@@ -1016,8 +1017,10 @@ execute_tail_calls (void)
   return tree_optimize_tail_calls_1 (true);
 }
 
-struct tree_opt_pass pass_tail_recursion = 
+struct gimple_opt_pass pass_tail_recursion = 
 {
+ {
+  GIMPLE_PASS,
   "tailr",                             /* name */
   gate_tail_calls,                     /* gate */
   execute_tail_recursion,              /* execute */
@@ -1029,12 +1032,14 @@ struct tree_opt_pass pass_tail_recursion =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa,    /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func | TODO_verify_ssa     /* todo_flags_finish */
+ }
 };
 
-struct tree_opt_pass pass_tail_calls = 
+struct gimple_opt_pass pass_tail_calls = 
 {
+ {
+  GIMPLE_PASS,
   "tailc",                             /* name */
   gate_tail_calls,                     /* gate */
   execute_tail_calls,                  /* execute */
@@ -1046,6 +1051,6 @@ struct tree_opt_pass pass_tail_calls =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa,    /* todo_flags_finish */
-  0                                    /* letter */
+  TODO_dump_func | TODO_verify_ssa     /* todo_flags_finish */
+ }
 };