diff options
author | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-11-08 04:56:18 +0000 |
---|---|---|
committer | mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4> | 1999-11-08 04:56:18 +0000 |
commit | b9cf3f639cc2234b6c9b471b6ba74d75d5ba5fdd (patch) | |
tree | 208424c6ec3b805174618dc54704dbe65bd2d6fc /gcc/profile.c | |
parent | 8ad4384682a29097ed009829294323ad2ea2c37b (diff) | |
download | ppe42-gcc-b9cf3f639cc2234b6c9b471b6ba74d75d5ba5fdd.tar.gz ppe42-gcc-b9cf3f639cc2234b6c9b471b6ba74d75d5ba5fdd.zip |
* cse.c (delete_trivially_dead_insns): Replace alloca with
xmalloc/xcalloc.
* except.c (update_rethrow_references): Likewise.
(init_eh_nesting_info): Likewise.
* function.c (identify_blocks): Likewise.
* gcse.c (dump_hash_table): Likewise.
* graph.c (print_rtl_graph_with_bb): Likewise.
* loop.c (combine_movables): Likewise.
(move_movables): Likewise.
(count_loop_regs_set): Likewise.
(strength_reduce): Likewise.
* profile.c (compute_branch_probabilities): New function, split
out from ...
(branch_prob): Here. Replace alloca with xmalloc/xcalloc.
* regclass.c (regclass): Likewise.
* regmove.c (regmove_optimize): Likewise.
* toplev.c (compile_file): Likewise.
(main): Don't mess with the stack rlimit.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30445 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/profile.c')
-rw-r--r-- | gcc/profile.c | 570 |
1 files changed, 295 insertions, 275 deletions
diff --git a/gcc/profile.c b/gcc/profile.c index f691245a3a0..1e8bdf2f9d0 100644 --- a/gcc/profile.c +++ b/gcc/profile.c @@ -160,6 +160,7 @@ static void output_arc_profiler PROTO((int, rtx)); static void instrument_arcs PROTO((rtx, int, FILE *)); static void output_gcov_string PROTO((const char *, long)); static int tablejump_entry_p PROTO((rtx, rtx)); +static void compute_branch_probabilities PROTO((int, FILE *)); #ifndef LONG_TYPE_SIZE #define LONG_TYPE_SIZE BITS_PER_WORD @@ -437,6 +438,293 @@ tablejump_entry_p (insn, label) return 0; } +/* Compute the branch probabilities for the various branches. + Annotate them accordingly. */ + +static void +compute_branch_probabilities (num_blocks, dump_file) + int num_blocks; + FILE *dump_file; +{ + int i; + int bad_counts = 0; + int num_arcs; + int changes; + int passes; + int prob; + int total; + int num_branches; + int num_never_executed; + int hist_br_prob[20]; + struct adj_list *arcptr; + + /* For each arc not on the spanning tree, set its execution count from + the .da file. */ + + /* The first count in the .da file is the number of times that the function + was entered. This is the exec_count for block zero. */ + + num_arcs = 0; + for (i = 0; i < num_blocks; i++) + for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next) + if (! arcptr->on_tree) + { + num_arcs++; + if (da_file) + { + long value; + __read_long (&value, da_file, 8); + ARC_COUNT (arcptr) = value; + } + else + ARC_COUNT (arcptr) = 0; + arcptr->count_valid = 1; + bb_graph[i].succ_count--; + bb_graph[ARC_TARGET (arcptr)].pred_count--; + } + + if (dump_file) + fprintf (dump_file, "%d arc counts read\n", num_arcs); + + /* For every block in the file, + - if every exit/entrance arc has a known count, then set the block count + - if the block count is known, and every exit/entrance arc but one has + a known execution count, then set the count of the remaining arc + + As arc counts are set, decrement the succ/pred count, but don't delete + the arc, that way we can easily tell when all arcs are known, or only + one arc is unknown. */ + + /* The order that the basic blocks are iterated through is important. + Since the code that finds spanning trees starts with block 0, low numbered + arcs are put on the spanning tree in preference to high numbered arcs. + Hence, most instrumented arcs are at the end. Graph solving works much + faster if we propagate numbers from the end to the start. + + This takes an average of slightly more than 3 passes. */ + + changes = 1; + passes = 0; + while (changes) + { + passes++; + changes = 0; + + for (i = num_blocks - 1; i >= 0; i--) + { + struct bb_info *binfo = &bb_graph[i]; + if (! binfo->count_valid) + { + if (binfo->succ_count == 0) + { + total = 0; + for (arcptr = binfo->succ; arcptr; + arcptr = arcptr->succ_next) + total += ARC_COUNT (arcptr); + binfo->exec_count = total; + binfo->count_valid = 1; + changes = 1; + } + else if (binfo->pred_count == 0) + { + total = 0; + for (arcptr = binfo->pred; arcptr; + arcptr = arcptr->pred_next) + total += ARC_COUNT (arcptr); + binfo->exec_count = total; + binfo->count_valid = 1; + changes = 1; + } + } + if (binfo->count_valid) + { + if (binfo->succ_count == 1) + { + total = 0; + /* One of the counts will be invalid, but it is zero, + so adding it in also doesn't hurt. */ + for (arcptr = binfo->succ; arcptr; + arcptr = arcptr->succ_next) + total += ARC_COUNT (arcptr); + /* Calculate count for remaining arc by conservation. */ + total = binfo->exec_count - total; + /* Search for the invalid arc, and set its count. */ + for (arcptr = binfo->succ; arcptr; + arcptr = arcptr->succ_next) + if (! arcptr->count_valid) + break; + if (! arcptr) + abort (); + arcptr->count_valid = 1; + ARC_COUNT (arcptr) = total; + binfo->succ_count--; + + bb_graph[ARC_TARGET (arcptr)].pred_count--; + changes = 1; + } + if (binfo->pred_count == 1) + { + total = 0; + /* One of the counts will be invalid, but it is zero, + so adding it in also doesn't hurt. */ + for (arcptr = binfo->pred; arcptr; + arcptr = arcptr->pred_next) + total += ARC_COUNT (arcptr); + /* Calculate count for remaining arc by conservation. */ + total = binfo->exec_count - total; + /* Search for the invalid arc, and set its count. */ + for (arcptr = binfo->pred; arcptr; + arcptr = arcptr->pred_next) + if (! arcptr->count_valid) + break; + if (! arcptr) + abort (); + arcptr->count_valid = 1; + ARC_COUNT (arcptr) = total; + binfo->pred_count--; + + bb_graph[ARC_SOURCE (arcptr)].succ_count--; + changes = 1; + } + } + } + } + + total_num_passes += passes; + if (dump_file) + fprintf (dump_file, "Graph solving took %d passes.\n\n", passes); + + /* If the graph has been correctly solved, every block will have a + succ and pred count of zero. */ + for (i = 0; i < num_blocks; i++) + { + struct bb_info *binfo = &bb_graph[i]; + if (binfo->succ_count || binfo->pred_count) + abort (); + } + + /* For every arc, calculate its branch probability and add a reg_note + to the branch insn to indicate this. */ + + for (i = 0; i < 20; i++) + hist_br_prob[i] = 0; + num_never_executed = 0; + num_branches = 0; + + for (i = 0; i < num_blocks; i++) + { + struct bb_info *binfo = &bb_graph[i]; + + total = binfo->exec_count; + for (arcptr = binfo->succ; arcptr; arcptr = arcptr->succ_next) + { + if (arcptr->branch_insn) + { + /* This calculates the branch probability as an integer between + 0 and REG_BR_PROB_BASE, properly rounded to the nearest + integer. Perform the arithmetic in double to avoid + overflowing the range of ints. */ + + if (total == 0) + prob = -1; + else + { + rtx pat = PATTERN (arcptr->branch_insn); + + prob = (((double)ARC_COUNT (arcptr) * REG_BR_PROB_BASE) + + (total >> 1)) / total; + if (prob < 0 || prob > REG_BR_PROB_BASE) + { + if (dump_file) + fprintf (dump_file, "bad count: prob for %d-%d thought to be %d (forcibly normalized)\n", + ARC_SOURCE (arcptr), ARC_TARGET (arcptr), + prob); + + bad_counts = 1; + prob = REG_BR_PROB_BASE / 2; + } + + /* Match up probability with JUMP pattern. */ + + if (GET_CODE (pat) == SET + && GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE) + { + if (ARC_TARGET (arcptr) == ARC_SOURCE (arcptr) + 1) + { + /* A fall through arc should never have a + branch insn. */ + abort (); + } + else + { + /* This is the arc for the taken branch. */ + if (GET_CODE (XEXP (SET_SRC (pat), 2)) != PC) + prob = REG_BR_PROB_BASE - prob; + } + } + } + + if (prob == -1) + num_never_executed++; + else + { + int index = prob * 20 / REG_BR_PROB_BASE; + if (index == 20) + index = 19; + hist_br_prob[index]++; + } + num_branches++; + + REG_NOTES (arcptr->branch_insn) + = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob), + REG_NOTES (arcptr->branch_insn)); + } + } + + /* Add a REG_EXEC_COUNT note to the first instruction of this block. */ + if (! binfo->first_insn + || GET_RTX_CLASS (GET_CODE (binfo->first_insn)) != 'i') + { + /* Block 0 is a fake block representing function entry, and does + not have a real first insn. The second last block might not + begin with a real insn. */ + if (i == num_blocks - 1) + return_label_execution_count = total; + else if (i != 0 && i != num_blocks - 2) + abort (); + } + else + { + REG_NOTES (binfo->first_insn) + = gen_rtx_EXPR_LIST (REG_EXEC_COUNT, GEN_INT (total), + REG_NOTES (binfo->first_insn)); + if (i == num_blocks - 1) + return_label_execution_count = total; + } + } + + /* This should never happen. */ + if (bad_counts) + warning ("Arc profiling: some arc counts were bad."); + + 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", + (hist_br_prob[i]+hist_br_prob[19-i])*100/num_branches, + 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]; + } +} + /* Instrument and/or analyze program behavior based on program flow graph. In either case, this function builds a flow graph for the function being compiled. The flow graph is stored in BB_GRAPH. @@ -460,11 +748,7 @@ branch_prob (f, dump_file) { int i, num_blocks; struct adj_list *arcptr; - int num_arcs, changes, passes; - int total, prob; - int hist_br_prob[20], num_never_executed, num_branches; - /* Set to non-zero if we got bad count information. */ - int bad_counts = 0; + int num_arcs; /* start of a function. */ if (flag_test_coverage) @@ -620,8 +904,8 @@ branch_prob (f, dump_file) /* Create and initialize the arrays that will hold bb_graph and execution count info. */ - bb_graph = (struct bb_info *) alloca (num_blocks * sizeof (struct bb_info)); - bzero ((char *) bb_graph, (sizeof (struct bb_info) * num_blocks)); + bb_graph = (struct bb_info *) xcalloc (num_blocks, + sizeof (struct bb_info)); { /* Scan the insns again: @@ -965,275 +1249,11 @@ branch_prob (f, dump_file) } /* Execute the rest only if doing branch probabilities. */ - if (! flag_branch_probabilities) - return; - - /* For each arc not on the spanning tree, set its execution count from - the .da file. */ - - /* The first count in the .da file is the number of times that the function - was entered. This is the exec_count for block zero. */ - - num_arcs = 0; - for (i = 0; i < num_blocks; i++) - for (arcptr = bb_graph[i].succ; arcptr; arcptr = arcptr->succ_next) - if (! arcptr->on_tree) - { - num_arcs++; - if (da_file) - { - long value; - __read_long (&value, da_file, 8); - ARC_COUNT (arcptr) = value; - } - else - ARC_COUNT (arcptr) = 0; - arcptr->count_valid = 1; - bb_graph[i].succ_count--; - bb_graph[ARC_TARGET (arcptr)].pred_count--; - } - - if (dump_file) - fprintf (dump_file, "%d arc counts read\n", num_arcs); - - /* For every block in the file, - - if every exit/entrance arc has a known count, then set the block count - - if the block count is known, and every exit/entrance arc but one has - a known execution count, then set the count of the remaining arc - - As arc counts are set, decrement the succ/pred count, but don't delete - the arc, that way we can easily tell when all arcs are known, or only - one arc is unknown. */ - - /* The order that the basic blocks are iterated through is important. - Since the code that finds spanning trees starts with block 0, low numbered - arcs are put on the spanning tree in preference to high numbered arcs. - Hence, most instrumented arcs are at the end. Graph solving works much - faster if we propagate numbers from the end to the start. - - This takes an average of slightly more than 3 passes. */ - - changes = 1; - passes = 0; - while (changes) - { - passes++; - changes = 0; - - for (i = num_blocks - 1; i >= 0; i--) - { - struct bb_info *binfo = &bb_graph[i]; - if (! binfo->count_valid) - { - if (binfo->succ_count == 0) - { - total = 0; - for (arcptr = binfo->succ; arcptr; - arcptr = arcptr->succ_next) - total += ARC_COUNT (arcptr); - binfo->exec_count = total; - binfo->count_valid = 1; - changes = 1; - } - else if (binfo->pred_count == 0) - { - total = 0; - for (arcptr = binfo->pred; arcptr; - arcptr = arcptr->pred_next) - total += ARC_COUNT (arcptr); - binfo->exec_count = total; - binfo->count_valid = 1; - changes = 1; - } - } - if (binfo->count_valid) - { - if (binfo->succ_count == 1) - { - total = 0; - /* One of the counts will be invalid, but it is zero, - so adding it in also doesn't hurt. */ - for (arcptr = binfo->succ; arcptr; - arcptr = arcptr->succ_next) - total += ARC_COUNT (arcptr); - /* Calculate count for remaining arc by conservation. */ - total = binfo->exec_count - total; - /* Search for the invalid arc, and set its count. */ - for (arcptr = binfo->succ; arcptr; - arcptr = arcptr->succ_next) - if (! arcptr->count_valid) - break; - if (! arcptr) - abort (); - arcptr->count_valid = 1; - ARC_COUNT (arcptr) = total; - binfo->succ_count--; - - bb_graph[ARC_TARGET (arcptr)].pred_count--; - changes = 1; - } - if (binfo->pred_count == 1) - { - total = 0; - /* One of the counts will be invalid, but it is zero, - so adding it in also doesn't hurt. */ - for (arcptr = binfo->pred; arcptr; - arcptr = arcptr->pred_next) - total += ARC_COUNT (arcptr); - /* Calculate count for remaining arc by conservation. */ - total = binfo->exec_count - total; - /* Search for the invalid arc, and set its count. */ - for (arcptr = binfo->pred; arcptr; - arcptr = arcptr->pred_next) - if (! arcptr->count_valid) - break; - if (! arcptr) - abort (); - arcptr->count_valid = 1; - ARC_COUNT (arcptr) = total; - binfo->pred_count--; - - bb_graph[ARC_SOURCE (arcptr)].succ_count--; - changes = 1; - } - } - } - } - - total_num_passes += passes; - if (dump_file) - fprintf (dump_file, "Graph solving took %d passes.\n\n", passes); - - /* If the graph has been correctly solved, every block will have a - succ and pred count of zero. */ - for (i = 0; i < num_blocks; i++) - { - struct bb_info *binfo = &bb_graph[i]; - if (binfo->succ_count || binfo->pred_count) - abort (); - } - - /* For every arc, calculate its branch probability and add a reg_note - to the branch insn to indicate this. */ - - for (i = 0; i < 20; i++) - hist_br_prob[i] = 0; - num_never_executed = 0; - num_branches = 0; - - for (i = 0; i < num_blocks; i++) - { - struct bb_info *binfo = &bb_graph[i]; - - total = binfo->exec_count; - for (arcptr = binfo->succ; arcptr; arcptr = arcptr->succ_next) - { - if (arcptr->branch_insn) - { - /* This calculates the branch probability as an integer between - 0 and REG_BR_PROB_BASE, properly rounded to the nearest - integer. Perform the arithmetic in double to avoid - overflowing the range of ints. */ - - if (total == 0) - prob = -1; - else - { - rtx pat = PATTERN (arcptr->branch_insn); - - prob = (((double)ARC_COUNT (arcptr) * REG_BR_PROB_BASE) - + (total >> 1)) / total; - if (prob < 0 || prob > REG_BR_PROB_BASE) - { - if (dump_file) - fprintf (dump_file, "bad count: prob for %d-%d thought to be %d (forcibly normalized)\n", - ARC_SOURCE (arcptr), ARC_TARGET (arcptr), - prob); - - bad_counts = 1; - prob = REG_BR_PROB_BASE / 2; - } - - /* Match up probability with JUMP pattern. */ - - if (GET_CODE (pat) == SET - && GET_CODE (SET_SRC (pat)) == IF_THEN_ELSE) - { - if (ARC_TARGET (arcptr) == ARC_SOURCE (arcptr) + 1) - { - /* A fall through arc should never have a - branch insn. */ - abort (); - } - else - { - /* This is the arc for the taken branch. */ - if (GET_CODE (XEXP (SET_SRC (pat), 2)) != PC) - prob = REG_BR_PROB_BASE - prob; - } - } - } - - if (prob == -1) - num_never_executed++; - else - { - int index = prob * 20 / REG_BR_PROB_BASE; - if (index == 20) - index = 19; - hist_br_prob[index]++; - } - num_branches++; - - REG_NOTES (arcptr->branch_insn) - = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob), - REG_NOTES (arcptr->branch_insn)); - } - } - - /* Add a REG_EXEC_COUNT note to the first instruction of this block. */ - if (! binfo->first_insn - || GET_RTX_CLASS (GET_CODE (binfo->first_insn)) != 'i') - { - /* Block 0 is a fake block representing function entry, and does - not have a real first insn. The second last block might not - begin with a real insn. */ - if (i == num_blocks - 1) - return_label_execution_count = total; - else if (i != 0 && i != num_blocks - 2) - abort (); - } - else - { - REG_NOTES (binfo->first_insn) - = gen_rtx_EXPR_LIST (REG_EXEC_COUNT, GEN_INT (total), - REG_NOTES (binfo->first_insn)); - if (i == num_blocks - 1) - return_label_execution_count = total; - } - } - - /* This should never happen. */ - if (bad_counts) - warning ("Arc profiling: some arc counts were bad."); - - 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", - (hist_br_prob[i]+hist_br_prob[19-i])*100/num_branches, - 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]; - } + if (flag_branch_probabilities) + compute_branch_probabilities (num_blocks, dump_file); + /* Clean up. */ + free (bb_graph); } /* Initialize a new arc. |