OSDN Git Service

* reorg.c (mostly_true_jump): Clean up code depending on
[pf3gnuchains/gcc-fork.git] / gcc / tree-tailcall.c
index 3a40a61..c5a2527 100644 (file)
@@ -144,9 +144,8 @@ suitable_for_tail_opt_p (void)
   FOR_EACH_REFERENCED_VAR (var, rvi)
     {
 
-      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;
     }
@@ -192,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.  */
@@ -559,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);
@@ -573,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);
@@ -583,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);
@@ -638,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);
@@ -653,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);
@@ -668,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.  */
 
@@ -717,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);