OSDN Git Service

2009-07-20 Shujing Zhao <pearly.zhao@oracle.com>
[pf3gnuchains/gcc-fork.git] / gcc / tree-tailcall.c
index 061d6c9..f2d58dd 100644 (file)
@@ -1,5 +1,5 @@
 /* Tail call optimization on trees.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -136,15 +136,11 @@ suitable_for_tail_opt_p (void)
   if (cfun->stdarg)
     return false;
 
-  /* No local variable nor structure field should be call-used.  We
-     ignore any kind of memory tag, as these are not real variables.  */
-
+  /* No local variable nor structure field should be call-used.  */
   FOR_EACH_REFERENCED_VAR (var, rvi)
     {
       if (!is_global_var (var)
-         && !MTAG_P (var)
-         && (gimple_aliases_computed_p (cfun)? is_call_used (var)
-             : TREE_ADDRESSABLE (var)))
+         && is_call_used (var))
        return false;
     }
 
@@ -410,11 +406,9 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
          break;
        }
 
-      /* If the statement has virtual or volatile operands, fail.  */
-      if (!ZERO_SSA_OPERANDS (stmt, (SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS))
-         || gimple_has_volatile_ops (stmt)
-         || (!gimple_aliases_computed_p (cfun)
-             && gimple_references_memory_p (stmt)))
+      /* If the statement references memory or volatile operands, fail.  */
+      if (gimple_references_memory_p (stmt)
+         || gimple_has_volatile_ops (stmt))
        return;
     }
 
@@ -573,6 +567,9 @@ adjust_return_value_with_ops (enum tree_code code, const char *label,
   gimple stmt = gimple_build_assign_with_ops (code, tmp, op0, op1);
   tree result;
 
+  if (TREE_CODE (ret_type) == COMPLEX_TYPE
+      || TREE_CODE (ret_type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp) = 1;
   add_referenced_var (tmp);
   result = make_ssa_name (tmp, stmt);
   gimple_assign_set_lhs (stmt, result);
@@ -867,6 +864,9 @@ create_tailcall_accumulator (const char *label, basic_block bb, tree init)
   tree tmp = create_tmp_var (ret_type, label);
   gimple phi;
 
+  if (TREE_CODE (ret_type) == COMPLEX_TYPE
+      || TREE_CODE (ret_type) == VECTOR_TYPE)
+    DECL_GIMPLE_REG_P (tmp) = 1;
   add_referenced_var (tmp);
   phi = create_phi_node (tmp, bb);
   /* RET_TYPE can be a float when -ffast-maths is enabled.  */
@@ -914,8 +914,10 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
 
       if (!phis_constructed)
        {
-         /* Ensure that there is only one predecessor of the block.  */
-         if (!single_pred_p (first))
+         /* Ensure that there is only one predecessor of the block
+            or if there are existing degenerate PHI nodes.  */
+         if (!single_pred_p (first)
+             || !gimple_seq_empty_p (phi_nodes (first)))
            first = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
 
          /* Copy the args if needed.  */
@@ -1003,7 +1005,7 @@ struct gimple_opt_pass pass_tail_recursion =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
+  TV_NONE,                             /* tv_id */
   PROP_cfg | PROP_ssa,                 /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
@@ -1022,8 +1024,8 @@ struct gimple_opt_pass pass_tail_calls =
   NULL,                                        /* sub */
   NULL,                                        /* next */
   0,                                   /* static_pass_number */
-  0,                                   /* tv_id */
-  PROP_cfg | PROP_ssa | PROP_alias,    /* properties_required */
+  TV_NONE,                             /* tv_id */
+  PROP_cfg | PROP_ssa,                 /* properties_required */
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */