OSDN Git Service

2008-06-15 Mark Shinwell <shinwell@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / value-prof.c
index b03e677..38ed8b2 100644 (file)
@@ -1,11 +1,12 @@
 /* Transformations based on profile information for values.
 /* Transformations based on profile information for values.
-   Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Free Software
+   Foundation, Inc.
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
 
 This file is part of GCC.
 
 GCC is free software; you can redistribute it and/or modify it under
 the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 2, or (at your option) any later
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -14,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
 for more details.
 
 You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
@@ -107,7 +107,7 @@ gimple_alloc_histogram_value (struct function *fun ATTRIBUTE_UNUSED,
 static hashval_t
 histogram_hash (const void *x)
 {
 static hashval_t
 histogram_hash (const void *x)
 {
-  return htab_hash_pointer (((histogram_value)x)->hvalue.stmt);
+  return htab_hash_pointer (((const_histogram_value)x)->hvalue.stmt);
 }
 
 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y.  */
 }
 
 /* Return nonzero if decl_id of die_struct X is the same as UID of decl *Y.  */
@@ -115,7 +115,7 @@ histogram_hash (const void *x)
 static int
 histogram_eq (const void *x, const void *y)
 {
 static int
 histogram_eq (const void *x, const void *y)
 {
-  return ((histogram_value) x)->hvalue.stmt == (tree)y;
+  return ((const_histogram_value) x)->hvalue.stmt == (const_tree)y;
 }
 
 /* Set histogram for STMT.  */
 }
 
 /* Set histogram for STMT.  */
@@ -337,6 +337,25 @@ gimple_duplicate_stmt_histograms (struct function *fun, tree stmt,
     }
 }
 
     }
 }
 
+
+/* Move all histograms associated with OSTMT to STMT.  */
+
+void
+gimple_move_stmt_histograms (struct function *fun, tree stmt, tree ostmt)
+{
+  histogram_value val = gimple_histogram_value (fun, ostmt);
+  if (val)
+    {
+      /* The following three statements can't be reordered,
+         because histogram hashtab relies on stmt field value
+        for finding the exact slot. */
+      set_histogram_value (fun, ostmt, NULL);
+      for (; val != NULL; val = val->hvalue.next)
+       val->hvalue.stmt = stmt;
+      set_histogram_value (fun, stmt, val);
+    }
+}
+
 static bool error_found = false;
 
 /* Helper function for verify_histograms.  For each histogram reachable via htab
 static bool error_found = false;
 
 /* Helper function for verify_histograms.  For each histogram reachable via htab
@@ -354,7 +373,7 @@ visit_hist (void **slot, void *data)
       debug_generic_stmt (hist->hvalue.stmt);
       error_found = true;
     }
       debug_generic_stmt (hist->hvalue.stmt);
       error_found = true;
     }
-  return 0;
+  return 1;
 }
 
 /* Verify sanity of the histograms.  */
 }
 
 /* Verify sanity of the histograms.  */
@@ -406,7 +425,7 @@ free_hist (void **slot, void *data ATTRIBUTE_UNUSED)
   memset (hist, 0xab, sizeof (*hist));
 #endif
   free (hist);
   memset (hist, 0xab, sizeof (*hist));
 #endif
   free (hist);
-  return 0;
+  return 1;
 }
 
 void
 }
 
 void
@@ -523,13 +542,11 @@ tree_divmod_fixed_value (tree stmt, tree operation,
 
   tmpv = create_tmp_var (optype, "PROF");
   tmp1 = create_tmp_var (optype, "PROF");
 
   tmpv = create_tmp_var (optype, "PROF");
   tmp1 = create_tmp_var (optype, "PROF");
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmpv,
-                 fold_convert (optype, value));
-  stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1, op2);
+  stmt1 = build_gimple_modify_stmt (tmpv, fold_convert (optype, value));
+  stmt2 = build_gimple_modify_stmt (tmp1, op2);
   stmt3 = build3 (COND_EXPR, void_type_node,
            build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
   stmt3 = build3 (COND_EXPR, void_type_node,
            build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
-           build1 (GOTO_EXPR, void_type_node, label_decl2),
-           build1 (GOTO_EXPR, void_type_node, label_decl1));
+           NULL_TREE, NULL_TREE);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
@@ -537,15 +554,17 @@ tree_divmod_fixed_value (tree stmt, tree operation,
 
   tmp2 = create_tmp_var (optype, "PROF");
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
 
   tmp2 = create_tmp_var (optype, "PROF");
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmp2,
-                 build2 (TREE_CODE (operation), optype, op1, tmpv));
+  stmt1 = build_gimple_modify_stmt (tmp2,
+                                   build2 (TREE_CODE (operation), optype,
+                                           op1, tmpv));
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb2end = stmt1;
 
   label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb2end = stmt1;
 
   label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmp2,
