Looks ok to me in general.
1) the parameter name is not ideal -- it is not callonce.
2) it might be better to extend the callonce parameter into
-ftest-coverage option such as -ftest-coverage=exec_once?
3) need documentation in invoke.texi
4) watch out for long lines.

cc Teresa.

David

On Tue, May 21, 2013 at 3:28 PM, Rong Xu <x...@google.com> wrote:
> This patch is to be used with customized coverage reduction.
>
> The functionalities are under two parameter options:
> --param=COVERAGE-CALLBACK={0|1}
> when enabled with 1, it injects a callback function for
> each arc counter. Default off.
> --param=COVERAGE-CALLONCE={0|1}
> when enabled with 1, it stops incrementing the arc counter
> when they flip to 1. Default off. Even with an extra condition
> check, this is drastically faster than the normal coverage test
> for highly threaded applications.
>
> It also fixes a bug in profile sampling where some counters
> (like those after the call stmt) are not sampled.
>
> It disables the may-uninit check if the warning will not be
> emitted.
>
> Tested with bootstrap, regressions test and google internal
> benchmarks.
>
> Thanks,
>
> -Rong
>
> 2013-05-21  Rong Xu  <x...@google.com>
>
>         * gcc/tree-ssa-uninit.c (gate_warn_uninitialized): Disable if
>         may-uninit warning will not emitted.
>         * gcc/params.def : (PARAM_COVERAGE_CALLBACK) New.
>         (PARAM_COVERAGE_CALLONCE): NEW.
>         * gcc/profile.c (branch_prob): Not increment edge counter after
>         first update.
>         (tree_init_instrumentation_sampling): Ditto.
>         (COVERAGE_CALLBACK_FUNC_NAME): New.
>         (COVERAGE_INSERT_CALL): New.
>         (insert_if_then): Update branch probability.
>         (add_sampling_wrapper): Ditto.
>         (add_callback_wrapper): New.
>         (add_sampling_to_edge_counters): Make predicate insertion
>         complete.
>         (gimple_gen_edge_profiler): Add coverage callback function.
>         (gimple_gen_ic_profiler): Fix trailing space.
>         (gimple_gen_ic_func_topn_profiler): Ditto.
>         (gimple_gen_dc_profiler): Ditto.
>         * libgcc/libgcov.c (__coverage_callback): Add an empty callback
>         function.
>
> Index: libgcc/libgcov.c
> ===================================================================
> --- libgcc/libgcov.c    (revision 198952)
> +++ libgcc/libgcov.c    (working copy)
> @@ -135,6 +135,14 @@ extern int gcov_dump_complete ATTRIBUTE_HIDDEN;
>     these symbols will always need to be resolved.  */
>  void (*__gcov_dummy_ref1)() = &__gcov_reset;
>  void (*__gcov_dummy_ref2)() = &__gcov_dump;
> +
> +__attribute__((weak)) void
> +__coverage_callback (gcov_type funcdef_no __attribute__ ((unused)),
> +                     int edge_no __attribute__ ((unused)))
> +{
> +   /* nothing */
> +}
> +
>  #endif /* __GCOV_KERNEL__ */
>
>  /* Utility function for outputing errors.  */
> Index: gcc/profile.c
> ===================================================================
> --- gcc/profile.c       (revision 198952)
> +++ gcc/profile.c       (working copy)
> @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "timevar.h"
>  #include "cfgloop.h"
>  #include "tree-pass.h"
> +#include "params.h"
>
>  #include "profile.h"
>
> @@ -1480,7 +1481,8 @@ branch_prob (void)
>        /* Commit changes done by instrumentation.  */
>        gsi_commit_edge_inserts ();
>
> -      if (flag_profile_generate_sampling)
> +      if (flag_profile_generate_sampling
> +          || PARAM_VALUE (PARAM_COVERAGE_CALLONCE))
>          add_sampling_to_edge_counters ();
>      }
>
> Index: gcc/params.def
> ===================================================================
> --- gcc/params.def      (revision 198952)
> +++ gcc/params.def      (working copy)
> @@ -1060,6 +1060,16 @@ DEFPARAM (PARAM_PROFILE_GENERATE_SAMPLING_PERIOD,
>           "sampling rate with -fprofile-generate-sampling",
>           100, 0, 2000000000)
>
> +DEFPARAM (PARAM_COVERAGE_CALLBACK,
> +         "coverage-callback",
> +         "callback a user-define function when for arc counter increments.",
> +         0, 0, 1)
> +
> +DEFPARAM (PARAM_COVERAGE_CALLONCE,
> +         "coverage-callonce",
> +         "Stop increment coverage counts once they become 1.",
> +         0, 0, 1)
> +
>  /* Used for debugging purpose. Tell the compiler to find
>     the gcda file in the current directory.  */
>  DEFPARAM (PARAM_GCOV_DEBUG,
> Index: gcc/tree-profile.c
> ===================================================================
> --- gcc/tree-profile.c  (revision 198952)
> +++ gcc/tree-profile.c  (working copy)
> @@ -54,6 +54,15 @@ along with GCC; see the file COPYING3.  If not see
>  #include "target.h"
>  #include "output.h"
>
> +/* Default name for coverage callback function.  */
> +#define COVERAGE_CALLBACK_FUNC_NAME "__coverage_callback"
> +
> +/* If we insert a callback to edge instrumentation code. Avoid this
> +   for the callback function itself.  */
> +#define COVERAGE_INSERT_CALL   ((PARAM_VALUE (PARAM_COVERAGE_CALLBACK) == 1) 
> \
> +                                 && strcmp (get_name 
> (current_function_decl), \
> +                                        COVERAGE_CALLBACK_FUNC_NAME))
> +
>  /* Number of statements inserted for each edge counter increment.  */
>  #define EDGE_COUNTER_STMT_COUNT 3
>
> @@ -202,14 +211,16 @@ static tree GTY(()) gcov_lipo_merge_modu_edges = N
>  static tree GTY(()) gcov_lipo_strict_inclusion = NULL_TREE;
>
>  /* Insert STMT_IF around given sequence of consecutive statements in the
> -   same basic block starting with STMT_START, ending with STMT_END.  */
> +   same basic block starting with STMT_START, ending with STMT_END.
> +   PROB is the probability of the taken branch.  */
>
>  static void
> -insert_if_then (gimple stmt_start, gimple stmt_end, gimple stmt_if)
> +insert_if_then (gimple stmt_start, gimple stmt_end, gimple stmt_if, int prob)
>  {
>    gimple_stmt_iterator gsi;
>    basic_block bb_original, bb_before_if, bb_after_if;
> -  edge e_if_taken, e_then_join;
> +  edge e_if_taken, e_then_join, e_else;
> +  int orig_frequency;
>
>    gsi = gsi_for_stmt (stmt_start);
>    gsi_insert_before (&gsi, stmt_if, GSI_SAME_STMT);
> @@ -220,7 +231,11 @@ static void
>    e_then_join = split_block (e_if_taken->dest, stmt_end);
>    bb_before_if = e_if_taken->src;
>    bb_after_if = e_then_join->dest;
> -  make_edge (bb_before_if, bb_after_if, EDGE_FALSE_VALUE);
> +  e_else = make_edge (bb_before_if, bb_after_if, EDGE_FALSE_VALUE);
> +  orig_frequency = bb_original->frequency;
> +  e_if_taken->probability = prob;
> +  e_else->probability = REG_BR_PROB_BASE - prob;
> +  e_if_taken->dest->frequency = orig_frequency * (prob / REG_BR_PROB_BASE);
>  }
>
>  /* Transform:
> @@ -274,9 +289,34 @@ add_sampling_wrapper (gimple stmt_start, gimple st
>    gsi_insert_before (&gsi, stmt_reset_counter, GSI_SAME_STMT);
>
>    /* Insert IF block.  */
> -  insert_if_then (stmt_reset_counter, stmt_end, stmt_if);
> +  /* Sampling rate can be changed runtime: hard to guess the branch prob,
> +     so make it 1.  */
> +  insert_if_then (stmt_reset_counter, stmt_end, stmt_if, REG_BR_PROB_BASE);
>  }
>
> +static void
> +add_callonce_wrapper (gimple stmt_start, gimple stmt_end)
> +{
> +  tree zero, tmp_var, tmp1;
> +  gimple stmt_if, stmt_assign;
> +  gimple_stmt_iterator gsi;
> +
> +  /* Create all the new statements needed.  */
> +  tmp_var = create_tmp_reg (get_gcov_type (), "PROF_temp");
> +  tmp1 = make_ssa_name (tmp_var, NULL);
> +  stmt_assign = gimple_build_assign (tmp1, gimple_assign_lhs (stmt_end));
> +
> +  zero = build_int_cst (get_gcov_type (), 0);
> +  stmt_if = gimple_build_cond (EQ_EXPR, tmp1, zero, NULL_TREE, NULL_TREE);
> +  find_referenced_vars_in (stmt_if);
> +
> +  gsi = gsi_for_stmt (stmt_start);
> +  gsi_insert_before (&gsi, stmt_assign, GSI_SAME_STMT);
> +
> +  /* Insert IF block.  */
> +  insert_if_then (stmt_start, stmt_end, stmt_if, 1);
> +}
> +
>  /* Return whether STMT is the beginning of an instrumentation block to be
>     applied sampling.  */
>
> @@ -295,22 +335,34 @@ add_sampling_to_edge_counters (void)
>    basic_block bb;
>
>    FOR_EACH_BB_REVERSE (bb)
> -    for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> +    for (gsi = gsi_last (bb_seq (bb)); !gsi_end_p (gsi); gsi_prev (&gsi))
>        {
> -        gimple stmt = gsi_stmt (gsi);
> -        if (is_instrumentation_to_be_sampled (stmt))
> +        gimple stmt_end = gsi_stmt (gsi);
> +        if (is_instrumentation_to_be_sampled (stmt_end))
>            {
> -            gimple stmt_end;
> +            gimple stmt_beg;
>              int i;
> +            int edge_counter_stmt_count = EDGE_COUNTER_STMT_COUNT;
> +
>              /* The code for edge counter increment has 
> EDGE_COUNTER_STMT_COUNT
>                 gimple statements. Advance that many statements to find the
> -               last statement.  */
> -            for (i = 0; i < EDGE_COUNTER_STMT_COUNT - 1; i++)
> -              gsi_next (&gsi);
> -            stmt_end = gsi_stmt (gsi);
> -            gcc_assert (stmt_end);
> -            add_sampling_wrapper (stmt, stmt_end);
> -            break;
> +               beginning statement.  */
> +            if (COVERAGE_INSERT_CALL)
> +              edge_counter_stmt_count++;
> +
> +            for (i = 0; i < edge_counter_stmt_count - 1; i++)
> +              gsi_prev (&gsi);
> +            stmt_beg = gsi_stmt (gsi);
> +            gcc_assert (stmt_beg);
> +
> +
> +            if (flag_profile_generate_sampling)
> +              add_sampling_wrapper (stmt_beg, stmt_end);
> +            if (PARAM_VALUE (PARAM_COVERAGE_CALLONCE))
> +              add_callonce_wrapper (stmt_beg, stmt_end);
> +
> +            /* reset the iterator and continue.  */
> +            gsi = gsi_last (bb_seq (bb));
>            }
>        }
>  }
> @@ -508,6 +560,9 @@ tree_init_instrumentation_sampling (void)
>          DECL_TLS_MODEL (gcov_sample_counter_decl) =
>              decl_default_tls_model (gcov_sample_counter_decl);
>      }
> +  if (PARAM_VALUE (PARAM_COVERAGE_CALLONCE)
> +      && instrumentation_to_be_sampled == 0)
> +    instrumentation_to_be_sampled = pointer_set_create ();
>  }
>
>  void
> @@ -675,6 +730,30 @@ gimple_gen_edge_profiler (int edgeno, edge e)
>      ref = tree_coverage_counter_ref (GCOV_COUNTER_ARCS, edgeno);
>
>    one = build_int_cst (gcov_type_node, 1);
> +
> +  /* insert a callback stmt stmt */
> +  if (COVERAGE_INSERT_CALL)
> +    {
> +      gimple call;
> +      tree tree_edgeno = build_int_cst (gcov_type_node, edgeno);
> +      tree tree_uid = build_int_cst (gcov_type_node, 
> current_function_funcdef_no);
> +      tree callback_fn_type
> +              = build_function_type_list (void_type_node,
> +                                          gcov_type_node,
> +                                          integer_type_node,
> +                                          NULL_TREE);
> +      tree tree_callback_fn = build_fn_decl (COVERAGE_CALLBACK_FUNC_NAME,
> +                                             callback_fn_type);
> +      TREE_NOTHROW (tree_callback_fn) = 1;
> +      DECL_ATTRIBUTES (tree_callback_fn)
> +        = tree_cons (get_identifier ("leaf"), NULL,
> +                     DECL_ATTRIBUTES (tree_callback_fn));
> +
> +      call = gimple_build_call (tree_callback_fn, 2, tree_uid, tree_edgeno);
> +      find_referenced_vars_in (call);
> +      gsi_insert_on_edge(e, call);
> +    }
> +
>    if (PROFILE_GEN_EDGE_ATOMIC)
>      {
>        /* __atomic_fetch_add (&counter, 1, MEMMODEL_RELAXED); */
> @@ -695,13 +774,14 @@ gimple_gen_edge_profiler (int edgeno, edge e)
>        gimple_assign_set_lhs (stmt2, make_ssa_name (gcov_type_tmp_var, 
> stmt2));
>        stmt3 = gimple_build_assign (unshare_expr (ref), gimple_assign_lhs 
> (stmt2));
>
> -      if (flag_profile_generate_sampling)
> -        pointer_set_insert (instrumentation_to_be_sampled, stmt1);
> -
>        gsi_insert_on_edge (e, stmt1);
>        gsi_insert_on_edge (e, stmt2);
>      }
>    gsi_insert_on_edge (e, stmt3);
> +
> +  if (flag_profile_generate_sampling
> +      || PARAM_VALUE (PARAM_COVERAGE_CALLONCE))
> +    pointer_set_insert (instrumentation_to_be_sampled, stmt3);
>  }
>
>  /* Emits code to get VALUE to instrument at GSI, and returns the
> @@ -802,7 +882,7 @@ gimple_gen_ic_profiler (histogram_value value, uns
>    gimple stmt;
>    gimple_stmt_iterator gsi;
>    tree ref_ptr;
> -
> +
>    stmt = value->hvalue.stmt;
>    gsi = gsi_for_stmt (stmt);
>    ref_ptr = tree_coverage_counter_addr (tag, base);
> @@ -905,7 +985,7 @@ gimple_gen_ic_func_topn_profiler (void)
>    gcov_info = build_fold_addr_expr (gcov_info_decl);
>    cur_func_id = build_int_cst (get_gcov_unsigned_t (),
>                                FUNC_DECL_FUNC_ID (cfun));
> -  stmt1 = gimple_build_call (tree_indirect_call_topn_profiler_fn,
> +  stmt1 = gimple_build_call (tree_indirect_call_topn_profiler_fn,
>                              3, cur_func, gcov_info, cur_func_id);
>    gsi_insert_before (&gsi, stmt1, GSI_SAME_STMT);
>  }
> @@ -922,7 +1002,7 @@ gimple_gen_dc_profiler (unsigned base, gimple call
>    gimple stmt1, stmt2, stmt3;
>    gimple_stmt_iterator gsi = gsi_for_stmt (call_stmt);
>    tree tmp1, tmp2, tmp3, callee = gimple_call_fn (call_stmt);
> -
> +
>    /* Insert code:
>       __gcov_direct_call_counters = get_relevant_counter_ptr ();
>       __gcov_callee = (void *) callee;
> Index: gcc/tree-ssa-uninit.c
> ===================================================================
> --- gcc/tree-ssa-uninit.c       (revision 198952)
> +++ gcc/tree-ssa-uninit.c       (working copy)
> @@ -2033,7 +2033,7 @@ execute_late_warn_uninitialized (void)
>  static bool
>  gate_warn_uninitialized (void)
>  {
> -  return warn_uninitialized != 0;
> +  return (warn_uninitialized != 0 && warn_maybe_uninitialized != 0);
>  }
>
>  struct gimple_opt_pass pass_late_warn_uninitialized =
>
> --
> This patch is available for review at http://codereview.appspot.com/9630043

Reply via email to