]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/profile.c
alias.c (nonlocal_mentioned_p, [...]): Use, LABEL_P, JUMP_P, CALL_P, NONJUMP_INSN_P...
[thirdparty/gcc.git] / gcc / profile.c
CommitLineData
a4d3961a 1/* Calculate branch probabilities, and basic block execution counts.
c913b6f1 2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
88462c42 3 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
86144b75
DE
4 Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5 based on some ideas from Dain Samples of UC Berkeley.
6 Further mangling by Bob Manson, Cygnus Support.
7
1322177d 8This file is part of GCC.
86144b75 9
1322177d
LB
10GCC is free software; you can redistribute it and/or modify it under
11the terms of the GNU General Public License as published by the Free
12Software Foundation; either version 2, or (at your option) any later
13version.
86144b75 14
1322177d
LB
15GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16WARRANTY; without even the implied warranty of MERCHANTABILITY or
17FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18for more details.
86144b75
DE
19
20You should have received a copy of the GNU General Public License
1322177d
LB
21along with GCC; see the file COPYING. If not, write to the Free
22Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2302111-1307, USA. */
86144b75 24
6c208acd
NS
25/* Generate basic block profile instrumentation and auxiliary files.
26 Profile generation is optimized, so that not all arcs in the basic
27 block graph need instrumenting. First, the BB graph is closed with
28 one entry (function start), and one exit (function exit). Any
29 ABNORMAL_EDGE cannot be instrumented (because there is no control
30 path to place the code). We close the graph by inserting fake
31 EDGE_FAKE edges to the EXIT_BLOCK, from the sources of abnormal
32 edges that do not go to the exit_block. We ignore such abnormal
33 edges. Naturally these fake edges are never directly traversed,
34 and so *cannot* be directly instrumented. Some other graph
35 massaging is done. To optimize the instrumentation we generate the
36 BB minimal span tree, only edges that are not on the span tree
37 (plus the entry point) need instrumenting. From that information
38 all other edge counts can be deduced. By construction all fake
39 edges must be on the spanning tree. We also attempt to place
40 EDGE_CRITICAL edges on the spanning tree.
41
6de9cd9a
DN
42 The auxiliary files generated are <dumpbase>.gcno (at compile time)
43 and <dumpbase>.gcda (at run time). The format is
4977bab6 44 described in full in gcov-io.h. */
6c208acd 45
86144b75
DE
46/* ??? Register allocation should use basic block execution counts to
47 give preference to the most commonly executed blocks. */
48
86144b75
DE
49/* ??? Should calculate branch probabilities before instrumenting code, since
50 then we can use arc counts to help decide which arcs to instrument. */
51
86144b75 52#include "config.h"
670ee920 53#include "system.h"
4977bab6
ZW
54#include "coretypes.h"
55#include "tm.h"
86144b75
DE
56#include "rtl.h"
57#include "flags.h"
86144b75 58#include "output.h"
e9a25f70 59#include "regs.h"
51891abe 60#include "expr.h"
49ad7cfa 61#include "function.h"
10f0ad3d 62#include "toplev.h"
ca29da43 63#include "coverage.h"
af166e5d
ZD
64#include "value-prof.h"
65#include "tree.h"
6de9cd9a
DN
66#include "cfghooks.h"
67#include "tree-flow.h"
68
69/* Hooks for profiling. */
70static struct profile_hooks* profile_hooks;
71
72/* File for profiling debug output. */
73static inline FILE*
74profile_dump_file (void) {
75 return profile_hooks->profile_dump_file ();
76}
86144b75 77
51891abe 78/* Additional information about the edges we need. */
6c208acd
NS
79struct edge_info {
80 unsigned int count_valid : 1;
0c20a65f 81
4b7e68e7 82 /* Is on the spanning tree. */
6c208acd 83 unsigned int on_tree : 1;
0c20a65f 84
6c208acd 85 /* Pretend this edge does not exist (it is abnormal and we've
4b7e68e7 86 inserted a fake to compensate). */
6c208acd
NS
87 unsigned int ignore : 1;
88};
89
90struct bb_info {
91 unsigned int count_valid : 1;
92
4b7e68e7 93 /* Number of successor and predecessor edges. */
6c208acd
NS
94 gcov_type succ_count;
95 gcov_type pred_count;
96};
51891abe
JH
97
98#define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
99#define BB_INFO(b) ((struct bb_info *) (b)->aux)
100
71c0e7fc 101/* Counter summary from the last set of coverage counts read. */
cdb23767
NS
102
103const struct gcov_ctr_summary *profile_info;
104
86144b75
DE
105/* Collect statistics on the performance of this pass for the entire source
106 file. */
107
108static int total_num_blocks;
51891abe 109static int total_num_edges;
dec2b703 110static int total_num_edges_ignored;
51891abe 111static int total_num_edges_instrumented;
86144b75
DE
112static int total_num_blocks_created;
113static int total_num_passes;
114static int total_num_times_called;
115static int total_hist_br_prob[20];
116static int total_num_never_executed;
117static int total_num_branches;
118
119/* Forward declarations. */
0c20a65f 120static void find_spanning_tree (struct edge_list *);
0c20a65f 121static unsigned instrument_edges (struct edge_list *);
af166e5d 122static void instrument_values (unsigned, struct histogram_value *);
0c20a65f 123static void compute_branch_probabilities (void);
6e885ee3 124static void compute_value_histograms (unsigned, struct histogram_value *);
0c20a65f
AJ
125static gcov_type * get_exec_counts (void);
126static basic_block find_group (basic_block);
127static void union_groups (basic_block, basic_block);
86144b75 128
86144b75 129\f
51891abe 130/* Add edge instrumentation code to the entire insn chain.
86144b75
DE
131
132 F is the first insn of the chain.
51891abe 133 NUM_BLOCKS is the number of basic blocks found in F. */
86144b75 134
6d70e6be 135static unsigned
0c20a65f 136instrument_edges (struct edge_list *el)
86144b75 137{
6d70e6be 138 unsigned num_instr_edges = 0;
51891abe 139 int num_edges = NUM_EDGES (el);
e0082a72 140 basic_block bb;
0c20a65f 141
51891abe
JH
142 remove_fake_edges ();
143
e0082a72 144 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
51891abe 145 {
6d70e6be
NS
146 edge e;
147
148 for (e = bb->succ; e; e = e->succ_next)
86144b75 149 {
51891abe 150 struct edge_info *inf = EDGE_INFO (e);
0c20a65f 151
51891abe 152 if (!inf->ignore && !inf->on_tree)
86144b75 153 {
51891abe 154 if (e->flags & EDGE_ABNORMAL)
86144b75 155 abort ();
c263766c
RH
156 if (dump_file)
157 fprintf (dump_file, "Edge %d to %d instrumented%s\n",
0b17ab2f 158 e->src->index, e->dest->index,
4262e623 159 EDGE_CRITICAL_P (e) ? " (and split)" : "");
6de9cd9a 160 (profile_hooks->gen_edge_profiler) (num_instr_edges++, e);
86144b75
DE
161 }
162 }
86144b75 163 }
51891abe 164
51891abe 165 total_num_blocks_created += num_edges;
c263766c
RH
166 if (dump_file)
167 fprintf (dump_file, "%d edges instrumented\n", num_instr_edges);
6d70e6be 168 return num_instr_edges;
86144b75 169}
af166e5d
ZD
170
171/* Add code to measure histograms list of VALUES of length N_VALUES. */
172static void
173instrument_values (unsigned n_values, struct histogram_value *values)
174{
af166e5d 175 unsigned i, t;
0c20a65f 176
af166e5d
ZD
177 /* Emit code to generate the histograms before the insns. */
178
179 for (i = 0; i < n_values; i++)
180 {
af166e5d
ZD
181 switch (values[i].type)
182 {
183 case HIST_TYPE_INTERVAL:
184 t = GCOV_COUNTER_V_INTERVAL;
185 break;
186
187 case HIST_TYPE_POW2:
188 t = GCOV_COUNTER_V_POW2;
189 break;
190
191 case HIST_TYPE_SINGLE_VALUE:
192 t = GCOV_COUNTER_V_SINGLE;
193 break;
194
195 case HIST_TYPE_CONST_DELTA:
196 t = GCOV_COUNTER_V_DELTA;
197 break;
198
199 default:
200 abort ();
201 }
202 if (!coverage_counter_alloc (t, values[i].n_counters))
203 continue;
204
205 switch (values[i].type)
206 {
207 case HIST_TYPE_INTERVAL:
6de9cd9a 208 (profile_hooks->gen_interval_profiler) (values + i, t, 0);
af166e5d
ZD
209 break;
210
211 case HIST_TYPE_POW2:
6de9cd9a 212 (profile_hooks->gen_pow2_profiler) (values + i, t, 0);
af166e5d
ZD
213 break;
214
215 case HIST_TYPE_SINGLE_VALUE:
6de9cd9a 216 (profile_hooks->gen_one_value_profiler) (values + i, t, 0);
af166e5d
ZD
217 break;
218
219 case HIST_TYPE_CONST_DELTA:
6de9cd9a 220 (profile_hooks->gen_const_delta_profiler) (values + i, t, 0);
af166e5d
ZD
221 break;
222
223 default:
224 abort ();
225 }
af166e5d
ZD
226 }
227}
4977bab6 228\f
8ade1519 229
af166e5d 230/* Computes hybrid profile for all matching entries in da_file. */
b7c9bf28
JH
231
232static gcov_type *
0c20a65f 233get_exec_counts (void)
b7c9bf28 234{
4977bab6 235 unsigned num_edges = 0;
e0082a72 236 basic_block bb;
ca29da43 237 gcov_type *counts;
0c20a65f 238
b7c9bf28 239 /* Count the edges to be (possibly) instrumented. */
e0082a72 240 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
b7c9bf28 241 {
b7c9bf28
JH
242 edge e;
243 for (e = bb->succ; e; e = e->succ_next)
244 if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
e0082a72 245 num_edges++;
b7c9bf28
JH
246 }
247
cdb23767 248 counts = get_coverage_counts (GCOV_COUNTER_ARCS, num_edges, &profile_info);
ca29da43
NS
249 if (!counts)
250 return NULL;
4977bab6 251
c263766c
RH
252 if (dump_file && profile_info)
253 fprintf(dump_file, "Merged %u profiles with maximal count %u.\n",
cdb23767 254 profile_info->runs, (unsigned) profile_info->sum_max);
b7c9bf28 255
ca29da43 256 return counts;
b7c9bf28
JH
257}
258\f
259
4da896b2
MM
260/* Compute the branch probabilities for the various branches.
261 Annotate them accordingly. */
262
263static void
0c20a65f 264compute_branch_probabilities (void)
4da896b2 265{
e0082a72 266 basic_block bb;
0b17ab2f
RH
267 int i;
268 int num_edges = 0;
4da896b2
MM
269 int changes;
270 int passes;
4da896b2 271 int hist_br_prob[20];
51891abe
JH
272 int num_never_executed;
273 int num_branches;
b7c9bf28
JH
274 gcov_type *exec_counts = get_exec_counts ();
275 int exec_counts_pos = 0;
4da896b2 276
f820b0cf
JH
277 /* Very simple sanity checks so we catch bugs in our profiling code. */
278 if (profile_info)
279 {
280 if (profile_info->run_max * profile_info->runs < profile_info->sum_max)
281 {
282 error ("corrupted profile info: run_max * runs < sum_max");
283 exec_counts = NULL;
284 }
285
286 if (profile_info->sum_all < profile_info->sum_max)
287 {
288 error ("corrupted profile info: sum_all is smaller than sum_max");
289 exec_counts = NULL;
290 }
291 }
292
51891abe
JH
293 /* Attach extra info block to each bb. */
294
ca6c03ca 295 alloc_aux_for_blocks (sizeof (struct bb_info));
e0082a72 296 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
51891abe 297 {
51891abe
JH
298 edge e;
299
51891abe
JH
300 for (e = bb->succ; e; e = e->succ_next)
301 if (!EDGE_INFO (e)->ignore)
302 BB_INFO (bb)->succ_count++;
303 for (e = bb->pred; e; e = e->pred_next)
304 if (!EDGE_INFO (e)->ignore)
305 BB_INFO (bb)->pred_count++;
306 }
307
308 /* Avoid predicting entry on exit nodes. */
309 BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
310 BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;
311
312 /* For each edge not on the spanning tree, set its execution count from
4da896b2
MM
313 the .da file. */
314
315 /* The first count in the .da file is the number of times that the function
316 was entered. This is the exec_count for block zero. */
317
e0082a72 318 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
51891abe 319 {
51891abe
JH
320 edge e;
321 for (e = bb->succ; e; e = e->succ_next)
322 if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
323 {
324 num_edges++;
b7c9bf28 325 if (exec_counts)
51891abe 326 {
b7c9bf28 327 e->count = exec_counts[exec_counts_pos++];
f820b0cf
JH
328 if (e->count > profile_info->sum_max)
329 {
330 error ("corrupted profile info: edge from %i to %i exceeds maximal count",
331 bb->index, e->dest->index);
332 }
51891abe
JH
333 }
334 else
335 e->count = 0;
b7c9bf28 336
51891abe
JH
337 EDGE_INFO (e)->count_valid = 1;
338 BB_INFO (bb)->succ_count--;
339 BB_INFO (e->dest)->pred_count--;
c263766c 340 if (dump_file)
b2aec5c0 341 {
c263766c 342 fprintf (dump_file, "\nRead edge from %i to %i, count:",
0b17ab2f 343 bb->index, e->dest->index);
c263766c 344 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
b2aec5c0
JH
345 (HOST_WIDEST_INT) e->count);
346 }
51891abe
JH
347 }
348 }
4da896b2 349
c263766c
RH
350 if (dump_file)
351 fprintf (dump_file, "\n%d edge counts read\n", num_edges);
4da896b2
MM
352
353 /* For every block in the file,
51891abe
JH
354 - if every exit/entrance edge has a known count, then set the block count
355 - if the block count is known, and every exit/entrance edge but one has
356 a known execution count, then set the count of the remaining edge
4da896b2 357
51891abe
JH
358 As edge counts are set, decrement the succ/pred count, but don't delete
359 the edge, that way we can easily tell when all edges are known, or only
360 one edge is unknown. */
4da896b2
MM
361
362 /* The order that the basic blocks are iterated through is important.
363 Since the code that finds spanning trees starts with block 0, low numbered
51891abe
JH
364 edges are put on the spanning tree in preference to high numbered edges.
365 Hence, most instrumented edges are at the end. Graph solving works much
4da896b2 366 faster if we propagate numbers from the end to the start.
51891abe 367
4da896b2
MM
368 This takes an average of slightly more than 3 passes. */
369
370 changes = 1;
371 passes = 0;
372 while (changes)
373 {
374 passes++;
375 changes = 0;
e0082a72 376 FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
4da896b2 377 {
51891abe
JH
378 struct bb_info *bi = BB_INFO (bb);
379 if (! bi->count_valid)
4da896b2 380 {
51891abe 381 if (bi->succ_count == 0)
4da896b2 382 {
51891abe 383 edge e;
b2aec5c0 384 gcov_type total = 0;
51891abe
JH
385
386 for (e = bb->succ; e; e = e->succ_next)
387 total += e->count;
388 bb->count = total;
389 bi->count_valid = 1;
4da896b2
MM
390 changes = 1;
391 }
51891abe 392 else if (bi->pred_count == 0)
4da896b2 393 {
51891abe 394 edge e;
b2aec5c0 395 gcov_type total = 0;
51891abe
JH
396
397 for (e = bb->pred; e; e = e->pred_next)
398 total += e->count;
399 bb->count = total;
400 bi->count_valid = 1;
4da896b2
MM
401 changes = 1;
402 }
403 }
51891abe 404 if (bi->count_valid)
4da896b2 405 {
51891abe 406 if (bi->succ_count == 1)
4da896b2 407 {
51891abe 408 edge e;
b2aec5c0 409 gcov_type total = 0;
51891abe 410
4da896b2
MM
411 /* One of the counts will be invalid, but it is zero,
412 so adding it in also doesn't hurt. */
51891abe
JH
413 for (e = bb->succ; e; e = e->succ_next)
414 total += e->count;
415
416 /* Seedgeh for the invalid edge, and set its count. */
417 for (e = bb->succ; e; e = e->succ_next)
418 if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
4da896b2 419 break;
51891abe
JH
420
421 /* Calculate count for remaining edge by conservation. */
422 total = bb->count - total;
423
424 if (! e)
4da896b2 425 abort ();
51891abe
JH
426 EDGE_INFO (e)->count_valid = 1;
427 e->count = total;
428 bi->succ_count--;
a4d3961a 429
51891abe 430 BB_INFO (e->dest)->pred_count--;
4da896b2
MM
431 changes = 1;
432 }
51891abe 433 if (bi->pred_count == 1)
4da896b2 434 {
51891abe 435 edge e;
b2aec5c0 436 gcov_type total = 0;
51891abe 437
4da896b2
MM
438 /* One of the counts will be invalid, but it is zero,
439 so adding it in also doesn't hurt. */
51891abe
JH
440 for (e = bb->pred; e; e = e->pred_next)
441 total += e->count;
442
6d70e6be 443 /* Search for the invalid edge, and set its count. */
51891abe 444 for (e = bb->pred; e; e = e->pred_next)
6d70e6be 445 if (!EDGE_INFO (e)->count_valid && !EDGE_INFO (e)->ignore)
4da896b2 446 break;
51891abe
JH
447
448 /* Calculate count for remaining edge by conservation. */
449 total = bb->count - total + e->count;
450
451 if (! e)
4da896b2 452 abort ();
51891abe
JH
453 EDGE_INFO (e)->count_valid = 1;
454 e->count = total;
455 bi->pred_count--;
a4d3961a 456
51891abe 457 BB_INFO (e->src)->succ_count--;
4da896b2
MM
458 changes = 1;
459 }
460 }
461 }
462 }
c263766c
RH
463 if (dump_file)
464 dump_flow_info (dump_file);
4da896b2
MM
465
466 total_num_passes += passes;
c263766c
RH
467 if (dump_file)
468 fprintf (dump_file, "Graph solving took %d passes.\n\n", passes);
4da896b2
MM
469
470 /* If the graph has been correctly solved, every block will have a
471 succ and pred count of zero. */
e0082a72 472 FOR_EACH_BB (bb)
4da896b2 473 {
51891abe 474 if (BB_INFO (bb)->succ_count || BB_INFO (bb)->pred_count)
4da896b2
MM
475 abort ();
476 }
477
51891abe 478 /* For every edge, calculate its branch probability and add a reg_note
4da896b2
MM
479 to the branch insn to indicate this. */
480
481 for (i = 0; i < 20; i++)
482 hist_br_prob[i] = 0;
483 num_never_executed = 0;
484 num_branches = 0;
485
e0082a72 486 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
4da896b2 487 {
51891abe 488 edge e;
51891abe
JH
489 rtx note;
490
04c5580f 491 if (bb->count < 0)
134d3a2e 492 {
04c5580f
JH
493 error ("corrupted profile info: number of iterations for basic block %d thought to be %i",
494 bb->index, (int)bb->count);
495 bb->count = 0;
496 }
497 for (e = bb->succ; e; e = e->succ_next)
498 {
ba228239 499 /* Function may return twice in the cased the called function is
04c5580f
JH
500 setjmp or calls fork, but we can't represent this by extra
501 edge from the entry, since extra edge from the exit is
502 already present. We get negative frequency from the entry
503 point. */
504 if ((e->count < 0
505 && e->dest == EXIT_BLOCK_PTR)
506 || (e->count > bb->count
507 && e->dest != EXIT_BLOCK_PTR))
508 {
6de9cd9a 509 if (block_ends_with_call_p (bb))
04c5580f
JH
510 e->count = e->count < 0 ? 0 : bb->count;
511 }
512 if (e->count < 0 || e->count > bb->count)
134d3a2e 513 {
04c5580f
JH
514 error ("corrupted profile info: number of executions for edge %d-%d thought to be %i",
515 e->src->index, e->dest->index,
516 (int)e->count);
517 e->count = bb->count / 2;
b9224c94 518 }
04c5580f
JH
519 }
520 if (bb->count)
521 {
522 for (e = bb->succ; e; e = e->succ_next)
523 e->probability = (e->count * REG_BR_PROB_BASE + bb->count / 2) / bb->count;
0b17ab2f 524 if (bb->index >= 0
6de9cd9a 525 && block_ends_with_condjump_p (bb)
b9224c94
JH
526 && bb->succ->succ_next)
527 {
528 int prob;
529 edge e;
134d3a2e
JH
530 int index;
531
532 /* Find the branch edge. It is possible that we do have fake
533 edges here. */
534 for (e = bb->succ; e->flags & (EDGE_FAKE | EDGE_FALLTHRU);
535 e = e->succ_next)
536 continue; /* Loop body has been intentionally left blank. */
537
538 prob = e->probability;
539 index = prob * 20 / REG_BR_PROB_BASE;
a4d3961a 540
134d3a2e
JH
541 if (index == 20)
542 index = 19;
543 hist_br_prob[index]++;
544
6de9cd9a
DN
545 /* Do this for RTL only. */
546 if (!ir_type ())
547 {
548 note = find_reg_note (BB_END (bb), REG_BR_PROB, 0);
549 /* There may be already note put by some other pass, such
550 as builtin_expect expander. */
551 if (note)
552 XEXP (note, 0) = GEN_INT (prob);
553 else
554 REG_NOTES (BB_END (bb))
555 = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
556 REG_NOTES (BB_END (bb)));
557 }
b9224c94 558 num_branches++;
4da896b2 559 }
b9224c94 560 }
4977bab6
ZW
561 /* Otherwise distribute the probabilities evenly so we get sane
562 sum. Use simple heuristics that if there are normal edges,
563 give all abnormals frequency of 0, otherwise distribute the
564 frequency over abnormals (this is the case of noreturn
565 calls). */
b9224c94
JH
566 else
567 {
04c5580f
JH
568 int total = 0;
569
b9224c94
JH
570 for (e = bb->succ; e; e = e->succ_next)
571 if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
572 total ++;
573 if (total)
574 {
575 for (e = bb->succ; e; e = e->succ_next)
576 if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
577 e->probability = REG_BR_PROB_BASE / total;
578 else
579 e->probability = 0;
580 }
581 else
582 {
583 for (e = bb->succ; e; e = e->succ_next)
584 total ++;
585 for (e = bb->succ; e; e = e->succ_next)
586 e->probability = REG_BR_PROB_BASE / total;
587 }
0b17ab2f 588 if (bb->index >= 0
6de9cd9a 589 && block_ends_with_condjump_p (bb)
b9224c94
JH
590 && bb->succ->succ_next)
591 num_branches++, num_never_executed;
4da896b2 592 }
4da896b2 593 }
4da896b2 594
c263766c 595 if (dump_file)
4da896b2 596 {
c263766c
RH
597 fprintf (dump_file, "%d branches\n", num_branches);
598 fprintf (dump_file, "%d branches never executed\n",
4da896b2
MM
599 num_never_executed);
600 if (num_branches)
601 for (i = 0; i < 10; i++)
c263766c 602 fprintf (dump_file, "%d%% branches in range %d-%d%%\n",
51891abe
JH
603 (hist_br_prob[i] + hist_br_prob[19-i]) * 100 / num_branches,
604 5 * i, 5 * i + 5);
4da896b2
MM
605
606 total_num_branches += num_branches;
607 total_num_never_executed += num_never_executed;
608 for (i = 0; i < 20; i++)
609 total_hist_br_prob[i] += hist_br_prob[i];
51891abe 610
c263766c
RH
611 fputc ('\n', dump_file);
612 fputc ('\n', dump_file);
4da896b2 613 }
51891abe 614
ca6c03ca 615 free_aux_for_blocks ();
b7c9bf28
JH
616}
617
6e885ee3
ZD
618/* Load value histograms for N_VALUES values whose description is stored
619 in VALUES array from .da file. */
620static void
621compute_value_histograms (unsigned n_values, struct histogram_value *values)
622{
623 unsigned i, j, t, any;
624 unsigned n_histogram_counters[GCOV_N_VALUE_COUNTERS];
625 gcov_type *histogram_counts[GCOV_N_VALUE_COUNTERS];
626 gcov_type *act_count[GCOV_N_VALUE_COUNTERS];
627 gcov_type *aact_count;
628
629 for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
630 n_histogram_counters[t] = 0;
631
632 for (i = 0; i < n_values; i++)
633 n_histogram_counters[(int) (values[i].type)] += values[i].n_counters;
634
635 any = 0;
636 for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
637 {
50612a04
ZD
638 if (!n_histogram_counters[t])
639 {
640 histogram_counts[t] = NULL;
641 continue;
642 }
643
6e885ee3
ZD
644 histogram_counts[t] =
645 get_coverage_counts (COUNTER_FOR_HIST_TYPE (t),
50612a04 646 n_histogram_counters[t], NULL);
6e885ee3
ZD
647 if (histogram_counts[t])
648 any = 1;
649 act_count[t] = histogram_counts[t];
650 }
651 if (!any)
652 return;
653
654 for (i = 0; i < n_values; i++)
655 {
656 rtx hist_list = NULL_RTX;
657 t = (int) (values[i].type);
658
6de9cd9a
DN
659 /* FIXME: make this work for trees. */
660 if (!ir_type ())
661 {
662 aact_count = act_count[t];
663 act_count[t] += values[i].n_counters;
664 for (j = values[i].n_counters; j > 0; j--)
665 hist_list = alloc_EXPR_LIST (0, GEN_INT (aact_count[j - 1]),
666 hist_list);
667 hist_list = alloc_EXPR_LIST (0,
668 copy_rtx ((rtx)values[i].value), hist_list);
669 hist_list = alloc_EXPR_LIST (0, GEN_INT (values[i].type), hist_list);
670 REG_NOTES ((rtx)values[i].insn) =
671 alloc_EXPR_LIST (REG_VALUE_PROFILE, hist_list,
672 REG_NOTES ((rtx)values[i].insn));
673 }
6e885ee3
ZD
674 }
675
676 for (t = 0; t < GCOV_N_VALUE_COUNTERS; t++)
677 if (histogram_counts[t])
678 free (histogram_counts[t]);
679}
680
86144b75
DE
681/* Instrument and/or analyze program behavior based on program flow graph.
682 In either case, this function builds a flow graph for the function being
683 compiled. The flow graph is stored in BB_GRAPH.
684
51891abe 685 When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
86144b75
DE
686 the flow graph that are needed to reconstruct the dynamic behavior of the
687 flow graph.
688
956d6950 689 When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
51891abe 690 information from a data file containing edge count information from previous
86144b75
DE
691 executions of the function being compiled. In this case, the flow graph is
692 annotated with actual execution counts, which are later propagated into the
693 rtl for optimization purposes.
694
695 Main entry point of this file. */
696
697void
0c20a65f 698branch_prob (void)
86144b75 699{
e0082a72 700 basic_block bb;
cb9e4555
ZD
701 unsigned i;
702 unsigned num_edges, ignored_edges;
6d70e6be 703 unsigned num_instrumented;
51891abe 704 struct edge_list *el;
af166e5d
ZD
705 unsigned n_values = 0;
706 struct histogram_value *values = NULL;
6a4d6760 707
86144b75
DE
708 total_num_times_called++;
709
f1330226 710 flow_call_edges_add (NULL);
2ab0437e 711 add_noreturn_fake_exit_edges ();
f1330226 712
51891abe
JH
713 /* We can't handle cyclic regions constructed using abnormal edges.
714 To avoid these we replace every source of abnormal edge by a fake
715 edge from entry node and every destination by fake edge to exit.
716 This keeps graph acyclic and our calculation exact for all normal
717 edges except for exit and entrance ones.
a4d3961a 718
51891abe
JH
719 We also add fake exit edges for each call and asm statement in the
720 basic, since it may not return. */
86144b75 721
e0082a72 722 FOR_EACH_BB (bb)
51891abe 723 {
51891abe
JH
724 int need_exit_edge = 0, need_entry_edge = 0;
725 int have_exit_edge = 0, have_entry_edge = 0;
51891abe 726 edge e;
86144b75 727
04c5580f
JH
728 /* Functions returning multiple times are not handled by extra edges.
729 Instead we simply allow negative counts on edges from exit to the
730 block past call and corresponding probabilities. We can't go
731 with the extra edges because that would result in flowgraph that
732 needs to have fake edges outside the spanning tree. */
570a98eb 733
51891abe
JH
734 for (e = bb->succ; e; e = e->succ_next)
735 {
736 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
737 && e->dest != EXIT_BLOCK_PTR)
738 need_exit_edge = 1;
739 if (e->dest == EXIT_BLOCK_PTR)
740 have_exit_edge = 1;
741 }
742 for (e = bb->pred; e; e = e->pred_next)
743 {
744 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
745 && e->src != ENTRY_BLOCK_PTR)
746 need_entry_edge = 1;
747 if (e->src == ENTRY_BLOCK_PTR)
748 have_entry_edge = 1;
749 }
86144b75 750
51891abe
JH
751 if (need_exit_edge && !have_exit_edge)
752 {
c263766c
RH
753 if (dump_file)
754 fprintf (dump_file, "Adding fake exit edge to bb %i\n",
0b17ab2f 755 bb->index);
6a4d6760 756 make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
51891abe
JH
757 }
758 if (need_entry_edge && !have_entry_edge)
759 {
c263766c
RH
760 if (dump_file)
761 fprintf (dump_file, "Adding fake entry edge to bb %i\n",
0b17ab2f 762 bb->index);
6a4d6760 763 make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
51891abe
JH
764 }
765 }
86144b75 766
51891abe
JH
767 el = create_edge_list ();
768 num_edges = NUM_EDGES (el);
ca6c03ca 769 alloc_aux_for_edges (sizeof (struct edge_info));
86144b75 770
bf77398c
ZD
771 /* The basic blocks are expected to be numbered sequentially. */
772 compact_blocks ();
773
dec2b703 774 ignored_edges = 0;
51891abe
JH
775 for (i = 0 ; i < num_edges ; i++)
776 {
777 edge e = INDEX_EDGE (el, i);
778 e->count = 0;
51891abe
JH
779
780 /* Mark edges we've replaced by fake edges above as ignored. */
781 if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
782 && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
6a4d6760 783 {
dec2b703
JJ
784 EDGE_INFO (e)->ignore = 1;
785 ignored_edges++;
6a4d6760 786 }
51891abe 787 }
86144b75 788
51891abe
JH
789#ifdef ENABLE_CHECKING
790 verify_flow_info ();
791#endif
86144b75 792
51891abe
JH
793 /* Create spanning tree from basic block graph, mark each edge that is
794 on the spanning tree. We insert as many abnormal and critical edges
f63d1bf7 795 as possible to minimize number of edge splits necessary. */
86144b75 796
51891abe 797 find_spanning_tree (el);
0c20a65f 798
dec2b703 799 /* Fake edges that are not on the tree will not be instrumented, so
dc297297 800 mark them ignored. */
6d70e6be 801 for (num_instrumented = i = 0; i < num_edges; i++)
dec2b703
JJ
802 {
803 edge e = INDEX_EDGE (el, i);
804 struct edge_info *inf = EDGE_INFO (e);
6d70e6be
NS
805
806 if (inf->ignore || inf->on_tree)
807 /*NOP*/;
808 else if (e->flags & EDGE_FAKE)
6a4d6760
KH
809 {
810 inf->ignore = 1;
811 ignored_edges++;
812 }
6d70e6be
NS
813 else
814 num_instrumented++;
dec2b703
JJ
815 }
816
0b17ab2f 817 total_num_blocks += n_basic_blocks + 2;
c263766c
RH
818 if (dump_file)
819 fprintf (dump_file, "%d basic blocks\n", n_basic_blocks);
dec2b703
JJ
820
821 total_num_edges += num_edges;
c263766c
RH
822 if (dump_file)
823 fprintf (dump_file, "%d edges\n", num_edges);
dec2b703
JJ
824
825 total_num_edges_ignored += ignored_edges;
c263766c
RH
826 if (dump_file)
827 fprintf (dump_file, "%d ignored edges\n", ignored_edges);
dec2b703 828
9b514d25
NS
829 /* Write the data from which gcov can reconstruct the basic block
830 graph. */
4da896b2 831
9b514d25 832 /* Basic block flags */
ca29da43 833 if (coverage_begin_output ())
86144b75 834 {
9b514d25 835 gcov_position_t offset;
0c20a65f 836
94de45d9 837 offset = gcov_write_tag (GCOV_TAG_BLOCKS);
cb9e4555 838 for (i = 0; i != (unsigned) (n_basic_blocks + 2); i++)
94de45d9
NS
839 gcov_write_unsigned (0);
840 gcov_write_length (offset);
9b514d25
NS
841 }
842
6d70e6be
NS
843 /* Keep all basic block indexes nonnegative in the gcov output.
844 Index 0 is used for entry block, last index is for exit block.
845 */
846 ENTRY_BLOCK_PTR->index = -1;
847 EXIT_BLOCK_PTR->index = last_basic_block;
848#define BB_TO_GCOV_INDEX(bb) ((bb)->index + 1)
0c20a65f 849
9b514d25
NS
850 /* Arcs */
851 if (coverage_begin_output ())
852 {
853 gcov_position_t offset;
854
e0082a72 855 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
4da896b2 856 {
51891abe 857 edge e;
51891abe 858
94de45d9
NS
859 offset = gcov_write_tag (GCOV_TAG_ARCS);
860 gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
0c20a65f 861
51891abe 862 for (e = bb->succ; e; e = e->succ_next)
4da896b2 863 {
51891abe
JH
864 struct edge_info *i = EDGE_INFO (e);
865 if (!i->ignore)
866 {
4977bab6 867 unsigned flag_bits = 0;
0c20a65f 868
51891abe 869 if (i->on_tree)
4977bab6 870 flag_bits |= GCOV_ARC_ON_TREE;
dec2b703 871 if (e->flags & EDGE_FAKE)
4977bab6 872 flag_bits |= GCOV_ARC_FAKE;
51891abe 873 if (e->flags & EDGE_FALLTHRU)
4977bab6 874 flag_bits |= GCOV_ARC_FALLTHROUGH;
51891abe 875
94de45d9
NS
876 gcov_write_unsigned (BB_TO_GCOV_INDEX (e->dest));
877 gcov_write_unsigned (flag_bits);
51891abe 878 }
86144b75 879 }
cb9e4555 880
94de45d9 881 gcov_write_length (offset);
86144b75 882 }
ca29da43 883 }
0c20a65f 884
71c0e7fc 885 /* Line numbers. */
6de9cd9a
DN
886 /* FIXME: make this work for trees. (Line numbers are in location_t
887 objects, but aren't always attached to the obvious tree...) */
888 if (coverage_begin_output () && !ir_type ())
ca29da43
NS
889 {
890 char const *prev_file_name = NULL;
9b514d25 891 gcov_position_t offset;
0c20a65f 892
ca29da43
NS
893 FOR_EACH_BB (bb)
894 {
a813c111 895 rtx insn = BB_HEAD (bb);
ca29da43 896 int ignore_next_note = 0;
0c20a65f 897
ca29da43 898 offset = 0;
0c20a65f 899
ca29da43
NS
900 /* We are looking for line number notes. Search backward
901 before basic block to find correct ones. */
902 insn = prev_nonnote_insn (insn);
903 if (!insn)
904 insn = get_insns ();
905 else
906 insn = NEXT_INSN (insn);
0c20a65f 907
a813c111 908 while (insn != BB_END (bb))
ca29da43 909 {
4b4bf941 910 if (NOTE_P (insn))
ca29da43
NS
911 {
912 /* Must ignore the line number notes that
913 immediately follow the end of an inline function
914 to avoid counting it twice. There is a note
915 before the call, and one after the call. */
916 if (NOTE_LINE_NUMBER (insn)
917 == NOTE_INSN_REPEATED_LINE_NUMBER)
918 ignore_next_note = 1;
919 else if (NOTE_LINE_NUMBER (insn) <= 0)
920 /*NOP*/;
921 else if (ignore_next_note)
922 ignore_next_note = 0;
923 else
924 {
6773e15f
PB
925 expanded_location s;
926
ca29da43
NS
927 if (!offset)
928 {
929 offset = gcov_write_tag (GCOV_TAG_LINES);
930 gcov_write_unsigned (BB_TO_GCOV_INDEX (bb));
931 }
0c20a65f 932
6773e15f
PB
933 NOTE_EXPANDED_LOCATION (s, insn);
934
ca29da43
NS
935 /* If this is a new source file, then output the
936 file's name to the .bb file. */
937 if (!prev_file_name
6773e15f 938 || strcmp (s.file, prev_file_name))
ca29da43 939 {
6773e15f 940 prev_file_name = s.file;
ca29da43
NS
941 gcov_write_unsigned (0);
942 gcov_write_string (prev_file_name);
943 }
6773e15f 944 gcov_write_unsigned (s.line);
ca29da43
NS
945 }
946 }
4977bab6 947 insn = NEXT_INSN (insn);
ca29da43 948 }
0c20a65f 949
ca29da43
NS
950 if (offset)
951 {
952 /* A file of NULL indicates the end of run. */
953 gcov_write_unsigned (0);
954 gcov_write_string (NULL);
955 gcov_write_length (offset);
956 }
957 }
86144b75 958 }
6de9cd9a 959
6d70e6be
NS
960 ENTRY_BLOCK_PTR->index = ENTRY_BLOCK;
961 EXIT_BLOCK_PTR->index = EXIT_BLOCK;
962#undef BB_TO_GCOV_INDEX
86144b75 963
af166e5d 964 if (flag_profile_values)
6de9cd9a 965 find_values_to_profile (&n_values, &values);
af166e5d 966
51891abe 967 if (flag_branch_probabilities)
6e885ee3
ZD
968 {
969 compute_branch_probabilities ();
970 if (flag_profile_values)
971 compute_value_histograms (n_values, values);
972 }
51891abe 973
6de9cd9a 974 /* For each edge not on the spanning tree, add counting code. */
6d70e6be
NS
975 if (profile_arc_flag
976 && coverage_counter_alloc (GCOV_COUNTER_ARCS, num_instrumented))
4da896b2 977 {
6d70e6be
NS
978 unsigned n_instrumented = instrument_edges (el);
979
980 if (n_instrumented != num_instrumented)
981 abort ();
cb9e4555 982
af166e5d
ZD
983 if (flag_profile_values)
984 instrument_values (n_values, values);
985
cb9e4555 986 /* Commit changes done by instrumentation. */
6de9cd9a
DN
987 if (ir_type ())
988 bsi_commit_edge_inserts ((int *)NULL);
989 else
990 {
991 commit_edge_insertions_watch_calls ();
992 allocate_reg_info (max_reg_num (), FALSE, FALSE);
993 }
86144b75
DE
994 }
995
51891abe 996 remove_fake_edges ();
cb9e4555 997 free_aux_for_edges ();
6de9cd9a
DN
998
999 if (!ir_type ())
1000 {
1001 /* Re-merge split basic blocks and the mess introduced by
1002 insert_insn_on_edge. */
1003 cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
1004 if (profile_dump_file())
1005 dump_flow_info (profile_dump_file());
1006 }
f1330226 1007
51891abe 1008 free_edge_list (el);
86144b75
DE
1009}
1010\f
51891abe 1011/* Union find algorithm implementation for the basic blocks using
dc297297 1012 aux fields. */
86144b75 1013
51891abe 1014static basic_block
0c20a65f 1015find_group (basic_block bb)
86144b75 1016{
51891abe 1017 basic_block group = bb, bb1;
86144b75 1018
51891abe
JH
1019 while ((basic_block) group->aux != group)
1020 group = (basic_block) group->aux;
86144b75 1021
51891abe
JH
1022 /* Compress path. */
1023 while ((basic_block) bb->aux != group)
86144b75 1024 {
51891abe
JH
1025 bb1 = (basic_block) bb->aux;
1026 bb->aux = (void *) group;
1027 bb = bb1;
86144b75 1028 }
51891abe
JH
1029 return group;
1030}
86144b75 1031
51891abe 1032static void
0c20a65f 1033union_groups (basic_block bb1, basic_block bb2)
51891abe
JH
1034{
1035 basic_block bb1g = find_group (bb1);
1036 basic_block bb2g = find_group (bb2);
86144b75 1037
51891abe
JH
1038 /* ??? I don't have a place for the rank field. OK. Lets go w/o it,
1039 this code is unlikely going to be performance problem anyway. */
1040 if (bb1g == bb2g)
1041 abort ();
86144b75 1042
51891abe 1043 bb1g->aux = bb2g;
86144b75 1044}
51891abe
JH
1045\f
1046/* This function searches all of the edges in the program flow graph, and puts
1047 as many bad edges as possible onto the spanning tree. Bad edges include
1048 abnormals edges, which can't be instrumented at the moment. Since it is
09da1532 1049 possible for fake edges to form a cycle, we will have to develop some
51891abe
JH
1050 better way in the future. Also put critical edges to the tree, since they
1051 are more expensive to instrument. */
86144b75
DE
1052
1053static void
0c20a65f 1054find_spanning_tree (struct edge_list *el)
86144b75 1055{
51891abe
JH
1056 int i;
1057 int num_edges = NUM_EDGES (el);
e0082a72 1058 basic_block bb;
86144b75 1059
51891abe 1060 /* We use aux field for standard union-find algorithm. */
e0082a72
ZD
1061 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1062 bb->aux = bb;
86144b75 1063
51891abe
JH
1064 /* Add fake edge exit to entry we can't instrument. */
1065 union_groups (EXIT_BLOCK_PTR, ENTRY_BLOCK_PTR);
1066
09da1532 1067 /* First add all abnormal edges to the tree unless they form a cycle. Also
b7c9bf28
JH
1068 add all edges to EXIT_BLOCK_PTR to avoid inserting profiling code behind
1069 setting return value from function. */
51891abe
JH
1070 for (i = 0; i < num_edges; i++)
1071 {
1072 edge e = INDEX_EDGE (el, i);
b7c9bf28 1073 if (((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
6d70e6be 1074 || e->dest == EXIT_BLOCK_PTR)
51891abe
JH
1075 && !EDGE_INFO (e)->ignore
1076 && (find_group (e->src) != find_group (e->dest)))
1077 {
c263766c
RH
1078 if (dump_file)
1079 fprintf (dump_file, "Abnormal edge %d to %d put to tree\n",
6a4d6760 1080 e->src->index, e->dest->index);
51891abe
JH
1081 EDGE_INFO (e)->on_tree = 1;
1082 union_groups (e->src, e->dest);
1083 }
1084 }
1085
09da1532 1086 /* Now insert all critical edges to the tree unless they form a cycle. */
51891abe
JH
1087 for (i = 0; i < num_edges; i++)
1088 {
1089 edge e = INDEX_EDGE (el, i);
6d70e6be
NS
1090 if (EDGE_CRITICAL_P (e) && !EDGE_INFO (e)->ignore
1091 && find_group (e->src) != find_group (e->dest))
51891abe 1092 {
c263766c
RH
1093 if (dump_file)
1094 fprintf (dump_file, "Critical edge %d to %d put to tree\n",
6a4d6760 1095 e->src->index, e->dest->index);
51891abe
JH
1096 EDGE_INFO (e)->on_tree = 1;
1097 union_groups (e->src, e->dest);
1098 }
1099 }
1100
1101 /* And now the rest. */
1102 for (i = 0; i < num_edges; i++)
1103 {
1104 edge e = INDEX_EDGE (el, i);
6d70e6be
NS
1105 if (!EDGE_INFO (e)->ignore
1106 && find_group (e->src) != find_group (e->dest))
51891abe 1107 {
c263766c
RH
1108 if (dump_file)
1109 fprintf (dump_file, "Normal edge %d to %d put to tree\n",
6a4d6760 1110 e->src->index, e->dest->index);
51891abe
JH
1111 EDGE_INFO (e)->on_tree = 1;
1112 union_groups (e->src, e->dest);
1113 }
1114 }
ca6c03ca 1115
e0082a72
ZD
1116 FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1117 bb->aux = NULL;
86144b75
DE
1118}
1119\f
1120/* Perform file-level initialization for branch-prob processing. */
1121
1122void
0c20a65f 1123init_branch_prob (void)
86144b75 1124{
86144b75
DE
1125 int i;
1126
86144b75 1127 total_num_blocks = 0;
51891abe 1128 total_num_edges = 0;
dec2b703 1129 total_num_edges_ignored = 0;
51891abe 1130 total_num_edges_instrumented = 0;
86144b75
DE
1131 total_num_blocks_created = 0;
1132 total_num_passes = 0;
1133 total_num_times_called = 0;
1134 total_num_branches = 0;
1135 total_num_never_executed = 0;
1136 for (i = 0; i < 20; i++)
1137 total_hist_br_prob[i] = 0;
1138}
1139
1140/* Performs file-level cleanup after branch-prob processing
1141 is completed. */
1142
1143void
0c20a65f 1144end_branch_prob (void)
86144b75 1145{
c263766c 1146 if (dump_file)
86144b75 1147 {
c263766c
RH
1148 fprintf (dump_file, "\n");
1149 fprintf (dump_file, "Total number of blocks: %d\n",
51891abe 1150 total_num_blocks);
c263766c
RH
1151 fprintf (dump_file, "Total number of edges: %d\n", total_num_edges);
1152 fprintf (dump_file, "Total number of ignored edges: %d\n",
dec2b703 1153 total_num_edges_ignored);
c263766c 1154 fprintf (dump_file, "Total number of instrumented edges: %d\n",
51891abe 1155 total_num_edges_instrumented);
c263766c 1156 fprintf (dump_file, "Total number of blocks created: %d\n",
86144b75 1157 total_num_blocks_created);
c263766c 1158 fprintf (dump_file, "Total number of graph solution passes: %d\n",
86144b75
DE
1159 total_num_passes);
1160 if (total_num_times_called != 0)
c263766c 1161 fprintf (dump_file, "Average number of graph solution passes: %d\n",
86144b75
DE
1162 (total_num_passes + (total_num_times_called >> 1))
1163 / total_num_times_called);
c263766c 1164 fprintf (dump_file, "Total number of branches: %d\n",
51891abe 1165 total_num_branches);
c263766c 1166 fprintf (dump_file, "Total number of branches never executed: %d\n",
86144b75
DE
1167 total_num_never_executed);
1168 if (total_num_branches)
1169 {
1170 int i;
1171
1172 for (i = 0; i < 10; i++)
c263766c 1173 fprintf (dump_file, "%d%% branches in range %d-%d%%\n",
86144b75
DE
1174 (total_hist_br_prob[i] + total_hist_br_prob[19-i]) * 100
1175 / total_num_branches, 5*i, 5*i+5);
1176 }
1177 }
1178}
86144b75 1179
6de9cd9a 1180/* Set up hooks to enable tree-based profiling. */
4977bab6 1181
6de9cd9a
DN
1182void
1183tree_register_profile_hooks (void)
af166e5d 1184{
6de9cd9a
DN
1185 profile_hooks = &tree_profile_hooks;
1186 if (!ir_type ())
1187 abort ();
af166e5d
ZD
1188}
1189
6de9cd9a 1190/* Set up hooks to enable RTL-based profiling. */
af166e5d 1191
6de9cd9a
DN
1192void
1193rtl_register_profile_hooks (void)
af166e5d 1194{
6de9cd9a
DN
1195 profile_hooks = &rtl_profile_hooks;
1196 if (ir_type ())
1197 abort ();
af166e5d 1198}