diff gcc/value-prof.c @ 67:f6334be47118

update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 22 Mar 2011 17:18:12 +0900
parents b7f97abdc517
children 04ced10e8804
line wrap: on
line diff
--- a/gcc/value-prof.c	Tue May 25 18:58:51 2010 +0900
+++ b/gcc/value-prof.c	Tue Mar 22 17:18:12 2011 +0900
@@ -1,5 +1,5 @@
 /* Transformations based on profile information for values.
-   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.
@@ -45,11 +45,8 @@
 #include "cgraph.h"
 #include "timevar.h"
 #include "tree-pass.h"
-#include "toplev.h"
 #include "pointer-set.h"
 
-static struct value_prof_hooks *value_prof_hooks;
-
 /* In this file value profile based optimizations are placed.  Currently the
    following optimizations are implemented (for more detailed descriptions
    see comments at value_profile_transformations):
@@ -375,7 +372,7 @@
   histogram_value hist = *(histogram_value *) slot;
   if (!pointer_set_contains (visited, hist))
     {
-      error ("Dead histogram");
+      error ("dead histogram");
       dump_histogram_value (stderr, hist);
       debug_gimple_stmt (hist->hvalue.stmt);
       error_found = true;
@@ -386,7 +383,7 @@
 
 /* Verify sanity of the histograms.  */
 
-void
+DEBUG_FUNCTION void
 verify_histograms (void)
 {
   basic_block bb;
@@ -466,7 +463,7 @@
               : DECL_SOURCE_LOCATION (current_function_decl);
       if (flag_profile_correction)
         {
-	  inform (locus, "Correcting inconsistent value profile: "
+	  inform (locus, "correcting inconsistent value profile: "
 		  "%s profiler overall count (%d) does not match BB count "
                   "(%d)", name, (int)*all, (int)bb_count);
 	  *all = bb_count;
@@ -476,9 +473,13 @@
 	}
       else
 	{
-	  error_at (locus, "Corrupted value profile: %s "
-		    "profiler overall count (%d) does not match BB count (%d)",
-		    name, (int)*all, (int)bb_count);
+	  error_at (locus, "corrupted value profile: %s "
+		    "profile counter (%d out of %d) inconsistent with "
+		    "basic-block count (%d)",
+		    name,
+		    (int) *count,
+		    (int) *all,
+		    (int) bb_count);
 	  return true;
 	}
     }
@@ -489,7 +490,7 @@
 
 /* GIMPLE based transformations. */
 
-static bool
+bool
 gimple_value_profile_transformations (void)
 {
   basic_block bb;
@@ -558,7 +559,7 @@
 			   gcov_type all)
 {
   gimple stmt1, stmt2, stmt3;
-  tree tmp1, tmp2, tmpv;
+  tree tmp0, tmp1, tmp2, tmpv;
   gimple bb1end, bb2end, bb3end;
   basic_block bb, bb2, bb3, bb4;
   tree optype, op1, op2;
@@ -576,19 +577,22 @@
   bb = gimple_bb (stmt);
   gsi = gsi_for_stmt (stmt);
 
-  tmpv = create_tmp_var (optype, "PROF");
-  tmp1 = create_tmp_var (optype, "PROF");
-  stmt1 = gimple_build_assign (tmpv, fold_convert (optype, value));
+  tmpv = create_tmp_reg (optype, "PROF");
+  tmp0 = make_ssa_name (tmpv, NULL);
+  tmp1 = make_ssa_name (tmpv, NULL);
+  stmt1 = gimple_build_assign (tmp0, fold_convert (optype, value));
+  SSA_NAME_DEF_STMT (tmp0) = stmt1;
   stmt2 = gimple_build_assign (tmp1, op2);
-  stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
+  SSA_NAME_DEF_STMT (tmp1) = stmt2;
+  stmt3 = gimple_build_cond (NE_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
   gsi_insert_before (&gsi, stmt3, GSI_SAME_STMT);
   bb1end = stmt3;
 
-  tmp2 = create_tmp_var (optype, "PROF");
+  tmp2 = make_rename_temp (optype, "PROF");
   stmt1 = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt), tmp2,
-					op1, tmpv);
+					op1, tmp0);
   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
   bb2end = stmt1;
 
@@ -699,6 +703,7 @@
     }
 
   gimple_assign_set_rhs_from_tree (si, result);
+  update_stmt (gsi_stmt (*si));
 
   return true;
 }
