00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 #include "config.h"
00053 #include "system.h"
00054 #include "coretypes.h"
00055 #include "tm.h"
00056 #include "rtl.h"
00057 #include "flags.h"
00058 #include "output.h"
00059 #include "regs.h"
00060 #include "expr.h"
00061 #include "function.h"
00062 #include "toplev.h"
00063 #include "coverage.h"
00064 #include "value-prof.h"
00065 #include "tree.h"
00066 #include "cfghooks.h"
00067 #include "tree-flow.h"
00068
00069
00070 static struct profile_hooks* profile_hooks;
00071
00072
00073 static inline FILE*
00074 profile_dump_file (void) {
00075 return profile_hooks->profile_dump_file ();
00076 }
00077
00078
00079 struct edge_info {
00080 unsigned int count_valid : 1;
00081
00082
00083 unsigned int on_tree : 1;
00084
00085
00086
00087 unsigned int ignore : 1;
00088 };
00089
00090 struct bb_info {
00091 unsigned int count_valid : 1;
00092
00093
00094 gcov_type succ_count;
00095 gcov_type pred_count;
00096 };
00097
00098 #define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
00099 #define BB_INFO(b) ((struct bb_info *) (b)->aux)
00100
00101
00102
00103 const struct gcov_ctr_summary *profile_info;
00104
00105
00106
00107
00108 static int total_num_blocks;
00109 static int total_num_edges;
00110 static int total_num_edges_ignored;
00111 static int total_num_edges_instrumented;
00112 static int total_num_blocks_created;
00113 static int total_num_passes;
00114 static int total_num_times_called;
00115 static int total_hist_br_prob[20];
00116 static int total_num_never_executed;
00117 static int total_num_branches;
00118
00119
00120 static void find_spanning_tree (struct edge_list *);
00121 static unsigned instrument_edges (struct edge_list *);
00122 static void instrument_values (histogram_values);
00123 static void compute_branch_probabilities (void);
00124 static void compute_value_histograms (histogram_values);
00125 static gcov_type * get_exec_counts (void);
00126 static basic_block find_group (basic_block);
00127 static void union_groups (basic_block, basic_block);
00128
00129
00130
00131
00132
00133
00134
00135 static unsigned
00136 instrument_edges (struct edge_list *el)
00137 {
00138 unsigned num_instr_edges = 0;
00139 int num_edges = NUM_EDGES (el);
00140 basic_block bb;
00141
00142 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00143 {
00144 edge e;
00145 edge_iterator ei;
00146
00147 FOR_EACH_EDGE (e, ei, bb->succs)
00148 {
00149 struct edge_info *inf = EDGE_INFO (e);
00150
00151 if (!inf->ignore && !inf->on_tree)
00152 {
00153 if (e->flags & EDGE_ABNORMAL)
00154 abort ();
00155 if (dump_file)
00156 fprintf (dump_file, "Edge %d to %d instrumented%s\n",
00157 e->src->index, e->dest->index,
00158 EDGE_CRITICAL_P (e) ? " (and split)" : "");
00159 (profile_hooks->gen_edge_profiler) (num_instr_edges++, e);
00160 }
00161 }
00162 }
00163
00164 total_num_blocks_created += num_edges;
00165 if (dump_file)
00166 fprintf (dump_file, "%d edges instrumented\n", num_instr_edges);
00167 return num_instr_edges;
00168 }
00169
00170
00171 static void
00172 instrument_values (histogram_values values)
00173 {
00174 unsigned i, t;
00175
00176
00177
00178 for (i = 0; i < VEC_length (histogram_value, values); i++)
00179 {
00180 histogram_value hist = VEC_index (histogram_value, values, i);
00181 switch (hist->type)
00182 {
00183 case HIST_TYPE_INTERVAL:
00184 t = GCOV_COUNTER_V_INTERVAL;
00185 break;
00186
00187 case HIST_TYPE_POW2:
00188 t = GCOV_COUNTER_V_POW2;
00189 break;
00190
00191 case HIST_TYPE_SINGLE_VALUE:
00192 t = GCOV_COUNTER_V_SINGLE;
00193 break;
00194
00195 case HIST_TYPE_CONST_DELTA:
00196 t = GCOV_COUNTER_V_DELTA;
00197 break;
00198
00199 default:
00200 abort ();
00201 }
00202 if (!coverage_counter_alloc (t, hist->n_counters))
00203 continue;
00204
00205 switch (hist->type)
00206 {
00207 case HIST_TYPE_INTERVAL:
00208 (profile_hooks->gen_interval_profiler) (hist, t, 0);
00209 break;
00210
00211 case HIST_TYPE_POW2:
00212 (profile_hooks->gen_pow2_profiler) (hist, t, 0);
00213 break;
00214
00215 case HIST_TYPE_SINGLE_VALUE:
00216 (profile_hooks->gen_one_value_profiler) (hist, t, 0);
00217 break;
00218
00219 case HIST_TYPE_CONST_DELTA:
00220 (profile_hooks->gen_const_delta_profiler) (hist, t, 0);
00221 break;
00222
00223 default:
00224 abort ();
00225 }
00226 }
00227 }
00228
00229
00230
00231
00232 static gcov_type *
00233 get_exec_counts (void)
00234 {
00235 unsigned num_edges = 0;
00236 basic_block bb;
00237 gcov_type *counts;
00238
00239
00240 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00241 {
00242 edge e;
00243 edge_iterator ei;
00244
00245 FOR_EACH_EDGE (e, ei, bb->succs)
00246 if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
00247 num_edges++;
00248 }
00249
00250 counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, &profile_info);
00251 if (!counts)
00252 return NULL;
00253
00254 if (dump_file && profile_info)
00255 fprintf(dump_file, "Merged %u profiles with maximal count %u.\n",
00256 profile_info->runs, (unsigned) profile_info->sum_max);
00257
00258 return counts;
00259 }
00260
00261
00262
00263
00264
00265 static void
00266 compute_branch_probabilities (void)
00267 {
00268 basic_block bb;
00269 int i;
00270 int num_edges = 0;
00271 int changes;
00272 int passes;
00273 int hist_br_prob[20];
00274 int num_never_executed;
00275 int num_branches;
00276 gcov_type *exec_counts = get_exec_counts ();
00277 int exec_counts_pos = 0;
00278
00279
00280 if (profile_info)
00281 {
00282 if (profile_info->run_max * profile_info->runs < profile_info->sum_max)
00283 {
00284 error ("corrupted profile info: run_max * runs < sum_max");
00285 exec_counts = NULL;
00286 }
00287
00288 if (profile_info->sum_all < profile_info->sum_max)
00289 {
00290 error ("corrupted profile info: sum_all is smaller than sum_max");
00291 exec_counts = NULL;
00292 }
00293 }
00294
00295
00296
00297 alloc_aux_for_blocks (sizeof (struct bb_info));
00298 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00299 {
00300 edge e;
00301 edge_iterator ei;
00302
00303 FOR_EACH_EDGE (e, ei, bb->succs)
00304 if (!EDGE_INFO (e)->ignore)
00305 BB_INFO (bb)->succ_count++;
00306 FOR_EACH_EDGE (e, ei, bb->preds)
00307 if (!EDGE_INFO (e)->ignore)
00308 BB_INFO (bb)->pred_count++;
00309 }
00310
00311
00312 BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
00313 BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;
00314
00315
00316
00317
00318
00319
00320
00321 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00322 {
00323 edge e;
00324 edge_iterator ei;
00325
00326 FOR_EACH_EDGE (e, ei, bb->succs)
00327 if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
00328 {
00329 num_edges++;
00330 if (exec_counts)
00331 {
00332 e->count = exec_counts[exec_counts_pos++];
00333 if (e->count > profile_info->sum_max)
00334 {
00335 error ("corrupted profile info: edge from %i to %i exceeds maximal count",
00336 bb->index, e->dest->index);
00337 }
00338 }
00339 else
00340 e->count = 0;
00341
00342 EDGE_INFO (e)->count_valid = 1;
00343 BB_INFO (bb)->succ_count--;
00344 BB_INFO (e->dest)->pred_count--;
00345 if (dump_file)
00346 {
00347 fprintf (dump_file, "\nRead edge from %i to %i, count:",
00348 bb->index, e->dest->index);
00349 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
00350 (HOST_WIDEST_INT) e->count);
00351 }
00352 }
00353 }
00354
00355 if (dump_file)
00356 fprintf (dump_file, "\n%d edge counts read\n", num_edges);
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375 changes = 1;
00376 passes = 0;
00377 while (changes)
00378 {
00379 passes++;
00380 changes = 0;
00381 FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
00382 {
00383 struct bb_info *bi = BB_INFO (bb);
00384 if (! bi->count_valid)
00385 {
00386 if (bi->succ_count == 0)
00387 {
00388 edge e;
00389 edge_iterator ei;
00390 gcov_type total = 0;
00391
00392 FOR_EACH_EDGE (e, ei, bb->succs)
00393 total += e->count;
00394 bb->count = total;
00395 bi->count_valid = 1;
00396 changes = 1;
00397 }
00398 else if (bi->pred_count == 0)
00399 {
00400 edge e;
00401 edge_iterator ei;
00402 gcov_type total = 0;
00403
00404 FOR_EACH_EDGE (e, ei, bb->preds)
00405 total += e->count;
00406 bb->count = total;
00407 bi->count_valid = 1;
00408 changes = 1;
00409 }
00410 }
00411 if (bi->count_valid)
00412 {
00413 if (bi->succ_count == 1)
00414 {
00415 edge e;
00416 edge_iterator ei;
00417 gcov_type total = 0;
00418
00419
00420
00421 FOR_EACH_EDGE (e, ei, bb->succs)
00422 total += e->count;
00423
00424
00425 FOR_EACH_EDGE (e, ei, bb->succs)
00426 if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
00427 break;
00428
00429
00430 total = bb->count - total;
00431
00432 if (! e)
00433 abort ();
00434 EDGE_INFO (e)->count_valid = 1;
00435 e->count = total;
00436 bi->succ_count--;
00437
00438 BB_INFO (e->dest)->pred_count--;
00439 changes = 1;
00440 }
00441 if (bi->pred_count == 1)
00442 {
00443 edge e;
00444 edge_iterator ei;
00445 gcov_type total = 0;
00446
00447
00448
00449 FOR_EACH_EDGE (e, ei, bb->preds)
00450 total += e->count;
00451
00452
00453 FOR_EACH_EDGE (e, ei, bb->preds)
00454 if (!EDGE_INFO (e)->count_valid && !EDGE_INFO (e)->ignore)
00455 break;
00456
00457
00458 total = bb->count - total + e->count;
00459
00460 if (! e)
00461 abort ();
00462 EDGE_INFO (e)->count_valid = 1;
00463 e->count = total;
00464 bi->pred_count--;
00465
00466 BB_INFO (e->src)->succ_count--;
00467 changes = 1;
00468 }
00469 }
00470 }
00471 }
00472 if (dump_file)
00473 dump_flow_info (dump_file);
00474
00475 total_num_passes += passes;
00476 if (dump_file)
00477 fprintf (dump_file, "Graph solving took %d passes.\n\n", passes);
00478
00479
00480
00481 FOR_EACH_BB (bb)
00482 {
00483 if (BB_INFO (bb)->succ_count || BB_INFO (bb)->pred_count)
00484 abort ();
00485 }
00486
00487
00488
00489
00490 for (i = 0; i < 20; i++)
00491 hist_br_prob[i] = 0;
00492 num_never_executed = 0;
00493 num_branches = 0;
00494
00495 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
00496 {
00497 edge e;
00498 edge_iterator ei;
00499 rtx note;
00500
00501 if (bb->count < 0)
00502 {
00503 error ("corrupted profile info: number of iterations for basic block %d thought to be %i",
00504 bb->index, (int)bb->count);
00505 bb->count = 0;
00506 }
00507 FOR_EACH_EDGE (e, ei, bb->succs)
00508 {
00509
00510
00511
00512
00513
00514 if ((e->count < 0
00515 && e->dest == EXIT_BLOCK_PTR)
00516 || (e->count > bb->count
00517 && e->dest != EXIT_BLOCK_PTR))
00518 {
00519 if (block_ends_with_call_p (bb))
00520 e->count = e->count < 0 ? 0 : bb->count;
00521 }
00522 if (e->count < 0 || e->count > bb->count)
00523 {
00524 error ("corrupted profile info: number of executions for edge %d-%d thought to be %i",
00525 e->src->index, e->dest->index,
00526 (int)e->count);
00527 e->count = bb->count / 2;
00528 }
00529 }
00530 if (bb->count)
00531 {
00532 FOR_EACH_EDGE (e, ei, bb->succs)
00533 e->probability = (e->count * REG_BR_PROB_BASE + bb->count / 2) / bb->count;
00534 if (bb->index >= 0
00535 && block_ends_with_condjump_p (bb)
00536 && EDGE_COUNT (bb->succs) >= 2)
00537 {
00538 int prob;
00539 edge e;
00540 int index;
00541
00542
00543
00544 FOR_EACH_EDGE (e, ei, bb->succs)
00545 if (!(e->flags & (EDGE_FAKE | EDGE_FALLTHRU)))
00546 break;
00547
00548 prob = e->probability;
00549 index = prob * 20 / REG_BR_PROB_BASE;
00550
00551 if (index == 20)
00552 index = 19;
00553 hist_br_prob[index]++;
00554
00555
00556 if (!ir_type ())
00557 {
00558 note = find_reg_note (BB_END (bb), REG_BR_PROB, 0);
00559
00560
00561 if (note)
00562 XEXP (note, 0) = GEN_INT (prob);
00563 else
00564 REG_NOTES (BB_END (bb))
00565 = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
00566 REG_NOTES (BB_END (bb)));
00567 }
00568 num_branches++;
00569 }
00570 }
00571
00572
00573
00574
00575 else if (profile_status == PROFILE_ABSENT
00576 && !ir_type ()
00577 && EDGE_COUNT (bb->succs) > 1
00578 && BB_END (bb)
00579 && (note = find_reg_note (BB_END (bb), REG_BR_PROB, 0)))
00580 {
00581 int prob = INTVAL (XEXP (note, 0));
00582
00583 BRANCH_EDGE (bb)->probability = prob;
00584 FALLTHRU_EDGE (bb)->probability = REG_BR_PROB_BASE - prob;
00585 }
00586
00587
00588
00589
00590
00591 else if (profile_status == PROFILE_ABSENT)
00592 {
00593 int total = 0;
00594
00595 FOR_EACH_EDGE (e, ei, bb->succs)
00596 if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
00597 total ++;
00598 if (total)
00599 {
00600 FOR_EACH_EDGE (e, ei, bb->succs)
00601 if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
00602 e->probability = REG_BR_PROB_BASE / total;
00603 else
00604 e->probability = 0;
00605 }
00606 else
00607 {
00608 total += EDGE_COUNT (bb->succs);
00609 FOR_EACH_EDGE (e, ei, bb->succs)
00610 e->probability = REG_BR_PROB_BASE / total;
00611 }
00612 if (bb->index >= 0
00613 && block_ends_with_condjump_p (bb)
00614 && EDGE_COUNT (bb->succs) >= 2)
00615 num_branches++, num_never_executed;
00616 }
00617 }
00618 counts_to_freqs ();
00619
00620 if (dump_file)
00621 {
00622 fprintf (dump_file, "%d branches\n", num_branches);
00623 fprintf (dump_file, "%d branches never executed\n",
00624 num_never_executed);
00625 if (num_branches)
00626 for (i = 0; i < 10; i++)
00627 fprintf (dump_file, "%d%% branches in range %d-%d%%\n",
00628 (hist_br_prob[i] + hist_br_prob[19-i]) * 100 / num_branches,
00629 5 * i, 5 * i + 5);
00630
00631 total_num_branches += num_branches;
00632 total_num_never_executed += num_never_executed;
00633 for (i = 0; i < 20; i++)
00634 total_hist_br_prob[i] += hist_br_prob[i];
00635
00636 fputc ('\n', dump_file);
00637 fputc ('\n', dump_file);
00638 }
00639
00640 free_aux_for_blocks ();
00641 }
00642
00643
00644
00645
00646 static void
00647 compute_value_histograms (histogram_values values)
00648 {
00649 unsigned i, j, t, any;
00650 unsigned n_histogram_counters[GCOV_N_VALUE_COUNTERS];
00651 gcov_type *histogram_counts[GCOV_N_VALUE_COUNTERS];
00652 gcov_type *act_count[GCOV_N_VALUE_COUNTERS];
00653 gcov_type *aact_count;
00654 histogram_value hist;
00655
00656 for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
00657 n_histogram_counters[t] = 0;
00658
00659 for (i = 0; i < VEC_length (histogram_value, values); i++)
00660 {
00661 hist = VEC_index (histogram_value, values, i);
00662 n_histogram_counters[(int) hist->type] += hist->n_counters;
00663 }
00664
00665 any = 0;
00666 for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
00667 {
00668 if (!n_histogram_counters[t])
00669 {
00670 histogram_counts[t] = NULL;
00671 continue;
00672 }
00673
00674 histogram_counts[t] =
00675 get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
00676 n_histogram_counters[t], NULL);
00677 if (histogram_counts[t])
00678 any = 1;
00679 act_count[t] = histogram_counts[t];
00680 }
00681 if (!any)
00682 return;
00683
00684 for (i = 0; i < VEC_length (histogram_value, values); i++)
00685 {
00686 rtx hist_list = NULL_RTX;
00687
00688 hist = VEC_index (histogram_value, values, i);
00689 t = (int) hist->type;
00690
00691
00692 if (!ir_type ())
00693 {
00694 aact_count = act_count[t];
00695 act_count[t] += hist->n_counters;
00696 for (j = hist->n_counters; j > 0; j--)
00697 hist_list = alloc_EXPR_LIST (0, GEN_INT (aact_count[j - 1]),
00698 hist_list);
00699 hist_list = alloc_EXPR_LIST (0,
00700 copy_rtx ((rtx) hist->value), hist_list);
00701 hist_list = alloc_EXPR_LIST (0, GEN_INT (hist->type), hist_list);
00702 REG_NOTES ((rtx) hist->insn) =
00703 alloc_EXPR_LIST (REG_VALUE_PROFILE, hist_list,
00704 REG_NOTES ((rtx) hist->insn));
00705 }
00706 }
00707
00708 for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
00709 if (histogram_counts[t])
00710 free (histogram_counts[t]);
00711 }
00712
00713 #define BB_TO_GCOV_INDEX(bb) ((bb)->index + 1)
00714
00715
00716
00717 static void
00718 output_location (char const *file_name, int line,
00719 gcov_position_t *offset, basic_block bb)
00720 {
00721 static char const *prev_file_name;
00722 static int prev_line;
00723 bool name_differs, line_differs;
00724
00725 if (!file_name)
00726 {
00727 prev_file_name = NULL;
00728 prev_line = -1;
00729 return;
00730 }
00731
00732 name_differs = !prev_file_name || strcmp (file_name, prev_file_name);
00733 line_differs = prev_line != line;
00734
00735 if (name_differs || line_differs)
00736 {
00737 if (!*offset)
00738 {
00739 *offset = gcov_write_tag (GCOV_TAG_LINES);
00740 gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
00741 name_differs = line_differs=true;
00742 }
00743
00744
00745
00746 if (name_differs)
00747 {
00748 prev_file_name = file_name;
00749 gcov_write_unsigned (0);
00750 gcov_write_string (prev_file_name);
00751 }
00752 if (line_differs)
00753 {
00754 gcov_write_unsigned (line);
00755 prev_line = line;
00756 }
00757 }
00758 }
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776 void
00777 branch_prob (void)
00778 {
00779 basic_block bb;
00780 unsigned i;
00781 unsigned num_edges, ignored_edges;
00782 unsigned num_instrumented;
00783 struct edge_list *el;
00784 histogram_values values = NULL;
00785
00786 total_num_times_called++;
00787
00788 flow_call_edges_add (NULL);
00789 add_noreturn_fake_exit_edges ();
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 FOR_EACH_BB (bb)
00801 {
00802 int need_exit_edge = 0, need_entry_edge = 0;
00803 int have_exit_edge = 0, have_entry_edge = 0;
00804 edge e;
00805 edge_iterator ei;
00806
00807
00808
00809
00810
00811
00812
00813 FOR_EACH_EDGE (e, ei, bb->succs)
00814 {
00815 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
00816 && e->dest != EXIT_BLOCK_PTR)
00817 need_exit_edge = 1;
00818 if (e->dest == EXIT_BLOCK_PTR)
00819 have_exit_edge = 1;
00820 }
00821 FOR_EACH_EDGE (e, ei, bb->preds)
00822 {
00823 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
00824 && e->src != ENTRY_BLOCK_PTR)
00825 need_entry_edge = 1;
00826 if (e->src == ENTRY_BLOCK_PTR)
00827 have_entry_edge = 1;
00828 }
00829
00830 if (need_exit_edge && !have_exit_edge)
00831 {
00832 if (dump_file)
00833 fprintf (dump_file, "Adding fake exit edge to bb %i\n",
00834 bb->index);
00835 make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
00836 }
00837 if (need_entry_edge && !have_entry_edge)
00838 {
00839 if (dump_file)
00840 fprintf (dump_file, "Adding fake entry edge to bb %i\n",
00841 bb->index);
00842 make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
00843 }
00844 }
00845
00846 el = create_edge_list ();
00847 num_edges = NUM_EDGES (el);
00848 alloc_aux_for_edges (sizeof (struct edge_info));
00849
00850
00851 compact_blocks ();
00852
00853 ignored_edges = 0;
00854 for (i = 0 ; i < num_edges ; i++)
00855 {
00856 edge e = INDEX_EDGE (el, i);
00857 e->count = 0;
00858
00859
00860 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
00861 && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
00862 {
00863 EDGE_INFO (e)->ignore = 1;
00864 ignored_edges++;
00865 }
00866 }
00867
00868
00869
00870
00871
00872 find_spanning_tree (el);
00873
00874
00875
00876 for (num_instrumented = i = 0; i < num_edges; i++)
00877 {
00878 edge e = INDEX_EDGE (el, i);
00879 struct edge_info *inf = EDGE_INFO (e);
00880
00881 if (inf->ignore || inf->on_tree)
00882 ;
00883 else if (e->flags & EDGE_FAKE)
00884 {
00885 inf->ignore = 1;
00886 ignored_edges++;
00887 }
00888 else
00889 num_instrumented++;
00890 }
00891
00892 total_num_blocks += n_basic_blocks + 2;
00893 if (dump_file)
00894 fprintf (dump_file, "%d basic blocks\n", n_basic_blocks);
00895
00896 total_num_edges += num_edges;
00897 if (dump_file)
00898 fprintf (dump_file, "%d edges\n", num_edges);
00899
00900 total_num_edges_ignored += ignored_edges;
00901 if (dump_file)
00902 fprintf (dump_file, "%d ignored edges\n", ignored_edges);
00903
00904
00905
00906
00907
00908 if (coverage_begin_output ())
00909 {
00910 gcov_position_t offset;
00911
00912 offset = gcov_write_tag (GCOV_TAG_BLOCKS);
00913 for (i = 0; i != (unsigned) (n_basic_blocks + 2); i++)
00914 gcov_write_unsigned (0);
00915 gcov_write_length (offset);
00916 }
00917
00918
00919
00920
00921 ENTRY_BLOCK_PTR->index = -1;
00922 EXIT_BLOCK_PTR->index = last_basic_block;
00923
00924
00925 if (coverage_begin_output ())
00926 {
00927 gcov_position_t offset;
00928
00929 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
00930 {
00931 edge e;
00932 edge_iterator ei;
00933
00934 offset = gcov_write_tag (GCOV_TAG_ARCS);
00935 gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
00936
00937 FOR_EACH_EDGE (e, ei, bb->succs)
00938 {
00939 struct edge_info *i = EDGE_INFO (e);
00940 if (!i->ignore)
00941 {
00942 unsigned flag_bits = 0;
00943
00944 if (i->on_tree)
00945 flag_bits |= GCOV_ARC_ON_TREE;
00946 if (e->flags & EDGE_FAKE)
00947 flag_bits |= GCOV_ARC_FAKE;
00948 if (e->flags & EDGE_FALLTHRU)
00949 flag_bits |= GCOV_ARC_FALLTHROUGH;
00950
00951
00952 if (ir_type ()
00953 && e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)
00954 && e->src->next_bb == e->dest)
00955 flag_bits |= GCOV_ARC_FALLTHROUGH;
00956
00957 gcov_write_unsigned (BB_TO_GCOV_INDEX (e->dest));
00958 gcov_write_unsigned (flag_bits);
00959 }
00960 }
00961
00962 gcov_write_length (offset);
00963 }
00964 }
00965
00966
00967 if (coverage_begin_output ())
00968 {
00969
00970 output_location (NULL, 0, NULL, NULL);
00971
00972 if (!ir_type ())
00973 {
00974 gcov_position_t offset;
00975
00976 FOR_EACH_BB (bb)
00977 {
00978 rtx insn = BB_HEAD (bb);
00979 int ignore_next_note = 0;
00980
00981 offset = 0;
00982
00983
00984
00985 insn = prev_nonnote_insn (insn);
00986 if (!insn)
00987 insn = get_insns ();
00988 else
00989 insn = NEXT_INSN (insn);
00990
00991 while (insn != BB_END (bb))
00992 {
00993 if (NOTE_P (insn))
00994 {
00995
00996
00997
00998
00999 if (NOTE_LINE_NUMBER (insn)
01000 == NOTE_INSN_REPEATED_LINE_NUMBER)
01001 ignore_next_note = 1;
01002 else if (NOTE_LINE_NUMBER (insn) <= 0)
01003 ;
01004 else if (ignore_next_note)
01005 ignore_next_note = 0;
01006 else
01007 {
01008 expanded_location s;
01009 NOTE_EXPANDED_LOCATION (s, insn);
01010 output_location (s.file, s.line, &offset, bb);
01011 }
01012 }
01013 insn = NEXT_INSN (insn);
01014 }
01015
01016 if (offset)
01017 {
01018
01019 gcov_write_unsigned (0);
01020 gcov_write_string (NULL);
01021 gcov_write_length (offset);
01022 }
01023 }
01024 }
01025 else
01026 {
01027 gcov_position_t offset;
01028
01029 FOR_EACH_BB (bb)
01030 {
01031 block_stmt_iterator bsi;
01032
01033 offset = 0;
01034
01035 if (bb == ENTRY_BLOCK_PTR->next_bb)
01036 {
01037 expanded_location curr_location =
01038 expand_location (DECL_SOURCE_LOCATION
01039 (current_function_decl));
01040 output_location (curr_location.file, curr_location.line,
01041 &offset, bb);
01042 }
01043
01044 for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
01045 {
01046 tree stmt = bsi_stmt (bsi);
01047 if (EXPR_HAS_LOCATION (stmt))
01048 output_location (EXPR_FILENAME (stmt),
01049 EXPR_LINENO (stmt),
01050 &offset, bb);
01051 }
01052
01053
01054
01055 if (EDGE_COUNT (bb->succs) == 1 && EDGE_SUCC (bb, 0)->goto_locus)
01056 {
01057
01058 source_locus curr_location = EDGE_SUCC (bb, 0)->goto_locus;
01059
01060 #ifdef USE_MAPPED_LOCATION
01061 output_location (LOCATION_FILE (curr_location),
01062 LOCATION_LINE (curr_location),
01063 &offset, bb);
01064 #else
01065 output_location (curr_location->file, curr_location->line,
01066 &offset, bb);
01067 #endif
01068 }
01069
01070 if (offset)
01071 {
01072
01073 gcov_write_unsigned (0);
01074 gcov_write_string (NULL);
01075 gcov_write_length (offset);
01076 }
01077 }
01078 }
01079 }
01080
01081 ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
01082 EXIT_BLOCK_PTR->index = EXIT_BLOCK;
01083 #undef BB_TO_GCOV_INDEX
01084
01085 if (flag_profile_values)
01086 find_values_to_profile (&values);
01087
01088 if (flag_branch_probabilities)
01089 {
01090 compute_branch_probabilities ();
01091 if (flag_profile_values)
01092 compute_value_histograms (values);
01093 }
01094
01095 remove_fake_edges ();
01096
01097
01098 if (profile_arc_flag
01099 && coverage_counter_alloc (GCOV_COUNTER_ARCS, num_instrumented))
01100 {
01101 unsigned n_instrumented;
01102
01103 profile_hooks->init_edge_profiler ();
01104
01105 n_instrumented = instrument_edges (el);
01106
01107 if (n_instrumented != num_instrumented)
01108 abort ();
01109
01110 if (flag_profile_values)
01111 instrument_values (values);
01112
01113
01114 if (ir_type ())
01115 bsi_commit_edge_inserts ();
01116 else
01117 {
01118 commit_edge_insertions_watch_calls ();
01119 allocate_reg_info (max_reg_num (), FALSE, FALSE);
01120 }
01121 }
01122
01123 free_aux_for_edges ();
01124
01125 if (!ir_type ())
01126 {
01127
01128
01129 cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
01130 if (profile_dump_file())
01131 dump_flow_info (profile_dump_file());
01132 }
01133
01134 free_edge_list (el);
01135 if (flag_branch_probabilities)
01136 profile_status = PROFILE_READ;
01137 }
01138
01139
01140
01141
01142 static basic_block
01143 find_group (basic_block bb)
01144 {
01145 basic_block group = bb, bb1;
01146
01147 while ((basic_block) group->aux != group)
01148 group = (basic_block) group->aux;
01149
01150
01151 while ((basic_block) bb->aux != group)
01152 {
01153 bb1 = (basic_block) bb->aux;
01154 bb->aux = (void *) group;
01155 bb = bb1;
01156 }
01157 return group;
01158 }
01159
01160 static void
01161 union_groups (basic_block bb1, basic_block bb2)
01162 {
01163 basic_block bb1g = find_group (bb1);
01164 basic_block bb2g = find_group (bb2);
01165
01166
01167
01168 if (bb1g == bb2g)
01169 abort ();
01170
01171 bb1g->aux = bb2g;
01172 }
01173
01174
01175
01176
01177
01178
01179
01180
01181 static void
01182 find_spanning_tree (struct edge_list *el)
01183 {
01184 int i;
01185 int num_edges = NUM_EDGES (el);
01186 basic_block bb;
01187
01188
01189 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
01190 bb->aux = bb;
01191
01192
01193 union_groups (EXIT_BLOCK_PTR, ENTRY_BLOCK_PTR);
01194
01195
01196
01197
01198 for (i = 0; i < num_edges; i++)
01199 {
01200 edge e = INDEX_EDGE (el, i);
01201 if (((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
01202 || e->dest == EXIT_BLOCK_PTR)
01203 && !EDGE_INFO (e)->ignore
01204 && (find_group (e->src) != find_group (e->dest)))
01205 {
01206 if (dump_file)
01207 fprintf (dump_file, "Abnormal edge %d to %d put to tree\n",
01208 e->src->index, e->dest->index);
01209 EDGE_INFO (e)->on_tree = 1;
01210 union_groups (e->src, e->dest);
01211 }
01212 }
01213
01214
01215 for (i = 0; i < num_edges; i++)
01216 {
01217 edge e = INDEX_EDGE (el, i);
01218 if (EDGE_CRITICAL_P (e) && !EDGE_INFO (e)->ignore
01219 && find_group (e->src) != find_group (e->dest))
01220 {
01221 if (dump_file)
01222 fprintf (dump_file, "Critical edge %d to %d put to tree\n",
01223 e->src->index, e->dest->index);
01224 EDGE_INFO (e)->on_tree = 1;
01225 union_groups (e->src, e->dest);
01226 }
01227 }
01228
01229
01230 for (i = 0; i < num_edges; i++)
01231 {
01232 edge e = INDEX_EDGE (el, i);
01233 if (!EDGE_INFO (e)->ignore
01234 && find_group (e->src) != find_group (e->dest))
01235 {
01236 if (dump_file)
01237 fprintf (dump_file, "Normal edge %d to %d put to tree\n",
01238 e->src->index, e->dest->index);
01239 EDGE_INFO (e)->on_tree = 1;
01240 union_groups (e->src, e->dest);
01241 }
01242 }
01243
01244 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
01245 bb->aux = NULL;
01246 }
01247
01248
01249
01250 void
01251 init_branch_prob (void)
01252 {
01253 int i;
01254
01255 total_num_blocks = 0;
01256 total_num_edges = 0;
01257 total_num_edges_ignored = 0;
01258 total_num_edges_instrumented = 0;
01259 total_num_blocks_created = 0;
01260 total_num_passes = 0;
01261 total_num_times_called = 0;
01262 total_num_branches = 0;
01263 total_num_never_executed = 0;
01264 for (i = 0; i < 20; i++)
01265 total_hist_br_prob[i] = 0;
01266 }
01267
01268
01269
01270
01271 void
01272 end_branch_prob (void)
01273 {
01274 if (dump_file)
01275 {
01276 fprintf (dump_file, "\n");
01277 fprintf (dump_file, "Total number of blocks: %d\n",
01278 total_num_blocks);
01279 fprintf (dump_file, "Total number of edges: %d\n", total_num_edges);
01280 fprintf (dump_file, "Total number of ignored edges: %d\n",
01281 total_num_edges_ignored);
01282 fprintf (dump_file, "Total number of instrumented edges: %d\n",
01283 total_num_edges_instrumented);
01284 fprintf (dump_file, "Total number of blocks created: %d\n",
01285 total_num_blocks_created);
01286 fprintf (dump_file, "Total number of graph solution passes: %d\n",
01287 total_num_passes);
01288 if (total_num_times_called != 0)
01289 fprintf (dump_file, "Average number of graph solution passes: %d\n",
01290 (total_num_passes + (total_num_times_called >> 1))
01291 / total_num_times_called);
01292 fprintf (dump_file, "Total number of branches: %d\n",
01293 total_num_branches);
01294 fprintf (dump_file, "Total number of branches never executed: %d\n",
01295 total_num_never_executed);
01296 if (total_num_branches)
01297 {
01298 int i;
01299
01300 for (i = 0; i < 10; i++)
01301 fprintf (dump_file, "%d%% branches in range %d-%d%%\n",
01302 (total_hist_br_prob[i] + total_hist_br_prob[19-i]) * 100
01303 / total_num_branches, 5*i, 5*i+5);
01304 }
01305 }
01306 }
01307
01308
01309
01310 void
01311 tree_register_profile_hooks (void)
01312 {
01313 profile_hooks = &tree_profile_hooks;
01314 if (!ir_type ())
01315 abort ();
01316 }
01317
01318
01319
01320 void
01321 rtl_register_profile_hooks (void)
01322 {
01323 profile_hooks = &rtl_profile_hooks;
01324 if (ir_type ())
01325 abort ();
01326 }