OSDN Git Service

Vector shuffling patch from Artem Shinkarov.
[pf3gnuchains/gcc-fork.git] / gcc / tree-tailcall.c
index 71a273f..87fc566 100644 (file)
@@ -1,5 +1,5 @@
 /* Tail call optimization on trees.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -34,6 +34,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "flags.h"
 #include "langhooks.h"
 #include "dbgcnt.h"
+#include "target.h"
+#include "common/common-target.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
@@ -151,7 +153,8 @@ suitable_for_tail_call_opt_p (void)
   /* If we are using sjlj exceptions, we may need to add a call to
      _Unwind_SjLj_Unregister at exit of the function.  Which means
      that we cannot do any sibcall transformations.  */
-  if (USING_SJLJ_EXCEPTIONS && current_function_has_exception_handlers ())
+  if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
+      && current_function_has_exception_handlers ())
     return false;
 
   /* Any function that calls setjmp might have longjmp called from
@@ -397,8 +400,10 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
     {
       stmt = gsi_stmt (gsi);
 
-      /* Ignore labels.  */
-      if (gimple_code (stmt) == GIMPLE_LABEL || is_gimple_debug (stmt))
+      /* Ignore labels, returns and debug stmts.  */
+      if (gimple_code (stmt) == GIMPLE_LABEL
+         || gimple_code (stmt) == GIMPLE_RETURN
+         || is_gimple_debug (stmt))
        continue;
 
       /* Check for a call.  */
@@ -479,7 +484,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
 
   /* Make sure the tail invocation of this function does not refer
      to local variables.  */
-  FOR_EACH_REFERENCED_VAR (var, rvi)
+  FOR_EACH_REFERENCED_VAR (cfun, var, rvi)
     {
       if (TREE_CODE (var) != PARM_DECL
          && auto_var_in_fn_p (var, cfun->decl)
@@ -530,20 +535,22 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
 
       if (tmp_a)
        {
+         tree type = TREE_TYPE (tmp_a);
          if (a)
-           a = fold_build2 (PLUS_EXPR, TREE_TYPE (tmp_a), a, tmp_a);
+           a = fold_build2 (PLUS_EXPR, type, fold_convert (type, a), tmp_a);
          else
            a = tmp_a;
        }
       if (tmp_m)
        {
+         tree type = TREE_TYPE (tmp_m);
          if (m)
-           m = fold_build2 (MULT_EXPR, TREE_TYPE (tmp_m), m, tmp_m);
+           m = fold_build2 (MULT_EXPR, type, fold_convert (type, m), tmp_m);
          else
            m = tmp_m;
 
          if (a)
-           a = fold_build2 (MULT_EXPR, TREE_TYPE (tmp_m), a, tmp_m);
+           a = fold_build2 (MULT_EXPR, type, fold_convert (type, a), tmp_m);
        }
     }
 
@@ -885,7 +892,7 @@ add_virtual_phis (void)
      this, we cannot do much better than to rebuild the ssa form for
      possibly affected virtual ssa names from scratch.  */
 
-  FOR_EACH_REFERENCED_VAR (var, rvi)
+  FOR_EACH_REFERENCED_VAR (cfun, var, rvi)
     {
       if (!is_gimple_reg (var) && gimple_default_def (cfun, var) != NULL_TREE)
        mark_sym_for_renaming (var);
@@ -1015,6 +1022,14 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
                                             integer_one_node);
     }
 
+  if (a_acc || m_acc)
+    {
+      /* When the tail call elimination using accumulators is performed,
+        statements adding the accumulated value are inserted at all exits.
+        This turns all other tail calls to non-tail ones.  */
+      opt_tailcalls = false;
+    }
+
   for (; tailcalls; tailcalls = next)
     {
       next = tailcalls->next;
@@ -1078,7 +1093,7 @@ struct gimple_opt_pass pass_tail_recursion =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa     /* todo_flags_finish */
+  TODO_verify_ssa                      /* todo_flags_finish */
  }
 };
 
@@ -1097,6 +1112,6 @@ struct gimple_opt_pass pass_tail_calls =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_verify_ssa     /* todo_flags_finish */
+  TODO_verify_ssa                      /* todo_flags_finish */
  }
 };