@@ -711,7 +716,7 @@
 gimple_mod_pow2 (gimple stmt, int prob, gcov_type count, gcov_type all)
 {
   gimple stmt1, stmt2, stmt3, stmt4;
-  tree tmp2, tmp3;
+  tree tmp2, tmp3, tmpv;
   gimple bb1end, bb2end, bb3end;
   basic_block bb, bb2, bb3, bb4;
   tree optype, op1, op2;
@@ -729,12 +734,15 @@
   bb = gimple_bb (stmt);
   gsi = gsi_for_stmt (stmt);
 
-  result = create_tmp_var (optype, "PROF");
-  tmp2 = create_tmp_var (optype, "PROF");
-  tmp3 = create_tmp_var (optype, "PROF");
+  result = make_rename_temp (optype, "PROF");
+  tmpv = create_tmp_var (optype, "PROF");
+  tmp2 = make_ssa_name (tmpv, NULL);
+  tmp3 = make_ssa_name (tmpv, NULL);
   stmt2 = gimple_build_assign_with_ops (PLUS_EXPR, tmp2, op2,
 					build_int_cst (optype, -1));
+  SSA_NAME_DEF_STMT (tmp2) = stmt2;
   stmt3 = gimple_build_assign_with_ops (BIT_AND_EXPR, tmp3, tmp2, op2);
+  SSA_NAME_DEF_STMT (tmp3) = stmt3;
   stmt4 = gimple_build_cond (NE_EXPR, tmp3, build_int_cst (optype, 0),
 			     NULL_TREE, NULL_TREE);
   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
@@ -845,6 +853,7 @@
   result = gimple_mod_pow2 (stmt, prob, count, all);
 
   gimple_assign_set_rhs_from_tree (si, result);
+  update_stmt (gsi_stmt (*si));
 
   return true;
 }
@@ -881,10 +890,11 @@
   bb = gimple_bb (stmt);
   gsi = gsi_for_stmt (stmt);
 
-  result = create_tmp_var (optype, "PROF");
-  tmp1 = create_tmp_var (optype, "PROF");
+  result = make_rename_temp (optype, "PROF");
+  tmp1 = make_ssa_name (create_tmp_var (optype, "PROF"), NULL);
   stmt1 = gimple_build_assign (result, op1);
   stmt2 = gimple_build_assign (tmp1, op2);
+  SSA_NAME_DEF_STMT (tmp1) = stmt2;
   stmt3 = gimple_build_cond (LT_EXPR, result, tmp1, NULL_TREE, NULL_TREE);
   gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
   gsi_insert_before (&gsi, stmt2, GSI_SAME_STMT);
@@ -1044,6 +1054,7 @@
   result = gimple_mod_subtract (stmt, prob1, prob2, i, count1, count2, all);
 
   gimple_assign_set_rhs_from_tree (si, result);
+  update_stmt (gsi_stmt (*si));
 
   return true;
 }
