X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fprofile.c;h=ac460464697cef6abbb60cb8bce2fac952a26c97;hb=73faef308beb68f43956ec108d6dc61a4ed1b3d6;hp=761c8ad4b07a3429e14c055f53d1bd0bedf7169c;hpb=e0dc6f2bee436056af7d1c49ed2714fa53ee430d;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/profile.c b/gcc/profile.c index 761c8ad4b07..ac460464697 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -1,6 +1,6 @@ /* Calculate branch probabilities, and basic block execution counts. Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 + 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by James E. Wilson, UC Berkeley/Cygnus Support; based on some ideas from Dain Samples of UC Berkeley. @@ -100,7 +100,6 @@ static int total_num_blocks_created; static int total_num_passes; static int total_num_times_called; static int total_hist_br_prob[20]; -static int total_num_never_executed; static int total_num_branches; /* Forward declarations. */ @@ -277,8 +276,20 @@ is_edge_inconsistent (VEC(edge,gc) *edges) { if (!EDGE_INFO (e)->ignore) { - if (e->count < 0) - return true; + if (e->count < 0 + && (!(e->flags & EDGE_FAKE) + || !block_ends_with_call_p (e->src))) + { + if (dump_file) + { + fprintf (dump_file, + "Edge %i->%i is inconsistent, count"HOST_WIDEST_INT_PRINT_DEC, + e->src->index, e->dest->index, e->count); + dump_bb (e->src, dump_file, 0); + dump_bb (e->dest, dump_file, 0); + } + return true; + } } } return false; @@ -307,20 +318,59 @@ static bool is_inconsistent (void) { basic_block bb; + bool inconsistent = false; FOR_EACH_BB (bb) { - if (is_edge_inconsistent (bb->preds)) - return true; - if (is_edge_inconsistent (bb->succs)) - return true; - if ( bb->count != sum_edge_counts (bb->preds) - || (bb->count != sum_edge_counts (bb->succs) && - !(find_edge (bb, EXIT_BLOCK_PTR) != NULL && - block_ends_with_call_p (bb)))) - return true; + inconsistent |= is_edge_inconsistent (bb->preds); + if (!dump_file && inconsistent) + return true; + inconsistent |= is_edge_inconsistent (bb->succs); + if (!dump_file && inconsistent) + return true; + if (bb->count < 0) + { + if (dump_file) + { + fprintf (dump_file, "BB %i count is negative " + HOST_WIDEST_INT_PRINT_DEC, + bb->index, + bb->count); + dump_bb (bb, dump_file, 0); + } + inconsistent = true; + } + if (bb->count != sum_edge_counts (bb->preds)) + { + if (dump_file) + { + fprintf (dump_file, "BB %i count does not match sum of incoming edges " + HOST_WIDEST_INT_PRINT_DEC" should be " HOST_WIDEST_INT_PRINT_DEC, + bb->index, + bb->count, + sum_edge_counts (bb->preds)); + dump_bb (bb, dump_file, 0); + } + inconsistent = true; + } + if (bb->count != sum_edge_counts (bb->succs) && + ! (find_edge (bb, EXIT_BLOCK_PTR) != NULL && block_ends_with_call_p (bb))) + { + if (dump_file) + { + fprintf (dump_file, "BB %i count does not match sum of outgoing edges " + HOST_WIDEST_INT_PRINT_DEC" should be " HOST_WIDEST_INT_PRINT_DEC, + bb->index, + bb->count, + sum_edge_counts (bb->succs)); + dump_bb (bb, dump_file, 0); + } + inconsistent = true; + } + if (!dump_file && inconsistent) + return true; } - return false; + return inconsistent; } /* Set each basic block count to the sum of its outgoing edge counts */ @@ -396,25 +446,23 @@ compute_branch_probabilities (void) int changes; int passes; int hist_br_prob[20]; - int num_never_executed; int num_branches; gcov_type *exec_counts = get_exec_counts (); int inconsistent = 0; /* Very simple sanity checks so we catch bugs in our profiling code. */ - if (profile_info) + if (!profile_info) + return; + if (profile_info->run_max * profile_info->runs < profile_info->sum_max) { - if (profile_info->run_max * profile_info->runs < profile_info->sum_max) - { - error ("corrupted profile info: run_max * runs < sum_max"); - exec_counts = NULL; - } + error ("corrupted profile info: run_max * runs < sum_max"); + exec_counts = NULL; + } - if (profile_info->sum_all < profile_info->sum_max) - { - error ("corrupted profile info: sum_all is smaller than sum_max"); - exec_counts = NULL; - } + if (profile_info->sum_all < profile_info->sum_max) + { + error ("corrupted profile info: sum_all is smaller than sum_max"); + exec_counts = NULL; } /* Attach extra info block to each bb. */ @@ -579,7 +627,7 @@ compute_branch_probabilities (void) if (informed == 0) { informed = 1; - inform ("correcting inconsistent profile data"); + inform (input_location, "correcting inconsistent profile data"); } correct_negative_edge_counts (); /* Set bb counts to the sum of the outgoing edge counts */ @@ -597,7 +645,6 @@ compute_branch_probabilities (void) for (i = 0; i < 20; i++) hist_br_prob[i] = 0; - num_never_executed = 0; num_branches = 0; FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) @@ -691,16 +738,15 @@ compute_branch_probabilities (void) if (bb->index >= NUM_FIXED_BLOCKS && block_ends_with_condjump_p (bb) && EDGE_COUNT (bb->succs) >= 2) - num_branches++, num_never_executed; + num_branches++; } } counts_to_freqs (); + profile_status = PROFILE_READ; if (dump_file) { fprintf (dump_file, "%d branches\n", num_branches); - fprintf (dump_file, "%d branches never executed\n", - num_never_executed); if (num_branches) for (i = 0; i < 10; i++) fprintf (dump_file, "%d%% branches in range %d-%d%%\n", @@ -708,7 +754,6 @@ compute_branch_probabilities (void) 5 * i, 5 * i + 5); total_num_branches += num_branches; - total_num_never_executed += num_never_executed; for (i = 0; i < 20; i++) total_hist_br_prob[i] += hist_br_prob[i]; @@ -730,7 +775,7 @@ compute_value_histograms (histogram_values values) gcov_type *histogram_counts[GCOV_N_VALUE_COUNTERS]; gcov_type *act_count[GCOV_N_VALUE_COUNTERS]; gcov_type *aact_count; - + for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++) n_histogram_counters[t] = 0; @@ -898,8 +943,8 @@ branch_prob (void) } /* Edge with goto locus might get wrong coverage info unless - it is the only edge out of BB. - Don't do that when the locuses match, so + it is the only edge out of BB. + Don't do that when the locuses match, so if (blah) goto something; is not computed twice. */ if (last @@ -909,10 +954,12 @@ branch_prob (void) && (LOCATION_FILE (e->goto_locus) != LOCATION_FILE (gimple_location (last)) || (LOCATION_LINE (e->goto_locus) - != LOCATION_LINE (gimple_location (last))))) + != LOCATION_LINE (gimple_location (last))))) { basic_block new_bb = split_edge (e); - single_succ_edge (new_bb)->goto_locus = e->goto_locus; + edge ne = single_succ_edge (new_bb); + ne->goto_locus = e->goto_locus; + ne->goto_block = e->goto_block; } if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL)) && e->dest != EXIT_BLOCK_PTR) @@ -1080,7 +1127,7 @@ branch_prob (void) if (bb == ENTRY_BLOCK_PTR->next_bb) { - expanded_location curr_location = + expanded_location curr_location = expand_location (DECL_SOURCE_LOCATION (current_function_decl)); output_location (curr_location.file, curr_location.line, &offset, bb); @@ -1154,8 +1201,6 @@ branch_prob (void) VEC_free (histogram_value, heap, values); free_edge_list (el); - if (flag_branch_probabilities) - profile_status = PROFILE_READ; coverage_end_function (); } @@ -1282,7 +1327,6 @@ init_branch_prob (void) total_num_passes = 0; total_num_times_called = 0; total_num_branches = 0; - total_num_never_executed = 0; for (i = 0; i < 20; i++) total_hist_br_prob[i] = 0; } @@ -1313,8 +1357,6 @@ end_branch_prob (void) / total_num_times_called); fprintf (dump_file, "Total number of branches: %d\n", total_num_branches); - fprintf (dump_file, "Total number of branches never executed: %d\n", - total_num_never_executed); if (total_num_branches) { int i;