OSDN Git Service

Backported from mainline
[pf3gnuchains/gcc-fork.git] / gcc / tree-tailcall.c
index 6a23080..e538700 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, 2012
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -35,6 +35,7 @@ along with GCC; see the file COPYING3.  If not see
 #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
@@ -152,7 +153,7 @@ 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 (targetm.except_unwind_info (&global_options) == UI_SJLJ
+  if (targetm_common.except_unwind_info (&global_options) == UI_SJLJ
       && current_function_has_exception_handlers ())
     return false;
 
@@ -328,8 +329,10 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
     case NEGATE_EXPR:
       if (FLOAT_TYPE_P (TREE_TYPE (op0)))
         *m = build_real (TREE_TYPE (op0), dconstm1);
-      else
+      else if (INTEGRAL_TYPE_P (TREE_TYPE (op0)))
         *m = build_int_cst (TREE_TYPE (op0), -1);
+      else
+        return false;
 
       *ass_var = dest;
       return true;
@@ -341,8 +344,10 @@ process_assignment (gimple stmt, gimple_stmt_iterator call, tree *m,
         {
           if (FLOAT_TYPE_P (TREE_TYPE (non_ass_var)))
             *m = build_real (TREE_TYPE (non_ass_var), dconstm1);
-          else
+          else if (INTEGRAL_TYPE_P (TREE_TYPE (non_ass_var)))
             *m = build_int_cst (TREE_TYPE (non_ass_var), -1);
+         else
+           return false;
 
           *a = fold_build1 (NEGATE_EXPR, TREE_TYPE (non_ass_var), non_ass_var);
         }
@@ -399,9 +404,10 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
     {
       stmt = gsi_stmt (gsi);
 
-      /* Ignore labels, returns and debug stmts.  */
+      /* Ignore labels, returns, clobbers and debug stmts.  */
       if (gimple_code (stmt) == GIMPLE_LABEL
          || gimple_code (stmt) == GIMPLE_RETURN
+         || gimple_clobber_p (stmt)
          || is_gimple_debug (stmt))
        continue;
 
@@ -522,6 +528,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
       if (gimple_code (stmt) == GIMPLE_RETURN)
        break;
 
+      if (gimple_clobber_p (stmt))
+       continue;
+
       if (is_gimple_debug (stmt))
        continue;
 
@@ -567,6 +576,11 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
   if (!tail_recursion && (m || a))
     return;
 
+  /* For pointers don't allow additions or multiplications.  */
+  if ((m || a)
+      && POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
+    return;
+
   nw = XNEW (struct tailcall);
 
   nw->call_gsi = gsi;
@@ -596,8 +610,8 @@ add_successor_phi_arg (edge e, tree var, tree phi_arg)
 }
 
 /* Creates a GIMPLE statement which computes the operation specified by
-   CODE, OP0 and OP1 to a new variable with name LABEL and inserts the
-   statement in the position specified by GSI and UPDATE.  Returns the
+   CODE, ACC and OP1 to a new variable with name LABEL and inserts the
+   statement in the position specified by GSI.  Returns the
    tree node of the statement's result.  */
 
 static tree
@@ -622,7 +636,7 @@ adjust_return_value_with_ops (enum tree_code code, const char *label,
                                            fold_convert (TREE_TYPE (op1), acc),
                                            op1));
       rhs = force_gimple_operand_gsi (&gsi, rhs,
-                                     false, NULL, true, GSI_CONTINUE_LINKING);
+                                     false, NULL, true, GSI_SAME_STMT);
       stmt = gimple_build_assign (NULL_TREE, rhs);
     }
 
@@ -1092,7 +1106,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 */
  }
 };
 
@@ -1111,6 +1125,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 */
  }
 };