@@ -1092,7 +1103,7 @@
 	   int prob, gcov_type count, gcov_type all)
 {
   gimple dcall_stmt, load_stmt, cond_stmt;
-  tree tmp1, tmpv, tmp;
+  tree tmp0, tmp1, tmpv, tmp;
   basic_block cond_bb, dcall_bb, icall_bb, join_bb;
   tree optype = build_pointer_type (void_type_node);
   edge e_cd, e_ci, e_di, e_dj, e_ij;
@@ -1102,20 +1113,26 @@
   cond_bb = gimple_bb (icall_stmt);
   gsi = gsi_for_stmt (icall_stmt);
 
-  tmpv = create_tmp_var (optype, "PROF");
-  tmp1 = create_tmp_var (optype, "PROF");
+  tmpv = create_tmp_reg (optype, "PROF");
+  tmp0 = make_ssa_name (tmpv, NULL);
+  tmp1 = make_ssa_name (tmpv, NULL);
   tmp = unshare_expr (gimple_call_fn (icall_stmt));
-  load_stmt = gimple_build_assign (tmpv, tmp);
+  load_stmt = gimple_build_assign (tmp0, tmp);
+  SSA_NAME_DEF_STMT (tmp0) = load_stmt;
   gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
 
   tmp = fold_convert (optype, build_addr (direct_call->decl,
 					  current_function_decl));
   load_stmt = gimple_build_assign (tmp1, tmp);
+  SSA_NAME_DEF_STMT (tmp1) = load_stmt;
   gsi_insert_before (&gsi, load_stmt, GSI_SAME_STMT);
 
-  cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
+  cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
   gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
 
+  gimple_set_vdef (icall_stmt, NULL_TREE);
+  gimple_set_vuse (icall_stmt, NULL_TREE);
+  update_stmt (icall_stmt);
   dcall_stmt = gimple_copy (icall_stmt);
   gimple_call_set_fndecl (dcall_stmt, direct_call->decl);
   gsi_insert_before (&gsi, dcall_stmt, GSI_SAME_STMT);
@@ -1130,7 +1147,16 @@
   icall_bb = e_di->dest;
   icall_bb->count = all - count;
 
-  e_ij = split_block (icall_bb, icall_stmt);
+  /* Do not disturb existing EH edges from the indirect call.  */
+  if (!stmt_ends_bb_p (icall_stmt))
+    e_ij = split_block (icall_bb, icall_stmt);
+  else
+    {
+      e_ij = find_fallthru_edge (icall_bb->succs);
+      e_ij->probability = REG_BR_PROB_BASE;
+      e_ij->count = all - count;
+      e_ij = single_pred_edge (split_edge (e_ij));
+    }
   join_bb = e_ij->dest;
   join_bb->count = all;
 
@@ -1151,21 +1177,42 @@
   e_ij->probability = REG_BR_PROB_BASE;
   e_ij->count = all - count;
 
-  /* Fix eh edges */
+  /* Insert PHI node for the call result if necessary.  */
+  if (gimple_call_lhs (icall_stmt)
+      && TREE_CODE (gimple_call_lhs (icall_stmt)) == SSA_NAME)
+    {
+      tree result = gimple_call_lhs (icall_stmt);
+      gimple phi = create_phi_node (result, join_bb);
+      SSA_NAME_DEF_STMT (result) = phi;
+      gimple_call_set_lhs (icall_stmt,
+			   make_ssa_name (SSA_NAME_VAR (result), icall_stmt));
+      add_phi_arg (phi, gimple_call_lhs (icall_stmt), e_ij, UNKNOWN_LOCATION);
+      gimple_call_set_lhs (dcall_stmt,
+			   make_ssa_name (SSA_NAME_VAR (result), dcall_stmt));
+      add_phi_arg (phi, gimple_call_lhs (dcall_stmt), e_dj, UNKNOWN_LOCATION);
+    }
+
+  /* Build an EH edge for the direct call if necessary.  */
   lp_nr = lookup_stmt_eh_lp (icall_stmt);
-  if (lp_nr != 0)
+  if (lp_nr != 0
+      && stmt_could_throw_p (dcall_stmt))
     {
-      if (stmt_could_throw_p (dcall_stmt))
+      edge e_eh, e;
+      edge_iterator ei;
+      gimple_stmt_iterator psi;
+
+      add_stmt_to_eh_lp (dcall_stmt, lp_nr);
+      FOR_EACH_EDGE (e_eh, ei, icall_bb->succs)
+	if (e_eh->flags & EDGE_EH)
+	  break;
+      e = make_edge (dcall_bb, e_eh->dest, EDGE_EH);
+      for (psi = gsi_start_phis (e_eh->dest);
+	   !gsi_end_p (psi); gsi_next (&psi))
 	{
-	  add_stmt_to_eh_lp (dcall_stmt, lp_nr);
-	  make_eh_edges (dcall_stmt);
+	  gimple phi = gsi_stmt (psi);
+	  SET_USE (PHI_ARG_DEF_PTR_FROM_EDGE (phi, e),
+		   PHI_ARG_DEF_FROM_EDGE (phi, e_eh));
 	}
-
-      gcc_assert (stmt_could_throw_p (icall_stmt));
-      make_eh_edges (icall_stmt);
-
-      /* The old EH edges are sill on the join BB, purge them.  */
-      gimple_purge_dead_eh_edges (join_bb);
     }
 
   return dcall_stmt;
@@ -1289,7 +1336,7 @@
 			     gcov_type count, gcov_type all)
 {
   gimple tmp_stmt, cond_stmt, icall_stmt;
-  tree tmp1, tmpv, vcall_size, optype;
+  tree tmp0, tmp1, tmpv, vcall_size, optype;
   basic_block cond_bb, icall_bb, vcall_bb, join_bb;
   edge e_ci, e_cv, e_iv, e_ij, e_vj;
   gimple_stmt_iterator gsi;
@@ -1307,16 +1354,22 @@
   optype = TREE_TYPE (vcall_size);
 
   tmpv = create_tmp_var (optype, "PROF");
-  tmp1 = create_tmp_var (optype, "PROF");
-  tmp_stmt = gimple_build_assign (tmpv, fold_convert (optype, icall_size));
+  tmp0 = make_ssa_name (tmpv, NULL);
+  tmp1 = make_ssa_name (tmpv, NULL);
+  tmp_stmt = gimple_build_assign (tmp0, fold_convert (optype, icall_size));
+  SSA_NAME_DEF_STMT (tmp0) = tmp_stmt;
   gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
 
   tmp_stmt = gimple_build_assign (tmp1, vcall_size);
+  SSA_NAME_DEF_STMT (tmp1) = tmp_stmt;
   gsi_insert_before (&gsi, tmp_stmt, GSI_SAME_STMT);
 
-  cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmpv, NULL_TREE, NULL_TREE);
+  cond_stmt = gimple_build_cond (EQ_EXPR, tmp1, tmp0, NULL_TREE, NULL_TREE);
   gsi_insert_before (&gsi, cond_stmt, GSI_SAME_STMT);
 
