OSDN Git Service

* stor-layout.c (layout_type): Don't complain about a too small
[pf3gnuchains/gcc-fork.git] / gcc / tree-tailcall.c
index 613841e..c5a2527 100644 (file)
@@ -132,20 +132,20 @@ static void find_tail_calls (basic_block, struct tailcall **);
 static bool
 suitable_for_tail_opt_p (void)
 {
-  int i;
+  referenced_var_iterator rvi;
+  tree var;
 
   if (current_function_stdarg)
     return false;
 
   /* No local variable nor structure field should be call-clobbered.  We
      ignore any kind of memory tag, as these are not real variables.  */
-  for (i = 0; i < (int) num_referenced_vars; i++)
+
+  FOR_EACH_REFERENCED_VAR (var, rvi)
     {
-      tree var = VEC_index (tree, referenced_vars, i);
 
-      if (!(TREE_STATIC (var) || DECL_EXTERNAL (var))
-         && (var_ann (var)->mem_tag_kind == NOT_A_TAG
-             || var_ann (var)->mem_tag_kind == STRUCT_FIELD)
+      if (!is_global_var (var)
+         && (!MTAG_P (var) || TREE_CODE (var) == STRUCT_FIELD_TAG)
          && is_call_clobbered (var))
        return false;
     }
@@ -191,7 +191,7 @@ suitable_for_tail_call_opt_p (void)
 }
 
 /* Checks whether the expression EXPR in stmt AT is independent of the
-   statement pointed by BSI (in a sense that we already know EXPR's value
+   statement pointed to by BSI (in a sense that we already know EXPR's value
    at BSI).  We use the fact that we are only called from the chain of
    basic blocks that have only single successor.  Returns the expression
    containing the value of EXPR at BSI.  */
@@ -558,8 +558,8 @@ adjust_accumulator_values (block_stmt_iterator bsi, tree m, tree a, edge back)
            var = m_acc;
          else
            {
-             stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
-                           build (MULT_EXPR, ret_type, m_acc, a));
+             stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+                            build2 (MULT_EXPR, ret_type, m_acc, a));
 
              tmp = create_tmp_var (ret_type, "acc_tmp");
              add_referenced_tmp_var (tmp);
@@ -572,8 +572,8 @@ adjust_accumulator_values (block_stmt_iterator bsi, tree m, tree a, edge back)
       else
        var = a;
 
-      stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
-                   build (PLUS_EXPR, ret_type, a_acc, var));
+      stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+                    build2 (PLUS_EXPR, ret_type, a_acc, var));
       var = make_ssa_name (SSA_NAME_VAR (a_acc), stmt);
       TREE_OPERAND (stmt, 0) = var;
       bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
@@ -582,8 +582,8 @@ adjust_accumulator_values (block_stmt_iterator bsi, tree m, tree a, edge back)
 
   if (m)
     {
-      stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
-                   build (MULT_EXPR, ret_type, m_acc, m));
+      stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+                    build2 (MULT_EXPR, ret_type, m_acc, m));
       var = make_ssa_name (SSA_NAME_VAR (m_acc), stmt);
       TREE_OPERAND (stmt, 0) = var;
       bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
@@ -637,8 +637,8 @@ adjust_return_value (basic_block bb, tree m, tree a)
 
   if (m)
     {
-      stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
-                   build (MULT_EXPR, ret_type, m_acc, ret_var));
+      stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+                    build2 (MULT_EXPR, ret_type, m_acc, ret_var));
 
       tmp = create_tmp_var (ret_type, "acc_tmp");
       add_referenced_tmp_var (tmp);
@@ -652,8 +652,8 @@ adjust_return_value (basic_block bb, tree m, tree a)
 
   if (a)
     {
-      stmt = build (MODIFY_EXPR, ret_type, NULL_TREE,
-                   build (PLUS_EXPR, ret_type, a_acc, var));
+      stmt = build2 (MODIFY_EXPR, ret_type, NULL_TREE,
+                    build2 (PLUS_EXPR, ret_type, a_acc, var));
 
       tmp = create_tmp_var (ret_type, "acc_tmp");
       add_referenced_tmp_var (tmp);
@@ -667,6 +667,29 @@ adjust_return_value (basic_block bb, tree m, tree a)
   update_stmt (ret_stmt);
 }
 
+/* Subtract COUNT and FREQUENCY from the basic block and it's
+   outgoing edge.  */
+static void
+decrease_profile (basic_block bb, gcov_type count, int frequency)
+{
+  edge e;
+  bb->count -= count;
+  if (bb->count < 0)
+    bb->count = 0;
+  bb->frequency -= frequency;
+  if (bb->frequency < 0)
+    bb->frequency = 0;
+  if (!single_succ_p (bb))
+    {
+      gcc_assert (!EDGE_COUNT (bb->succs));
+      return;
+    }
+  e = single_succ_edge (bb);
+  e->count -= count;
+  if (e->count < 0)
+    e->count = 0;
+}
+
 /* Eliminates tail call described by T.  TMP_VARS is a list of
    temporary variables used to copy the function arguments.  */
 
@@ -716,6 +739,13 @@ eliminate_tail_call (struct tailcall *t)
       release_defs (t);
     }
 
+  /* Number of executions of function has reduced by the tailcall.  */
+  e = single_succ_edge (t->call_block);
+  decrease_profile (EXIT_BLOCK_PTR, e->count, EDGE_FREQUENCY (e));
+  decrease_profile (ENTRY_BLOCK_PTR, e->count, EDGE_FREQUENCY (e));
+  if (e->dest != EXIT_BLOCK_PTR)
+    decrease_profile (e->dest, e->count, EDGE_FREQUENCY (e));
+
   /* Replace the call by a jump to the start of function.  */
   e = redirect_edge_and_branch (single_succ_edge (t->call_block), first);
   gcc_assert (e);
@@ -755,7 +785,7 @@ eliminate_tail_call (struct tailcall *t)
 
       if (!phi)
        {
-         tree name = var_ann (param)->default_def;
+         tree name = default_def (param);
          tree new_name;
 
          if (!name)
@@ -768,7 +798,7 @@ eliminate_tail_call (struct tailcall *t)
            }
          new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
 
-         var_ann (param)->default_def = new_name;
+         set_default_def (param, new_name);
          phi = create_phi_node (name, first);
          SSA_NAME_DEF_STMT (name) = phi;
          add_phi_arg (phi, new_name, single_succ_edge (ENTRY_BLOCK_PTR));
@@ -867,6 +897,7 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
 
       if (!phis_constructed)
        {
+         tree name;
          /* Ensure that there is only one predecessor of the block.  */
          if (!single_pred_p (first))
            first = split_edge (single_succ_edge (ENTRY_BLOCK_PTR));
@@ -879,14 +910,13 @@ tree_optimize_tail_calls_1 (bool opt_tailcalls)
                && var_ann (param)
                /* Also parameters that are only defined but never used need not
                   be copied.  */
-               && (var_ann (param)->default_def
-                   && TREE_CODE (var_ann (param)->default_def) == SSA_NAME))
+               && ((name = default_def (param))
+                   && TREE_CODE (name) == SSA_NAME))
            {
-             tree name = var_ann (param)->default_def;
              tree new_name = make_ssa_name (param, SSA_NAME_DEF_STMT (name));
              tree phi;
 
-             var_ann (param)->default_def = new_name;
+             set_default_def (param, new_name);
              phi = create_phi_node (name, first);
              SSA_NAME_DEF_STMT (name) = phi;
              add_phi_arg (phi, new_name, single_pred_edge (first));