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.
-   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
-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
@@ -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
-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"
@@ -107,7 +107,7 @@ gimple_alloc_histogram_value (struct function *fun ATTRIBUTE_UNUSED,
 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.  */
@@ -115,7 +115,7 @@ histogram_hash (const void *x)
 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.  */
@@ -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
@@ -354,7 +373,7 @@ visit_hist (void **slot, void *data)
       debug_generic_stmt (hist->hvalue.stmt);
       error_found = true;
     }
-  return 0;
+  return 1;
 }
 
 /* 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);
-  return 0;
+  return 1;
 }
 
 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");
-  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),
-           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);
@@ -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);
-  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);
-  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;
@@ -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;
-  int prob;
+  gcov_type prob;
 
   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.  */
-  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,
@@ -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");
-  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)),
-                 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);
@@ -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);
-  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);
-  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;
@@ -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;
-  int prob;
+  gcov_type prob;
 
   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;
 
-  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);
 
@@ -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");
-  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),
-           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);
@@ -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);
-      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),
-               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);
@@ -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);
-  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;
@@ -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;
-  int prob1, prob2;
+  gcov_type prob1, prob2;
   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).  */
-  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.  */
@@ -1044,7 +1076,7 @@ find_func_by_pid (int     pid)
 
 /* 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
@@ -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;
-  tree tmp1, tmpv;
+  tree tmp1, tmpv, tmp;
   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");
-  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),
-                 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);
@@ -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);
-  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;
@@ -1156,7 +1187,7 @@ tree_ic_transform (tree stmt)
 {
   histogram_value histogram;
   gcov_type val, count, all;
-  int prob;
+  gcov_type prob;
   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;
 
-  callee = TREE_OPERAND (call, 0);
+  callee = CALL_EXPR_FN (call);
 
   if (TREE_CODE (callee) == ADDR_EXPR)
     return false;
@@ -1182,7 +1213,10 @@ tree_ic_transform (tree stmt)
   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)
@@ -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);
+      fprintf (dump_file, "hist->count "HOST_WIDEST_INT_PRINT_DEC
+              " hist->all "HOST_WIDEST_INT_PRINT_DEC"\n", count, all);
     }
 
   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
-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);
 
-  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 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:
-       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:
-        return validate_arglist (arglist, POINTER_TYPE, INTEGER_TYPE,
-                                VOID_TYPE);
+       return validate_arglist (call, POINTER_TYPE, INTEGER_TYPE,
+                               VOID_TYPE);
      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);
-  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;
 
@@ -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");
-  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),
-           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);
@@ -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);
-  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);
@@ -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 arglist;
   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;
-  int prob;
+  gcov_type prob;
   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);
-  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)
-    blck_size = TREE_VALUE (TREE_CHAIN (arglist));
+    blck_size = CALL_EXPR_ARG (call, 1);
   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;
 
@@ -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;
-  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:
-      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,
-                               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,
-                               dest_align))
+                               dest_align, true))
        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;
 
-  callee = TREE_OPERAND (call, 0);
+  callee = CALL_EXPR_FN (call);
   
   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 arglist;
   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);
-  arglist = TREE_OPERAND (call, 1);
 
-  if (!interesting_stringop_to_profile_p (fndecl, arglist))
+  if (!interesting_stringop_to_profile_p (fndecl, call))
     return;
 
-  dest = TREE_VALUE (arglist);
+  dest = CALL_EXPR_ARG (call, 0);
   if (fcode == BUILT_IN_BZERO)
-    blck_size = TREE_VALUE (TREE_CHAIN (arglist));
+    blck_size = CALL_EXPR_ARG (call, 1);
   else
-    blck_size = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+    blck_size = CALL_EXPR_ARG (call, 2);
 
   if (TREE_CODE (blck_size) != INTEGER_CST)
     {
@@ -1715,4 +1746,3 @@ value_profile_transformations (void)
   return (value_prof_hooks->value_profile_transformations) ();
 }
 \f
-