+  gimple_set_vdef (vcall_stmt, NULL);
+  gimple_set_vuse (vcall_stmt, NULL);
+  update_stmt (vcall_stmt);
   icall_stmt = gimple_copy (vcall_stmt);
   gimple_call_set_arg (icall_stmt, size_arg, icall_size);
   gsi_insert_before (&gsi, icall_stmt, GSI_SAME_STMT);
@@ -1352,6 +1405,21 @@
   e_vj->probability = REG_BR_PROB_BASE;
   e_vj->count = all - count;
 
+  /* Insert PHI node for the call result if necessary.  */
+  if (gimple_call_lhs (vcall_stmt)
+      && TREE_CODE (gimple_call_lhs (vcall_stmt)) == SSA_NAME)
+    {
+      tree result = gimple_call_lhs (vcall_stmt);
+      gimple phi = create_phi_node (result, join_bb);
+      SSA_NAME_DEF_STMT (result) = phi;
+      gimple_call_set_lhs (vcall_stmt,
+			   make_ssa_name (SSA_NAME_VAR (result), vcall_stmt));
+      add_phi_arg (phi, gimple_call_lhs (vcall_stmt), e_vj, UNKNOWN_LOCATION);
+      gimple_call_set_lhs (icall_stmt,
+			   make_ssa_name (SSA_NAME_VAR (result), icall_stmt));
+      add_phi_arg (phi, gimple_call_lhs (icall_stmt), e_ij, UNKNOWN_LOCATION);
+    }
+
   /* Because these are all string op builtins, they're all nothrow.  */
   gcc_assert (!stmt_could_throw_p (vcall_stmt));
   gcc_assert (!stmt_could_throw_p (icall_stmt));
@@ -1494,14 +1562,6 @@
     }
 }
 
-struct value_prof_hooks {
-  /* Find list of values for which we want to measure histograms.  */
-  void (*find_values_to_profile) (histogram_values *);
-
-  /* Identify and exploit properties of values that are hard to analyze
-     statically.  See value-prof.c for more detail.  */
-  bool (*value_profile_transformations) (void);
-};
 
 /* Find values inside STMT for that we want to measure histograms for
    division/modulo optimization.  */
@@ -1635,7 +1695,7 @@
     }
 }
 
-static void
+void
 gimple_find_values_to_profile (histogram_values *values)
 {
   basic_block bb;
@@ -1648,7 +1708,7 @@
     for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
       gimple_values_to_profile (gsi_stmt (gsi), values);
 
-  for (i = 0; VEC_iterate (histogram_value, *values, i, hist); i++)
+  FOR_EACH_VEC_ELT (histogram_value, *values, i, hist)
     {
       switch (hist->type)
         {
@@ -1692,28 +1752,3 @@
     }
 }
 
-static struct value_prof_hooks gimple_value_prof_hooks = {
-  gimple_find_values_to_profile,
-  gimple_value_profile_transformations
-};
-
-void
-gimple_register_value_prof_hooks (void)
-{
-  gcc_assert (current_ir_type () == IR_GIMPLE);
-  value_prof_hooks = &gimple_value_prof_hooks;
-}
-
-/* IR-independent entry points.  */
-void
-find_values_to_profile (histogram_values *values)
-{
-  (value_prof_hooks->find_values_to_profile) (values);
-}
-
-bool
-value_profile_transformations (void)
-{
-  return (value_prof_hooks->value_profile_transformations) ();
-}
-