-                 build2 (TREE_CODE (operation), optype, op1, op2));
+  stmt1 = build_gimple_modify_stmt (tmp2,
+                                   build2 (TREE_CODE (operation), optype,
+                                           op1, op2));
   bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb3end = stmt1;
   bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb3end = stmt1;
@@ -591,7 +610,7 @@ tree_divmod_fixed_value_transform (tree stmt)
   enum tree_code code;
   gcov_type val, count, all;
   tree modify, op, op1, op2, result, value, tree_val;
   enum tree_code code;
   gcov_type val, count, all;
   tree modify, op, op1, op2, result, value, tree_val;
-  int prob;
+  gcov_type prob;
 
   modify = stmt;
   if (TREE_CODE (stmt) == RETURN_EXPR
 
   modify = stmt;
   if (TREE_CODE (stmt) == RETURN_EXPR
@@ -632,7 +651,10 @@ tree_divmod_fixed_value_transform (tree stmt)
     return false;
 
   /* Compute probability of taking the optimal path.  */
     return false;
 
   /* Compute probability of taking the optimal path.  */
-  prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+  if (all > 0)
+    prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+  else
+    prob = 0;
 
   tree_val = build_int_cst_wide (get_gcov_type (),
                                 (unsigned HOST_WIDE_INT) val,
 
   tree_val = build_int_cst_wide (get_gcov_type (),
                                 (unsigned HOST_WIDE_INT) val,
@@ -680,15 +702,15 @@ tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
 
   tmp2 = create_tmp_var (optype, "PROF");
   tmp3 = create_tmp_var (optype, "PROF");
 
   tmp2 = create_tmp_var (optype, "PROF");
   tmp3 = create_tmp_var (optype, "PROF");
-  stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp2, 
-                 build2 (PLUS_EXPR, optype, op2, build_int_cst (optype, -1)));
-  stmt3 = build2 (GIMPLE_MODIFY_STMT, optype, tmp3,
-                 build2 (BIT_AND_EXPR, optype, tmp2, op2));
+  stmt2 = build_gimple_modify_stmt (tmp2, 
+                                   build2 (PLUS_EXPR, optype, op2,
+                                           build_int_cst (optype, -1)));
+  stmt3 = build_gimple_modify_stmt (tmp3,
+                                   build2 (BIT_AND_EXPR, optype, tmp2, op2));
   stmt4 = build3 (COND_EXPR, void_type_node,
                  build2 (NE_EXPR, boolean_type_node,
                          tmp3, build_int_cst (optype, 0)),
   stmt4 = build3 (COND_EXPR, void_type_node,
                  build2 (NE_EXPR, boolean_type_node,
                          tmp3, build_int_cst (optype, 0)),
-                 build1 (GOTO_EXPR, void_type_node, label_decl2),
-                 build1 (GOTO_EXPR, void_type_node, label_decl1));
+                 NULL_TREE, NULL_TREE);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt4, BSI_SAME_STMT);
@@ -696,15 +718,16 @@ tree_mod_pow2 (tree stmt, tree operation, tree op1, tree op2, int prob,
 
   /* tmp2 == op2-1 inherited from previous block */
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
 
   /* tmp2 == op2-1 inherited from previous block */
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
-                 build2 (BIT_AND_EXPR, optype, op1, tmp2));
+  stmt1 = build_gimple_modify_stmt (result,
+                                   build2 (BIT_AND_EXPR, optype, op1, tmp2));
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb2end = stmt1;
 
   label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb2end = stmt1;
 
   label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
-                 build2 (TREE_CODE (operation), optype, op1, op2));
+  stmt1 = build_gimple_modify_stmt (result,
+                                   build2 (TREE_CODE (operation), optype,
+                                           op1, op2));
   bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb3end = stmt1;
   bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb3end = stmt1;
@@ -750,7 +773,7 @@ tree_mod_pow2_value_transform (tree stmt)
   enum tree_code code;
   gcov_type count, wrong_values, all;
   tree modify, op, op1, op2, result, value;
   enum tree_code code;
   gcov_type count, wrong_values, all;
   tree modify, op, op1, op2, result, value;
-  int prob;
+  gcov_type prob;
 
   modify = stmt;
   if (TREE_CODE (stmt) == RETURN_EXPR
 
   modify = stmt;
   if (TREE_CODE (stmt) == RETURN_EXPR
@@ -797,7 +820,10 @@ tree_mod_pow2_value_transform (tree stmt)
   if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
     return false;
 
   if (check_counter (stmt, "pow2", all, bb_for_stmt (stmt)->count))
     return false;
 
-  prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+  if (all > 0)
+    prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+  else
+    prob = 0;
 
   result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
 
 
   result = tree_mod_pow2 (stmt, op, op1, op2, prob, count, all);
 
@@ -838,13 +864,11 @@ tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
   bsi = bsi_for_stmt (stmt);
 
   tmp1 = create_tmp_var (optype, "PROF");
   bsi = bsi_for_stmt (stmt);
 
   tmp1 = create_tmp_var (optype, "PROF");
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result, op1);
-  stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1, op2);
+  stmt1 = build_gimple_modify_stmt (result, op1);
+  stmt2 = build_gimple_modify_stmt (tmp1, op2);
   stmt3 = build3 (COND_EXPR, void_type_node,
            build2 (LT_EXPR, boolean_type_node, result, tmp1),
   stmt3 = build3 (COND_EXPR, void_type_node,
            build2 (LT_EXPR, boolean_type_node, result, tmp1),
-           build1 (GOTO_EXPR, void_type_node, label_decl3),
-           build1 (GOTO_EXPR, void_type_node, 
-                   ncounts ? label_decl1 : label_decl2));
+           NULL_TREE, NULL_TREE);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
@@ -853,12 +877,12 @@ tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
   if (ncounts) /* Assumed to be 0 or 1 */
     {
       label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
   if (ncounts) /* Assumed to be 0 or 1 */
     {
       label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
-      stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
-                     build2 (MINUS_EXPR, optype, result, tmp1));
+      stmt1 = build_gimple_modify_stmt (result,
+                                       build2 (MINUS_EXPR, optype,
+                                               result, tmp1));
       stmt2 = build3 (COND_EXPR, void_type_node,
                build2 (LT_EXPR, boolean_type_node, result, tmp1),
       stmt2 = build3 (COND_EXPR, void_type_node,
                build2 (LT_EXPR, boolean_type_node, result, tmp1),
-               build1 (GOTO_EXPR, void_type_node, label_decl3),
-               build1 (GOTO_EXPR, void_type_node, label_decl2));
+               NULL_TREE, NULL_TREE);
       bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
       bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
       bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
       bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
       bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
       bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
@@ -867,8 +891,9 @@ tree_mod_subtract (tree stmt, tree operation, tree op1, tree op2,
 
   /* Fallback case. */
   label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
 
   /* Fallback case. */
   label2 = build1 (LABEL_EXPR, void_type_node, label_decl2);
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, result,
-                   build2 (TREE_CODE (operation), optype, result, tmp1));
+  stmt1 = build_gimple_modify_stmt (result,
+                                   build2 (TREE_CODE (operation), optype,
+                                           result, tmp1));
   bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb3end = stmt1;
   bsi_insert_before (&bsi, label2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb3end = stmt1;
@@ -930,7 +955,7 @@ tree_mod_subtract_transform (tree stmt)
   enum tree_code code;
   gcov_type count, wrong_values, all;
   tree modify, op, op1, op2, result, value;
   enum tree_code code;
   gcov_type count, wrong_values, all;
   tree modify, op, op1, op2, result, value;
-  int prob1, prob2;
+  gcov_type prob1, prob2;
   unsigned int i, steps;
   gcov_type count1, count2;
 
   unsigned int i, steps;
   gcov_type count1, count2;
 
@@ -997,8 +1022,15 @@ tree_mod_subtract_transform (tree stmt)
     }
 
   /* Compute probability of taking the optimal path(s).  */
     }
 
   /* Compute probability of taking the optimal path(s).  */
-  prob1 = (count1 * REG_BR_PROB_BASE + all / 2) / all;
-  prob2 = (count2 * REG_BR_PROB_BASE + all / 2) / all;
+  if (all > 0)
+    {
+      prob1 = (count1 * REG_BR_PROB_BASE + all / 2) / all;
+      prob2 = (count2 * REG_BR_PROB_BASE + all / 2) / all;
+    }
+  else
+    {
+      prob1 = prob2 = 0;
+    }
 
   /* In practice, "steps" is always 2.  This interface reflects this,
      and will need to be changed if "steps" can change.  */
 
   /* In practice, "steps" is always 2.  This interface reflects this,
      and will need to be changed if "steps" can change.  */
@@ -1044,7 +1076,7 @@ find_func_by_pid (int     pid)
 
 /* Do transformation
 
 
 /* Do transformation
 
-  if (actual_callee_addres == addres_of_most_common_function/method)
+  if (actual_callee_address == address_of_most_common_function/method)
     do direct call
   else
     old call
     do direct call
   else
     old call
@@ -1055,7 +1087,7 @@ tree_ic (tree stmt, tree call, struct cgraph_node* direct_call,
         int prob, gcov_type count, gcov_type all)
 {
   tree stmt1, stmt2, stmt3;
         int prob, gcov_type count, gcov_type all)
 {
   tree stmt1, stmt2, stmt3;
-  tree tmp1, tmpv;
+  tree tmp1, tmpv, tmp;
   tree label_decl1 = create_artificial_label ();
   tree label_decl2 = create_artificial_label ();
   tree label1, label2;
   tree label_decl1 = create_artificial_label ();
   tree label_decl2 = create_artificial_label ();
   tree label1, label2;
@@ -1072,15 +1104,14 @@ tree_ic (tree stmt, tree call, struct cgraph_node* direct_call,
 
   tmpv = create_tmp_var (optype, "PROF");
   tmp1 = create_tmp_var (optype, "PROF");
 
   tmpv = create_tmp_var (optype, "PROF");
   tmp1 = create_tmp_var (optype, "PROF");
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmpv, 
-                 unshare_expr (TREE_OPERAND (call, 0)));
-  stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1
-                 fold_convert (optype, build_addr (direct_call->decl, 
-                                                   current_function_decl)));
+  stmt1 = build_gimple_modify_stmt (tmpv, 
+                                   unshare_expr (CALL_EXPR_FN (call)));
+  tmp = fold_convert (optype, build_addr (direct_call->decl
+                                         current_function_decl));
+  stmt2 = build_gimple_modify_stmt (tmp1, tmp);
   stmt3 = build3 (COND_EXPR, void_type_node,
                  build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
   stmt3 = build3 (COND_EXPR, void_type_node,
                  build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
-                 build1 (GOTO_EXPR, void_type_node, label_decl2),
-                 build1 (GOTO_EXPR, void_type_node, label_decl1));
+                 NULL_TREE, NULL_TREE);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
@@ -1089,8 +1120,8 @@ tree_ic (tree stmt, tree call, struct cgraph_node* direct_call,
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
   stmt1 = unshare_expr (stmt);
   new_call = get_call_expr_in (stmt1);
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
   stmt1 = unshare_expr (stmt);
   new_call = get_call_expr_in (stmt1);
-  TREE_OPERAND (new_call, 0) = build_addr (direct_call->decl, 
-                                          current_function_decl);
+  CALL_EXPR_FN (new_call) = build_addr (direct_call->decl, 
+                                       current_function_decl);
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb2end = stmt1;
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bb2end = stmt1;
@@ -1156,7 +1187,7 @@ tree_ic_transform (tree stmt)
 {
   histogram_value histogram;
   gcov_type val, count, all;
 {
   histogram_value histogram;
   gcov_type val, count, all;
-  int prob;
+  gcov_type prob;
   tree call, callee, modify;
   struct cgraph_node *direct_call;
   
   tree call, callee, modify;
   struct cgraph_node *direct_call;
   
@@ -1165,7 +1196,7 @@ tree_ic_transform (tree stmt)
   if (!call || TREE_CODE (call) != CALL_EXPR)
     return false;
 
   if (!call || TREE_CODE (call) != CALL_EXPR)
     return false;
 
-  callee = TREE_OPERAND (call, 0);
+  callee = CALL_EXPR_FN (call);
 
   if (TREE_CODE (callee) == ADDR_EXPR)
     return false;
 
   if (TREE_CODE (callee) == ADDR_EXPR)
     return false;
@@ -1182,7 +1213,10 @@ tree_ic_transform (tree stmt)
   if (4 * count <= 3 * all)
     return false;
 
   if (4 * count <= 3 * all)
     return false;
 
-  prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+  if (all > 0)
+    prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+  else
+    prob = 0;
   direct_call = find_func_by_pid ((int)val);
 
   if (direct_call == NULL)
   direct_call = find_func_by_pid ((int)val);
 
   if (direct_call == NULL)
@@ -1200,37 +1234,39 @@ tree_ic_transform (tree stmt)
       print_generic_stmt (dump_file, stmt, TDF_SLIM);
       fprintf (dump_file, " to ");
       print_generic_stmt (dump_file, modify, TDF_SLIM);
       print_generic_stmt (dump_file, stmt, TDF_SLIM);
       fprintf (dump_file, " to ");
       print_generic_stmt (dump_file, modify, TDF_SLIM);
+      fprintf (dump_file, "hist->count "HOST_WIDEST_INT_PRINT_DEC
+              " hist->all "HOST_WIDEST_INT_PRINT_DEC"\n", count, all);
     }
 
   return true;
 }
 
     }
 
   return true;
 }
 
-/* Return true if the stringop FNDECL with ARGLIST shall be profiled.  */
+/* Return true if the stringop CALL with FNDECL shall be profiled.  */
 static bool
 static bool
-interesting_stringop_to_profile_p (tree fndecl, tree arglist)
+interesting_stringop_to_profile_p (tree fndecl, tree call)
 {
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
 
 {
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
 
-  if (fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_MEMCPY
-      && fcode != BUILT_IN_BZERO)
+  if (fcode != BUILT_IN_MEMCPY && fcode != BUILT_IN_MEMPCPY
+      && fcode != BUILT_IN_MEMSET && fcode != BUILT_IN_BZERO)
     return false;
 
   switch (fcode)
     {
      case BUILT_IN_MEMCPY:
      case BUILT_IN_MEMPCPY:
     return false;
 
   switch (fcode)
     {
      case BUILT_IN_MEMCPY:
      case BUILT_IN_MEMPCPY:
-       return validate_arglist (arglist,
-                                POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
-                                VOID_TYPE);
+       return validate_arglist (call,
+                               POINTER_TYPE, POINTER_TYPE, INTEGER_TYPE,
+                               VOID_TYPE);
      case BUILT_IN_MEMSET:
      case BUILT_IN_MEMSET:
-       return validate_arglist (arglist,
-                                POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
-                                VOID_TYPE);
+       return validate_arglist (call,
+                               POINTER_TYPE, INTEGER_TYPE, INTEGER_TYPE,
+                               VOID_TYPE);
      case BUILT_IN_BZERO:
      case BUILT_IN_BZERO:
-        return validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE,
-                                VOID_TYPE);
+       return validate_arglist (call, POINTER_TYPE, INTEGER_TYPE,
+                               VOID_TYPE);
      default:
      default:
-       gcc_unreachable ();
+       gcc_unreachable ();
     }
 }
 
     }
 }
 
