X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fprofile.c;h=7c38b7fe149fcfb60b476792e76ca275f0accad9;hb=08dfbb2b6a4622eb1217ad3bba98b7d40305b87d;hp=c32003e787c1f2f939039dc7335e6cfde4dc6b97;hpb=67ce556b47830dd825524e8370969b814c355216;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/profile.c b/gcc/profile.c index c32003e787c..7c38b7fe149 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -65,16 +65,13 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tree.h" #include "cfghooks.h" #include "tree-flow.h" +#include "timevar.h" +#include "cfgloop.h" +#include "tree-pass.h" /* Hooks for profiling. */ static struct profile_hooks* profile_hooks; -/* File for profiling debug output. */ -static inline FILE* -profile_dump_file (void) { - return profile_hooks->profile_dump_file (); -} - /* Additional information about the edges we need. */ struct edge_info { unsigned int count_valid : 1; @@ -223,7 +220,6 @@ instrument_values (histogram_values values) gcc_unreachable (); } } - VEC_free (histogram_value, heap, values); } @@ -468,7 +464,7 @@ compute_branch_probabilities (void) } } if (dump_file) - dump_flow_info (dump_file); + dump_flow_info (dump_file, dump_flags); total_num_passes += passes; if (dump_file) @@ -493,7 +489,6 @@ compute_branch_probabilities (void) { edge e; edge_iterator ei; - rtx note; if (bb->count < 0) { @@ -528,7 +523,7 @@ compute_branch_probabilities (void) { FOR_EACH_EDGE (e, ei, bb->succs) e->probability = (e->count * REG_BR_PROB_BASE + bb->count / 2) / bb->count; - if (bb->index >= 0 + if (bb->index >= NUM_FIXED_BLOCKS && block_ends_with_condjump_p (bb) && EDGE_COUNT (bb->succs) >= 2) { @@ -549,37 +544,9 @@ compute_branch_probabilities (void) index = 19; hist_br_prob[index]++; - /* Do this for RTL only. */ - if (!ir_type ()) - { - note = find_reg_note (BB_END (bb), REG_BR_PROB, 0); - /* There may be already note put by some other pass, such - as builtin_expect expander. */ - if (note) - XEXP (note, 0) = GEN_INT (prob); - else - REG_NOTES (BB_END (bb)) - = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob), - REG_NOTES (BB_END (bb))); - } num_branches++; } } - /* Otherwise try to preserve the existing REG_BR_PROB probabilities - tree based profile guessing put into code. BB can be the - ENTRY_BLOCK, and it can have multiple (fake) successors in - EH cases, but it still has no code; don't crash in this case. */ - else if (profile_status == PROFILE_ABSENT - && !ir_type () - && EDGE_COUNT (bb->succs) > 1 - && BB_END (bb) - && (note = find_reg_note (BB_END (bb), REG_BR_PROB, 0))) - { - int prob = INTVAL (XEXP (note, 0)); - - BRANCH_EDGE (bb)->probability = prob; - FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob; - } /* As a last resort, distribute the probabilities evenly. Use simple heuristics that if there are normal edges, give all abnormals frequency of 0, otherwise distribute the @@ -606,7 +573,7 @@ compute_branch_probabilities (void) FOR_EACH_EDGE (e, ei, bb->succs) e->probability = REG_BR_PROB_BASE / total; } - if (bb->index >= 0 + if (bb->index >= NUM_FIXED_BLOCKS && block_ends_with_condjump_p (bb) && EDGE_COUNT (bb->succs) >= 2) num_branches++, num_never_executed; @@ -648,14 +615,13 @@ 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; - histogram_value hist; for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++) n_histogram_counters[t] = 0; for (i = 0; i < VEC_length (histogram_value, values); i++) { - hist = VEC_index (histogram_value, values, i); + histogram_value hist = VEC_index (histogram_value, values, i); n_histogram_counters[(int) hist->type] += hist->n_counters; } @@ -680,37 +646,18 @@ compute_value_histograms (histogram_values values) for (i = 0; i < VEC_length (histogram_value, values); i++) { - rtx hist_list = NULL_RTX; + histogram_value hist = VEC_index (histogram_value, values, i); + tree stmt = hist->hvalue.stmt; - hist = VEC_index (histogram_value, values, i); t = (int) hist->type; aact_count = act_count[t]; act_count[t] += hist->n_counters; - if (!ir_type ()) - { - for (j = hist->n_counters; j > 0; j--) - hist_list = alloc_EXPR_LIST (0, GEN_INT (aact_count[j - 1]), - hist_list); - hist_list = alloc_EXPR_LIST (0, - copy_rtx (hist->hvalue.rtl.value), hist_list); - hist_list = alloc_EXPR_LIST (0, GEN_INT (hist->type), hist_list); - REG_NOTES (hist->hvalue.rtl.insn) = - alloc_EXPR_LIST (REG_VALUE_PROFILE, hist_list, - REG_NOTES (hist->hvalue.rtl.insn)); - } - else - { - tree stmt = hist->hvalue.tree.stmt; - stmt_ann_t ann = get_stmt_ann (stmt); - hist->hvalue.tree.next = ann->histograms; - ann->histograms = hist; - hist->hvalue.tree.counters = - xmalloc (sizeof (gcov_type) * hist->n_counters); - for (j = 0; j < hist->n_counters; j++) - hist->hvalue.tree.counters[j] = aact_count[j]; - } + gimple_add_histogram_value (cfun, stmt, hist); + hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters); + for (j = 0; j < hist->n_counters; j++) + hist->hvalue.counters[j] = aact_count[j]; } for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++) @@ -718,7 +665,9 @@ compute_value_histograms (histogram_values values) free (histogram_counts[t]); } -#define BB_TO_GCOV_INDEX(bb) ((bb)->index + 1) +/* The entry basic block will be moved around so that it has index=1, + there is nothing at index 0 and the exit is at n_basic_block. */ +#define BB_TO_GCOV_INDEX(bb) ((bb)->index - 1) /* When passed NULL as file_name, initialize. When passed something else, output the necessary commands to change line to LINE and offset to FILE_NAME. */ @@ -820,6 +769,40 @@ branch_prob (void) FOR_EACH_EDGE (e, ei, bb->succs) { + block_stmt_iterator bsi; + tree last = NULL; + + /* It may happen that there are compiler generated statements + without a locus at all. Go through the basic block from the + last to the first statement looking for a locus. */ + for (bsi = bsi_last (bb); !bsi_end_p (bsi); bsi_prev (&bsi)) + { + last = bsi_stmt (bsi); + if (EXPR_LOCUS (last)) + break; + } + + /* 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 + if (blah) goto something; + is not computed twice. */ + if (last && EXPR_LOCUS (last) + && e->goto_locus + && !single_succ_p (bb) +#ifdef USE_MAPPED_LOCATION + && (LOCATION_FILE (e->goto_locus) + != LOCATION_FILE (EXPR_LOCATION (last)) + || (LOCATION_LINE (e->goto_locus) + != LOCATION_LINE (EXPR_LOCATION (last))))) +#else + && (e->goto_locus->file != EXPR_LOCUS (last)->file + || (e->goto_locus->line != EXPR_LOCUS (last)->line))) +#endif + { + basic_block new = split_edge (e); + single_succ_edge (new)->goto_locus = e->goto_locus; + } if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL)) && e->dest != EXIT_BLOCK_PTR) need_exit_edge = 1; @@ -897,7 +880,7 @@ branch_prob (void) num_instrumented++; } - total_num_blocks += n_basic_blocks + 2; + total_num_blocks += n_basic_blocks; if (dump_file) fprintf (dump_file, "%d basic blocks\n", n_basic_blocks); @@ -918,7 +901,7 @@ branch_prob (void) gcov_position_t offset; offset = gcov_write_tag (GCOV_TAG_BLOCKS); - for (i = 0; i != (unsigned) (n_basic_blocks + 2); i++) + for (i = 0; i != (unsigned) (n_basic_blocks); i++) gcov_write_unsigned (0); gcov_write_length (offset); } @@ -926,7 +909,7 @@ branch_prob (void) /* Keep all basic block indexes nonnegative in the gcov output. Index 0 is used for entry block, last index is for exit block. */ - ENTRY_BLOCK_PTR->index = -1; + ENTRY_BLOCK_PTR->index = 1; EXIT_BLOCK_PTR->index = last_basic_block; /* Arcs */ @@ -957,8 +940,7 @@ branch_prob (void) flag_bits |= GCOV_ARC_FALLTHROUGH; /* On trees we don't have fallthru flags, but we can recompute them from CFG shape. */ - if (ir_type () - && e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE) + if (e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE) && e->src->next_bb == e->dest) flag_bits |= GCOV_ARC_FALLTHROUGH; @@ -974,116 +956,57 @@ branch_prob (void) /* Line numbers. */ if (coverage_begin_output ()) { + gcov_position_t offset; + /* Initialize the output. */ output_location (NULL, 0, NULL, NULL); - if (!ir_type ()) + FOR_EACH_BB (bb) { - gcov_position_t offset; + block_stmt_iterator bsi; - FOR_EACH_BB (bb) - { - rtx insn = BB_HEAD (bb); - int ignore_next_note = 0; - - offset = 0; - - /* We are looking for line number notes. Search backward - before basic block to find correct ones. */ - insn = prev_nonnote_insn (insn); - if (!insn) - insn = get_insns (); - else - insn = NEXT_INSN (insn); - - while (insn != BB_END (bb)) - { - if (NOTE_P (insn)) - { - /* Must ignore the line number notes that - immediately follow the end of an inline function - to avoid counting it twice. There is a note - before the call, and one after the call. */ - if (NOTE_LINE_NUMBER (insn) - == NOTE_INSN_REPEATED_LINE_NUMBER) - ignore_next_note = 1; - else if (NOTE_LINE_NUMBER (insn) <= 0) - /*NOP*/; - else if (ignore_next_note) - ignore_next_note = 0; - else - { - expanded_location s; - NOTE_EXPANDED_LOCATION (s, insn); - output_location (s.file, s.line, &offset, bb); - } - } - insn = NEXT_INSN (insn); - } + offset = 0; - if (offset) - { - /* A file of NULL indicates the end of run. */ - gcov_write_unsigned (0); - gcov_write_string (NULL); - gcov_write_length (offset); - } + if (bb == ENTRY_BLOCK_PTR->next_bb) + { + expanded_location curr_location = + expand_location (DECL_SOURCE_LOCATION (current_function_decl)); + output_location (curr_location.file, curr_location.line, + &offset, bb); } - } - else - { - gcov_position_t offset; - FOR_EACH_BB (bb) + for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) { - block_stmt_iterator bsi; - - offset = 0; - - if (bb == ENTRY_BLOCK_PTR->next_bb) - { - expanded_location curr_location = - expand_location (DECL_SOURCE_LOCATION - (current_function_decl)); - output_location (curr_location.file, curr_location.line, - &offset, bb); - } - - for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi)) - { - tree stmt = bsi_stmt (bsi); - if (EXPR_HAS_LOCATION (stmt)) - output_location (EXPR_FILENAME (stmt), - EXPR_LINENO (stmt), - &offset, bb); - } + tree stmt = bsi_stmt (bsi); + if (EXPR_HAS_LOCATION (stmt)) + output_location (EXPR_FILENAME (stmt), EXPR_LINENO (stmt), + &offset, bb); + } - /* Notice GOTO expressions we eliminated while constructing the - CFG. */ - if (single_succ_p (bb) && single_succ_edge (bb)->goto_locus) - { - /* ??? source_locus type is marked deprecated in input.h. */ - source_locus curr_location = single_succ_edge (bb)->goto_locus; - /* ??? The FILE/LINE API is inconsistent for these cases. */ + /* Notice GOTO expressions we eliminated while constructing the + CFG. */ + if (single_succ_p (bb) && single_succ_edge (bb)->goto_locus) + { + /* ??? source_locus type is marked deprecated in input.h. */ + source_locus curr_location = single_succ_edge (bb)->goto_locus; + /* ??? The FILE/LINE API is inconsistent for these cases. */ #ifdef USE_MAPPED_LOCATION - output_location (LOCATION_FILE (curr_location), - LOCATION_LINE (curr_location), - &offset, bb); + output_location (LOCATION_FILE (curr_location), + LOCATION_LINE (curr_location), &offset, bb); #else - output_location (curr_location->file, curr_location->line, - &offset, bb); + output_location (curr_location->file, curr_location->line, + &offset, bb); #endif - } + } - if (offset) - { - /* A file of NULL indicates the end of run. */ - gcov_write_unsigned (0); - gcov_write_string (NULL); - gcov_write_length (offset); - } + if (offset) + { + /* A file of NULL indicates the end of run. */ + gcov_write_unsigned (0); + gcov_write_string (NULL); + gcov_write_length (offset); } - } + } } ENTRY_BLOCK_PTR->index = ENTRY_BLOCK; @@ -1118,26 +1041,12 @@ branch_prob (void) instrument_values (values); /* Commit changes done by instrumentation. */ - if (ir_type ()) - bsi_commit_edge_inserts (); - else - { - commit_edge_insertions_watch_calls (); - allocate_reg_info (max_reg_num (), FALSE, FALSE); - } + bsi_commit_edge_inserts (); } free_aux_for_edges (); - if (!ir_type ()) - { - /* Re-merge split basic blocks and the mess introduced by - insert_insn_on_edge. */ - cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0); - if (profile_dump_file()) - dump_flow_info (profile_dump_file()); - } - + VEC_free (histogram_value, heap, values); free_edge_list (el); if (flag_branch_probabilities) profile_status = PROFILE_READ; @@ -1317,15 +1226,7 @@ end_branch_prob (void) void tree_register_profile_hooks (void) { - gcc_assert (ir_type ()); + gcc_assert (current_ir_type () == IR_GIMPLE); profile_hooks = &tree_profile_hooks; } -/* Set up hooks to enable RTL-based profiling. */ - -void -rtl_register_profile_hooks (void) -{ - gcc_assert (!ir_type ()); - profile_hooks = &rtl_profile_hooks; -}