PATCH: Bug fix for counter overflow and arithmetic exception

Vinodha Ramasamy vinodha@google.com
Thu Jun 5 22:40:00 GMT 2008


Description:
Variables to hold edge counts were incorrectly defined as int type, resulting
in counter overflows. Fixed the type of such variables to be gcov_type. Also
added code to check if a counter value is 0, when the counter is used as the
denominator in a divide operation to avoid arithmetic exception.

Changelog:
2008-06-05 Vinodha Ramasamy  <vinodha@google.com>

       * value_prob.c (tree_divmod_fixed_value_transform): Use gcov_type
       for prob.  Add check for all > 0.
       (tree_mod_pow2_value_transform, tree_ic_transform): Likewise.
       (tree_stringops_transform): Likewise.
       (tree_mod_subtract_transform): Use gcov_type for prob1 and prob2.
       Add check for all > 0.
       * tree-inline.c (copy_bb, copy_edges_for_bb): Corrected type of
       count_scale to gcov_type.
       (initialize_cfun): Corrected type of count_scale and frequency_scale
       to gcov_type.

Index: gcc/value-prof.c
==============================
=====================================
--- gcc/value-prof.c    (revision 136174)
+++ gcc/value-prof.c    (working copy)
@@ -609,7 +609,7 @@ tree_divmod_fixed_value_transform (tree
   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
@@ -650,7 +650,10 @@ tree_divmod_fixed_value_transform (tree
     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,
@@ -769,7 +772,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
@@ -816,7 +819,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);

@@ -948,7 +954,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;

@@ -1015,8 +1021,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.  */
@@ -1173,7 +1186,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;

@@ -1199,7 +1212,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)
@@ -1364,7 +1380,7 @@ tree_stringops_transform (block_stmt_ite
   tree value;
   tree dest, src;
   unsigned int dest_align, src_align;
-  int prob;
+  gcov_type prob;
   tree tree_val;

   if (!call)
@@ -1398,7 +1414,10 @@ tree_stringops_transform (block_stmt_ite
     return false;
   if (check_counter (stmt, "value", 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;
   dest = CALL_EXPR_ARG (call, 0);
   dest_align = get_pointer_alignment (dest, BIGGEST_ALIGNMENT);
   switch (fcode)
@@ -1726,4 +1745,3 @@ value_profile_transformations (void)
   return (value_prof_hooks->value_profile_transformations) ();
 }

-
Index: gcc/tree-inline.c
===================================================================
--- gcc/tree-inline.c   (revision 136174)
+++ gcc/tree-inline.c   (working copy)
@@ -795,7 +795,8 @@ copy_body_r (tree *tp, int *walk_subtree
    later  */

 static basic_block
-copy_bb (copy_body_data *id, basic_block bb, int frequency_scale, int
count_scale)
+copy_bb (copy_body_data *id, basic_block bb, int frequency_scale,
+         gcov_type count_scale)
 {
   block_stmt_iterator bsi, copy_bsi;
   basic_block copy_basic_block;
@@ -1108,7 +1109,7 @@ update_ssa_across_abnormal_edges (basic_
    accordingly.  Edges will be taken care of later.  Assume aux
    pointers to point to the copies of each BB.  */
 static void
-copy_edges_for_bb (basic_block bb, int count_scale, basic_block ret_bb)
+copy_edges_for_bb (basic_block bb, gcov_type count_scale, basic_block ret_bb)
 {
   basic_block new_bb = (basic_block) bb->aux;
   edge_iterator ei;
@@ -1257,7 +1258,7 @@ initialize_cfun (tree new_fndecl, tree c
   struct function *new_cfun
      = (struct function *) ggc_alloc_cleared (sizeof (struct function));
   struct function *src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);
-  int count_scale, frequency_scale;
+  gcov_type count_scale, frequency_scale;

   if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count)
     count_scale = (REG_BR_PROB_BASE * count
@@ -1321,7 +1322,7 @@ copy_cfg_body (copy_body_data * id, gcov
   struct function *cfun_to_copy;
   basic_block bb;
   tree new_fndecl = NULL;
-  int count_scale, frequency_scale;
+  gcov_type count_scale, frequency_scale;
   int last;

   if (ENTRY_BLOCK_PTR_FOR_FUNCTION (src_cfun)->count)



More information about the Gcc-patches mailing list