@@ -1256,8 +1292,7 @@ tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count,
   edge e12, e13, e23, e24, e34;
   block_stmt_iterator bsi;
   tree call = get_call_expr_in (stmt);
   edge e12, e13, e23, e24, e34;
   block_stmt_iterator bsi;
   tree call = get_call_expr_in (stmt);
-  tree arglist = TREE_OPERAND (call, 1);
-  tree blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+  tree blck_size = CALL_EXPR_ARG (call, 2);
   tree optype = TREE_TYPE (blck_size);
   int region;
 
   tree optype = TREE_TYPE (blck_size);
   int region;
 
@@ -1280,13 +1315,11 @@ tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count,
 
   tmpv = create_tmp_var (optype, "PROF");
   tmp1 = create_tmp_var (optype, "PROF");
 
   tmpv = create_tmp_var (optype, "PROF");
   tmp1 = create_tmp_var (optype, "PROF");
-  stmt1 = build2 (GIMPLE_MODIFY_STMT, optype, tmpv,
-                 fold_convert (optype, value));
-  stmt2 = build2 (GIMPLE_MODIFY_STMT, optype, tmp1, blck_size);
+  stmt1 = build_gimple_modify_stmt (tmpv, fold_convert (optype, value));
+  stmt2 = build_gimple_modify_stmt (tmp1, blck_size);
   stmt3 = build3 (COND_EXPR, void_type_node,
            build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
   stmt3 = build3 (COND_EXPR, void_type_node,
            build2 (NE_EXPR, boolean_type_node, tmp1, tmpv),
-           build1 (GOTO_EXPR, void_type_node, label_decl2),
-           build1 (GOTO_EXPR, void_type_node, label_decl1));
+           NULL_TREE, NULL_TREE);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt2, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt3, BSI_SAME_STMT);
@@ -1295,8 +1328,7 @@ tree_stringop_fixed_value (tree stmt, tree value, int prob, gcov_type count,
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
   stmt1 = unshare_expr (stmt);
   call = get_call_expr_in (stmt1);
   label1 = build1 (LABEL_EXPR, void_type_node, label_decl1);
   stmt1 = unshare_expr (stmt);
   call = get_call_expr_in (stmt1);
-  arglist = TREE_OPERAND (call, 1);
-  TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist))) = value;
+  CALL_EXPR_ARG (call, 2) = value;
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   region = lookup_stmt_eh_region (stmt);
   bsi_insert_before (&bsi, label1, BSI_SAME_STMT);
   bsi_insert_before (&bsi, stmt1, BSI_SAME_STMT);
   region = lookup_stmt_eh_region (stmt);
