diff options
author | Jan Hubicka <jh@suse.cz> | 2013-08-09 20:23:23 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2013-08-09 18:23:23 +0000 |
commit | 2fa3d31bd6bb9274abaa3a7d59cc88e9a6112194 (patch) | |
tree | 58562426672deca3c5be2e63eabd43cdf4af64ae /gcc/value-prof.c | |
parent | 36849c21ccee087a778360d3a5dce38d1f7dd586 (diff) | |
download | gcc-2fa3d31bd6bb9274abaa3a7d59cc88e9a6112194.zip gcc-2fa3d31bd6bb9274abaa3a7d59cc88e9a6112194.tar.gz gcc-2fa3d31bd6bb9274abaa3a7d59cc88e9a6112194.tar.bz2 |
cgraph.h (cgraph_node): Add profile_id.
* cgraph.h (cgraph_node): Add profile_id.
* value-prof.c (cgraph_node_map): Turn into pointer_map.
(init_node_map): Rewrite to handle hashes increas of incremental
IDs.
(del_node_map): Update.
(find_func_by_funcdef_no): Replace by ...
(find_func_by_profile_id): ... this one.
(gimple_ic_transform): Do not remove useful histograms when
speculation is not done; dump info when indirect call removal
can happen at LTO.
* value-prof.h (find_func_by_profile_id, gimple_ic): Declare.
* gcov-io.h (__gcov_indirect_call_profiler): Replace by ...
(__gcov_indirect_call_profiler_v2): .. this one.
* profile.h (init_node_map): Update.
* coverage.c (coverage_compute_profile_id): New function.
* coverage.h (coverage_compute_profile_id): Declare.
* tree-profile.c (init_ic_make_global_vars): Make
__gcov_indirect_call_callee and __gcov_indirect_call_counters global.
(gimple_init_edge_profiler): Update prototype of
__gcov_indirect_call_profiler.
(gimple_gen_ic_func_profiler): Simplify.
(tree_profiling): Use init_node_map
From-SVN: r201634
Diffstat (limited to 'gcc/value-prof.c')
-rw-r--r-- | gcc/value-prof.c | 119 |
1 files changed, 86 insertions, 33 deletions
diff --git a/gcc/value-prof.c b/gcc/value-prof.c index c198c65..f110277 100644 --- a/gcc/value-prof.c +++ b/gcc/value-prof.c @@ -1173,24 +1173,67 @@ gimple_mod_subtract_transform (gimple_stmt_iterator *si) return true; } -static vec<cgraph_node_ptr> cgraph_node_map - = vNULL; +static pointer_map_t *cgraph_node_map; -/* Initialize map from FUNCDEF_NO to CGRAPH_NODE. */ +/* Initialize map from PROFILE_ID to CGRAPH_NODE. + When LOCAL is true, the PROFILE_IDs are computed. when it is false we assume + that the PROFILE_IDs was already assigned. */ void -init_node_map (void) +init_node_map (bool local) { struct cgraph_node *n; + cgraph_node_map = pointer_map_create (); - if (get_last_funcdef_no ()) - cgraph_node_map.safe_grow_cleared (get_last_funcdef_no ()); - - FOR_EACH_FUNCTION (n) - { - if (DECL_STRUCT_FUNCTION (n->symbol.decl)) - cgraph_node_map[DECL_STRUCT_FUNCTION (n->symbol.decl)->funcdef_no] = n; - } + FOR_EACH_DEFINED_FUNCTION (n) + if (cgraph_function_with_gimple_body_p (n) + && !cgraph_only_called_directly_p (n)) + { + void **val; + if (local) + { + n->profile_id = coverage_compute_profile_id (n); + while ((val = pointer_map_contains (cgraph_node_map, + (void *)(size_t)n->profile_id)) + || !n->profile_id) + { + if (dump_file) + fprintf (dump_file, "Local profile-id %i conflict" + " with nodes %s/%i %s/%i\n", + n->profile_id, + cgraph_node_name (n), + n->symbol.order, + symtab_node_name (*(symtab_node*)val), + (*(symtab_node *)val)->symbol.order); + n->profile_id = (n->profile_id + 1) & 0x7fffffff; + } + } + else if (!n->profile_id) + { + if (dump_file) + fprintf (dump_file, + "Node %s/%i has no profile-id" + " (profile feedback missing?)\n", + cgraph_node_name (n), + n->symbol.order); + continue; + } + else if ((val = pointer_map_contains (cgraph_node_map, + (void *)(size_t)n->profile_id))) + { + if (dump_file) + fprintf (dump_file, + "Node %s/%i has IP profile-id %i conflict. " + "Giving up.\n", + cgraph_node_name (n), + n->symbol.order, + n->profile_id); + *val = NULL; + continue; + } + *pointer_map_insert (cgraph_node_map, + (void *)(size_t)n->profile_id) = (void *)n; + } } /* Delete the CGRAPH_NODE_MAP. */ @@ -1198,27 +1241,20 @@ init_node_map (void) void del_node_map (void) { - cgraph_node_map.release (); + pointer_map_destroy (cgraph_node_map); } /* Return cgraph node for function with pid */ -static inline struct cgraph_node* -find_func_by_funcdef_no (int func_id) +struct cgraph_node* +find_func_by_profile_id (int profile_id) { - int max_id = get_last_funcdef_no (); - if (func_id >= max_id || cgraph_node_map[func_id] == NULL) - { - if (flag_profile_correction) - inform (DECL_SOURCE_LOCATION (current_function_decl), - "Inconsistent profile: indirect call target (%d) does not exist", func_id); - else - error ("Inconsistent profile: indirect call target (%d) does not exist", func_id); - - return NULL; - } - - return cgraph_node_map[func_id]; + void **val = pointer_map_contains (cgraph_node_map, + (void *)(size_t)profile_id); + if (val) + return (struct cgraph_node *)*val; + else + return NULL; } /* Perform sanity check on the indirect call target. Due to race conditions, @@ -1415,10 +1451,12 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) val = histogram->hvalue.counters [0]; count = histogram->hvalue.counters [1]; all = histogram->hvalue.counters [2]; - gimple_remove_histogram_value (cfun, stmt, histogram); if (4 * count <= 3 * all) - return false; + { + gimple_remove_histogram_value (cfun, stmt, histogram); + return false; + } bb_all = gimple_bb (stmt)->count; /* The order of CHECK_COUNTER calls is important - @@ -1426,16 +1464,31 @@ gimple_ic_transform (gimple_stmt_iterator *gsi) and we want to make count <= all <= bb_all. */ if ( check_counter (stmt, "ic", &all, &bb_all, bb_all) || check_counter (stmt, "ic", &count, &all, all)) - return false; + { + gimple_remove_histogram_value (cfun, stmt, histogram); + return false; + } if (all > 0) prob = GCOV_COMPUTE_SCALE (count, all); else prob = 0; - direct_call = find_func_by_funcdef_no ((int)val); + direct_call = find_func_by_profile_id ((int)val); if (direct_call == NULL) - return false; + { + if (val) + { + if (dump_file) + { + fprintf (dump_file, "Indirect call -> direct call from other module"); + print_generic_expr (dump_file, gimple_call_fn (stmt), TDF_SLIM); + fprintf (dump_file, "=> %i (will resolve only with LTO)\n", (int)val); + } + } + return false; + } + gimple_remove_histogram_value (cfun, stmt, histogram); if (!check_ic_target (stmt, direct_call)) return false; |