@@ -1342,7 +1374,6 @@ tree_stringops_transform (block_stmt_iterator *bsi)
   tree stmt = bsi_stmt (*bsi);
   tree call = get_call_expr_in (stmt);
   tree fndecl;
   tree stmt = bsi_stmt (*bsi);
   tree call = get_call_expr_in (stmt);
   tree fndecl;
-  tree arglist;
   tree blck_size;
   enum built_in_function fcode;
   histogram_value histogram;
   tree blck_size;
   enum built_in_function fcode;
   histogram_value histogram;
@@ -1350,7 +1381,7 @@ tree_stringops_transform (block_stmt_iterator *bsi)
   tree value;
   tree dest, src;
   unsigned int dest_align, src_align;
   tree value;
   tree dest, src;
   unsigned int dest_align, src_align;
-  int prob;
+  gcov_type prob;
   tree tree_val;
 
   if (!call)
   tree tree_val;
 
   if (!call)
@@ -1359,14 +1390,13 @@ tree_stringops_transform (block_stmt_iterator *bsi)
   if (!fndecl)
     return false;
   fcode = DECL_FUNCTION_CODE (fndecl);
   if (!fndecl)
     return false;
   fcode = DECL_FUNCTION_CODE (fndecl);
-  arglist = TREE_OPERAND (call, 1);
-  if (!interesting_stringop_to_profile_p (fndecl, arglist))
+  if (!interesting_stringop_to_profile_p (fndecl, call))
     return false;
 
   if (fcode == BUILT_IN_BZERO)
     return false;
 
   if (fcode == BUILT_IN_BZERO)
-    blck_size = TREE_VALUE (TREE_CHAIN (arglist));
+    blck_size = CALL_EXPR_ARG (call, 1);
   else
   else
-    blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+    blck_size = CALL_EXPR_ARG (call, 2);
   if (TREE_CODE (blck_size) == INTEGER_CST)
     return false;
 
   if (TREE_CODE (blck_size) == INTEGER_CST)
     return false;
 
@@ -1385,28 +1415,31 @@ tree_stringops_transform (block_stmt_iterator *bsi)
     return false;
   if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
     return false;
     return false;
   if (check_counter (stmt, "value", all, bb_for_stmt (stmt)->count))
     return false;
-  prob = (count * REG_BR_PROB_BASE + all / 2) / all;
-  dest = TREE_VALUE (arglist);
+  if (all > 0)
+    prob = (count * REG_BR_PROB_BASE + all / 2) / all;
+  else
+    prob = 0;
+  dest = CALL_EXPR_ARG (call, 0);
   dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
   switch (fcode)
     {
     case BUILT_IN_MEMCPY:
     case BUILT_IN_MEMPCPY:
   dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
   switch (fcode)
     {
     case BUILT_IN_MEMCPY:
     case BUILT_IN_MEMPCPY:
-      src = TREE_VALUE (TREE_CHAIN (arglist));
+      src = CALL_EXPR_ARG (call, 1);
       src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
       if (!can_move_by_pieces (val, MIN (dest_align, src_align)))
        return false;
       break;
     case BUILT_IN_MEMSET:
       if (!can_store_by_pieces (val, builtin_memset_read_str,
       src_align = get_pointer_alignment (src, BIGGEST_ALIGNMENT);
       if (!can_move_by_pieces (val, MIN (dest_align, src_align)))
        return false;
       break;
     case BUILT_IN_MEMSET:
       if (!can_store_by_pieces (val, builtin_memset_read_str,
-                               TREE_VALUE (TREE_CHAIN (arglist)),
-                               dest_align))
+                               CALL_EXPR_ARG (call, 1),
+                               dest_align, true))
        return false;
       break;
     case BUILT_IN_BZERO:
       if (!can_store_by_pieces (val, builtin_memset_read_str,
                                integer_zero_node,
        return false;
       break;
     case BUILT_IN_BZERO:
       if (!can_store_by_pieces (val, builtin_memset_read_str,
                                integer_zero_node,
-                               dest_align))
+                               dest_align, true))
        return false;
       break;
     default:
        return false;
       break;
     default:
@@ -1561,7 +1594,7 @@ tree_indirect_call_to_profile (tree stmt, histogram_values *values)
   if (!call || TREE_CODE (call) != CALL_EXPR)
     return;
 
   if (!call || TREE_CODE (call) != CALL_EXPR)
     return;
 
-  callee = TREE_OPERAND (call, 0);
+  callee = CALL_EXPR_FN (call);
   
   if (TREE_CODE (callee) == ADDR_EXPR)
     return;
   
   if (TREE_CODE (callee) == ADDR_EXPR)
     return;
@@ -1582,7 +1615,6 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values)
 {
   tree call = get_call_expr_in (stmt);
   tree fndecl;
 {
   tree call = get_call_expr_in (stmt);
   tree fndecl;
-  tree arglist;
   tree blck_size;
   tree dest;
   enum built_in_function fcode;
   tree blck_size;
   tree dest;
   enum built_in_function fcode;
@@ -1593,16 +1625,15 @@ tree_stringops_values_to_profile (tree stmt, histogram_values *values)
   if (!fndecl)
     return;
   fcode = DECL_FUNCTION_CODE (fndecl);
   if (!fndecl)
     return;
   fcode = DECL_FUNCTION_CODE (fndecl);
-  arglist = TREE_OPERAND (call, 1);
 
 
-  if (!interesting_stringop_to_profile_p (fndecl, arglist))
+  if (!interesting_stringop_to_profile_p (fndecl, call))
     return;
 
     return;
 
-  dest = TREE_VALUE (arglist);
+  dest = CALL_EXPR_ARG (call, 0);
   if (fcode == BUILT_IN_BZERO)
   if (fcode == BUILT_IN_BZERO)
-    blck_size = TREE_VALUE (TREE_CHAIN (arglist));
+    blck_size = CALL_EXPR_ARG (call, 1);
   else
   else
-    blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+    blck_size = CALL_EXPR_ARG (call, 2);
 
   if (TREE_CODE (blck_size) != INTEGER_CST)
     {
 
   if (TREE_CODE (blck_size) != INTEGER_CST)
     {
@@ -1715,4 +1746,3 @@ value_profile_transformations (void)
   return (value_prof_hooks->value_profile_transformations) ();
 }
 \f
   return (value_prof_hooks->value_profile_transformations) ();
 }
 \f
-