xref: /openbsd-src/gnu/usr.bin/gcc/gcc/profile.c (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
1 /* Calculate branch probabilities, and basic block execution counts.
2    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3    2000, 2001  Free Software Foundation, Inc.
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 
8 This file is part of GCC.
9 
10 GCC is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free
12 Software Foundation; either version 2, or (at your option) any later
13 version.
14 
15 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
16 WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18 for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with GCC; see the file COPYING.  If not, write to the Free
22 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23 02111-1307, USA.  */
24 
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 
42    The two auxiliary files generated are <dumpbase>.bb and
43    <dumpbase>.bbg. The former contains the BB->linenumber
44    mappings, and the latter describes the BB graph.
45 
46    The BB file contains line numbers for each block. For each basic
47    block, a zero count is output (to mark the start of a block), then
48    the line numbers of that block are listed. A zero ends the file
49    too.
50 
51    The BBG file contains a count of the blocks, followed by edge
52    information, for every edge in the graph. The edge information
53    lists the source and target block numbers, and a bit mask
54    describing the type of edge.
55 
56    The BB and BBG file formats are fully described in the gcov
57    documentation.  */
58 
59 /* ??? Register allocation should use basic block execution counts to
60    give preference to the most commonly executed blocks.  */
61 
62 /* ??? The .da files are not safe.  Changing the program after creating .da
63    files or using different options when compiling with -fbranch-probabilities
64    can result the arc data not matching the program.  Maybe add instrumented
65    arc count to .bbg file?  Maybe check whether PFG matches the .bbg file?  */
66 
67 /* ??? Should calculate branch probabilities before instrumenting code, since
68    then we can use arc counts to help decide which arcs to instrument.  */
69 
70 #include "config.h"
71 #include "system.h"
72 #include "rtl.h"
73 #include "tree.h"
74 #include "flags.h"
75 #include "insn-config.h"
76 #include "output.h"
77 #include "regs.h"
78 #include "expr.h"
79 #include "function.h"
80 #include "toplev.h"
81 #include "ggc.h"
82 #include "hard-reg-set.h"
83 #include "basic-block.h"
84 #include "gcov-io.h"
85 #include "target.h"
86 #include "profile.h"
87 #include "libfuncs.h"
88 #include "langhooks.h"
89 
90 /* Additional information about the edges we need.  */
91 struct edge_info {
92   unsigned int count_valid : 1;
93 
94   /* Is on the spanning tree.  */
95   unsigned int on_tree : 1;
96 
97   /* Pretend this edge does not exist (it is abnormal and we've
98      inserted a fake to compensate).  */
99   unsigned int ignore : 1;
100 };
101 
102 struct bb_info {
103   unsigned int count_valid : 1;
104 
105   /* Number of successor and predecessor edges.  */
106   gcov_type succ_count;
107   gcov_type pred_count;
108 };
109 
110 #define EDGE_INFO(e)  ((struct edge_info *) (e)->aux)
111 #define BB_INFO(b)  ((struct bb_info *) (b)->aux)
112 
113 /* Keep all basic block indexes nonnegative in the gcov output.  Index 0
114    is used for entry block, last block exit block.  */
115 #define BB_TO_GCOV_INDEX(bb)  ((bb) == ENTRY_BLOCK_PTR ? 0		\
116 			       : ((bb) == EXIT_BLOCK_PTR		\
117 				  ? last_basic_block + 1 : (bb)->index + 1))
118 
119 /* Instantiate the profile info structure.  */
120 
121 struct profile_info profile_info;
122 
123 /* Name and file pointer of the output file for the basic block graph.  */
124 
125 static FILE *bbg_file;
126 
127 /* Name and file pointer of the input file for the arc count data.  */
128 
129 static FILE *da_file;
130 static char *da_file_name;
131 
132 /* Pointer of the output file for the basic block/line number map.  */
133 static FILE *bb_file;
134 
135 /* Last source file name written to bb_file.  */
136 
137 static char *last_bb_file_name;
138 
139 /* Collect statistics on the performance of this pass for the entire source
140    file.  */
141 
142 static int total_num_blocks;
143 static int total_num_edges;
144 static int total_num_edges_ignored;
145 static int total_num_edges_instrumented;
146 static int total_num_blocks_created;
147 static int total_num_passes;
148 static int total_num_times_called;
149 static int total_hist_br_prob[20];
150 static int total_num_never_executed;
151 static int total_num_branches;
152 
153 /* Forward declarations.  */
154 static void find_spanning_tree PARAMS ((struct edge_list *));
155 static void init_edge_profiler PARAMS ((void));
156 static rtx gen_edge_profiler PARAMS ((int));
157 static void instrument_edges PARAMS ((struct edge_list *));
158 static void output_gcov_string PARAMS ((const char *, long));
159 static void compute_branch_probabilities PARAMS ((void));
160 static gcov_type * get_exec_counts PARAMS ((void));
161 static long compute_checksum PARAMS ((void));
162 static basic_block find_group PARAMS ((basic_block));
163 static void union_groups PARAMS ((basic_block, basic_block));
164 
165 /* If nonzero, we need to output a constructor to set up the
166    per-object-file data.  */
167 static int need_func_profiler = 0;
168 
169 /* Add edge instrumentation code to the entire insn chain.
170 
171    F is the first insn of the chain.
172    NUM_BLOCKS is the number of basic blocks found in F.  */
173 
174 static void
instrument_edges(el)175 instrument_edges (el)
176      struct edge_list *el;
177 {
178   int num_instr_edges = 0;
179   int num_edges = NUM_EDGES (el);
180   basic_block bb;
181   remove_fake_edges ();
182 
183   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
184     {
185       edge e = bb->succ;
186       while (e)
187 	{
188 	  struct edge_info *inf = EDGE_INFO (e);
189 	  if (!inf->ignore && !inf->on_tree)
190 	    {
191 	      if (e->flags & EDGE_ABNORMAL)
192 		abort ();
193 	      if (rtl_dump_file)
194 		fprintf (rtl_dump_file, "Edge %d to %d instrumented%s\n",
195 			 e->src->index, e->dest->index,
196 			 EDGE_CRITICAL_P (e) ? " (and split)" : "");
197 	      need_func_profiler = 1;
198 	      insert_insn_on_edge (
199 			 gen_edge_profiler (total_num_edges_instrumented
200 					    + num_instr_edges++), e);
201 	    }
202 	  e = e->succ_next;
203 	}
204     }
205 
206   profile_info.count_edges_instrumented_now = num_instr_edges;
207   total_num_edges_instrumented += num_instr_edges;
208   profile_info.count_instrumented_edges = total_num_edges_instrumented;
209 
210   total_num_blocks_created += num_edges;
211   if (rtl_dump_file)
212     fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);
213 
214   commit_edge_insertions_watch_calls ();
215 }
216 
217 /* Output STRING to bb_file, surrounded by DELIMITER.  */
218 
219 static void
output_gcov_string(string,delimiter)220 output_gcov_string (string, delimiter)
221      const char *string;
222      long delimiter;
223 {
224   size_t temp;
225 
226   /* Write a delimiter to indicate that a file name follows.  */
227   __write_long (delimiter, bb_file, 4);
228 
229   /* Write the string.  */
230   temp = strlen (string) + 1;
231   fwrite (string, temp, 1, bb_file);
232 
233   /* Append a few zeros, to align the output to a 4 byte boundary.  */
234   temp = temp & 0x3;
235   if (temp)
236     {
237       char c[4];
238 
239       c[0] = c[1] = c[2] = c[3] = 0;
240       fwrite (c, sizeof (char), 4 - temp, bb_file);
241     }
242 
243   /* Store another delimiter in the .bb file, just to make it easy to find
244      the end of the file name.  */
245   __write_long (delimiter, bb_file, 4);
246 }
247 
248 
249 /* Computes hybrid profile for all matching entries in da_file.
250    Sets max_counter_in_program as a side effect.  */
251 
252 static gcov_type *
get_exec_counts()253 get_exec_counts ()
254 {
255   int num_edges = 0;
256   basic_block bb;
257   int okay = 1, i;
258   int mismatch = 0;
259   gcov_type *profile;
260   char *function_name_buffer;
261   int function_name_buffer_len;
262   gcov_type max_counter_in_run;
263   const char *name = IDENTIFIER_POINTER
264 		      (DECL_ASSEMBLER_NAME (current_function_decl));
265 
266   profile_info.max_counter_in_program = 0;
267   profile_info.count_profiles_merged = 0;
268 
269   /* No .da file, no execution counts.  */
270   if (!da_file)
271     return 0;
272 
273   /* Count the edges to be (possibly) instrumented.  */
274 
275   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
276     {
277       edge e;
278       for (e = bb->succ; e; e = e->succ_next)
279 	if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
280 	  num_edges++;
281     }
282 
283   /* now read and combine all matching profiles.  */
284 
285   profile = xmalloc (sizeof (gcov_type) * num_edges);
286   rewind (da_file);
287   function_name_buffer_len = strlen (name) + 1;
288   function_name_buffer = xmalloc (function_name_buffer_len + 1);
289 
290   for (i = 0; i < num_edges; i++)
291     profile[i] = 0;
292 
293   while (1)
294     {
295       long magic, extra_bytes;
296       long func_count;
297       int i;
298 
299       if (__read_long (&magic, da_file, 4) != 0)
300 	break;
301 
302       if (magic != -123)
303 	{
304 	  okay = 0;
305 	  break;
306 	}
307 
308       if (__read_long (&func_count, da_file, 4) != 0)
309 	{
310 	  okay = 0;
311 	  break;
312 	}
313 
314       if (__read_long (&extra_bytes, da_file, 4) != 0)
315 	{
316 	  okay = 0;
317 	  break;
318 	}
319 
320       fseek (da_file, 4 + 8, SEEK_CUR);
321 
322       /* read the maximal counter.  */
323       __read_gcov_type (&max_counter_in_run, da_file, 8);
324 
325       /* skip the rest of "statistics" emited by __bb_exit_func.  */
326       fseek (da_file, extra_bytes - (4 + 8 + 8), SEEK_CUR);
327 
328       for (i = 0; i < func_count; i++)
329 	{
330 	  long arc_count;
331 	  long chksum;
332 	  int j;
333 
334 	  if (__read_gcov_string
335 	      (function_name_buffer, function_name_buffer_len, da_file,
336 	       -1) != 0)
337 	    {
338 	      okay = 0;
339 	      break;
340 	    }
341 
342 	  if (__read_long (&chksum, da_file, 4) != 0)
343 	    {
344 	      okay = 0;
345 	      break;
346 	    }
347 
348 	  if (__read_long (&arc_count, da_file, 4) != 0)
349 	    {
350 	      okay = 0;
351 	      break;
352 	    }
353 
354 	  if (strcmp (function_name_buffer, name) != 0)
355 	    {
356 	      /* skip */
357 	      if (fseek (da_file, arc_count * 8, SEEK_CUR) < 0)
358 		{
359 		  okay = 0;
360 		  break;
361 		}
362 	    }
363 	  else if (arc_count != num_edges
364 		   || chksum != profile_info.current_function_cfg_checksum)
365 	    okay = 0, mismatch = 1;
366 	  else
367 	    {
368 	      gcov_type tmp;
369 
370 	      profile_info.max_counter_in_program += max_counter_in_run;
371 	      profile_info.count_profiles_merged++;
372 
373 	      for (j = 0; j < arc_count; j++)
374 		if (__read_gcov_type (&tmp, da_file, 8) != 0)
375 		  {
376 		    okay = 0;
377 		    break;
378 		  }
379 		else
380 		  {
381 		    profile[j] += tmp;
382 		  }
383 	    }
384 	}
385 
386       if (!okay)
387 	break;
388 
389     }
390 
391   free (function_name_buffer);
392 
393   if (!okay)
394     {
395       if (mismatch)
396 	error
397 	  ("Profile does not match flowgraph of function %s (out of date?)",
398 	   current_function_name);
399       else
400 	error (".da file corrupted");
401       free (profile);
402       return 0;
403     }
404   if (rtl_dump_file)
405     {
406       fprintf(rtl_dump_file, "Merged %i profiles with maximal count %i.\n",
407 	      profile_info.count_profiles_merged,
408 	      (int)profile_info.max_counter_in_program);
409     }
410 
411   return profile;
412 }
413 
414 
415 /* Compute the branch probabilities for the various branches.
416    Annotate them accordingly.  */
417 
418 static void
compute_branch_probabilities()419 compute_branch_probabilities ()
420 {
421   basic_block bb;
422   int i;
423   int num_edges = 0;
424   int changes;
425   int passes;
426   int hist_br_prob[20];
427   int num_never_executed;
428   int num_branches;
429   gcov_type *exec_counts = get_exec_counts ();
430   int exec_counts_pos = 0;
431 
432   /* Attach extra info block to each bb.  */
433 
434   alloc_aux_for_blocks (sizeof (struct bb_info));
435   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
436     {
437       edge e;
438 
439       for (e = bb->succ; e; e = e->succ_next)
440 	if (!EDGE_INFO (e)->ignore)
441 	  BB_INFO (bb)->succ_count++;
442       for (e = bb->pred; e; e = e->pred_next)
443 	if (!EDGE_INFO (e)->ignore)
444 	  BB_INFO (bb)->pred_count++;
445     }
446 
447   /* Avoid predicting entry on exit nodes.  */
448   BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
449   BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;
450 
451   /* For each edge not on the spanning tree, set its execution count from
452      the .da file.  */
453 
454   /* The first count in the .da file is the number of times that the function
455      was entered.  This is the exec_count for block zero.  */
456 
457   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
458     {
459       edge e;
460       for (e = bb->succ; e; e = e->succ_next)
461 	if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
462 	  {
463 	    num_edges++;
464 	    if (exec_counts)
465 	      {
466 		e->count = exec_counts[exec_counts_pos++];
467 	      }
468 	    else
469 	      e->count = 0;
470 
471 	    EDGE_INFO (e)->count_valid = 1;
472 	    BB_INFO (bb)->succ_count--;
473 	    BB_INFO (e->dest)->pred_count--;
474 	    if (rtl_dump_file)
475 	      {
476 		fprintf (rtl_dump_file, "\nRead edge from %i to %i, count:",
477 			 bb->index, e->dest->index);
478 		fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC,
479 			 (HOST_WIDEST_INT) e->count);
480 	      }
481 	  }
482     }
483 
484   if (rtl_dump_file)
485     fprintf (rtl_dump_file, "\n%d edge counts read\n", num_edges);
486 
487   /* For every block in the file,
488      - if every exit/entrance edge has a known count, then set the block count
489      - if the block count is known, and every exit/entrance edge but one has
490      a known execution count, then set the count of the remaining edge
491 
492      As edge counts are set, decrement the succ/pred count, but don't delete
493      the edge, that way we can easily tell when all edges are known, or only
494      one edge is unknown.  */
495 
496   /* The order that the basic blocks are iterated through is important.
497      Since the code that finds spanning trees starts with block 0, low numbered
498      edges are put on the spanning tree in preference to high numbered edges.
499      Hence, most instrumented edges are at the end.  Graph solving works much
500      faster if we propagate numbers from the end to the start.
501 
502      This takes an average of slightly more than 3 passes.  */
503 
504   changes = 1;
505   passes = 0;
506   while (changes)
507     {
508       passes++;
509       changes = 0;
510       FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
511 	{
512 	  struct bb_info *bi = BB_INFO (bb);
513 	  if (! bi->count_valid)
514 	    {
515 	      if (bi->succ_count == 0)
516 		{
517 		  edge e;
518 		  gcov_type total = 0;
519 
520 		  for (e = bb->succ; e; e = e->succ_next)
521 		    total += e->count;
522 		  bb->count = total;
523 		  bi->count_valid = 1;
524 		  changes = 1;
525 		}
526 	      else if (bi->pred_count == 0)
527 		{
528 		  edge e;
529 		  gcov_type total = 0;
530 
531 		  for (e = bb->pred; e; e = e->pred_next)
532 		    total += e->count;
533 		  bb->count = total;
534 		  bi->count_valid = 1;
535 		  changes = 1;
536 		}
537 	    }
538 	  if (bi->count_valid)
539 	    {
540 	      if (bi->succ_count == 1)
541 		{
542 		  edge e;
543 		  gcov_type total = 0;
544 
545 		  /* One of the counts will be invalid, but it is zero,
546 		     so adding it in also doesn't hurt.  */
547 		  for (e = bb->succ; e; e = e->succ_next)
548 		    total += e->count;
549 
550 		  /* Seedgeh for the invalid edge, and set its count.  */
551 		  for (e = bb->succ; e; e = e->succ_next)
552 		    if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
553 		      break;
554 
555 		  /* Calculate count for remaining edge by conservation.  */
556 		  total = bb->count - total;
557 
558 		  if (! e)
559 		    abort ();
560 		  EDGE_INFO (e)->count_valid = 1;
561 		  e->count = total;
562 		  bi->succ_count--;
563 
564 		  BB_INFO (e->dest)->pred_count--;
565 		  changes = 1;
566 		}
567 	      if (bi->pred_count == 1)
568 		{
569 		  edge e;
570 		  gcov_type total = 0;
571 
572 		  /* One of the counts will be invalid, but it is zero,
573 		     so adding it in also doesn't hurt.  */
574 		  for (e = bb->pred; e; e = e->pred_next)
575 		    total += e->count;
576 
577 		  /* Seedgeh for the invalid edge, and set its count.  */
578 		  for (e = bb->pred; e; e = e->pred_next)
579 		    if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
580 		      break;
581 
582 		  /* Calculate count for remaining edge by conservation.  */
583 		  total = bb->count - total + e->count;
584 
585 		  if (! e)
586 		    abort ();
587 		  EDGE_INFO (e)->count_valid = 1;
588 		  e->count = total;
589 		  bi->pred_count--;
590 
591 		  BB_INFO (e->src)->succ_count--;
592 		  changes = 1;
593 		}
594 	    }
595 	}
596     }
597   if (rtl_dump_file)
598     dump_flow_info (rtl_dump_file);
599 
600   total_num_passes += passes;
601   if (rtl_dump_file)
602     fprintf (rtl_dump_file, "Graph solving took %d passes.\n\n", passes);
603 
604   /* If the graph has been correctly solved, every block will have a
605      succ and pred count of zero.  */
606   FOR_EACH_BB (bb)
607     {
608       if (BB_INFO (bb)->succ_count || BB_INFO (bb)->pred_count)
609 	abort ();
610     }
611 
612   /* For every edge, calculate its branch probability and add a reg_note
613      to the branch insn to indicate this.  */
614 
615   for (i = 0; i < 20; i++)
616     hist_br_prob[i] = 0;
617   num_never_executed = 0;
618   num_branches = 0;
619 
620   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
621     {
622       edge e;
623       gcov_type total;
624       rtx note;
625 
626       total = bb->count;
627       if (total)
628 	{
629 	  for (e = bb->succ; e; e = e->succ_next)
630 	    {
631 		e->probability = (e->count * REG_BR_PROB_BASE + total / 2) / total;
632 		if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
633 		  {
634 		    error ("corrupted profile info: prob for %d-%d thought to be %d",
635 			   e->src->index, e->dest->index, e->probability);
636 		    e->probability = REG_BR_PROB_BASE / 2;
637 		  }
638 	    }
639 	  if (bb->index >= 0
640 	      && any_condjump_p (bb->end)
641 	      && bb->succ->succ_next)
642 	    {
643 	      int prob;
644 	      edge e;
645 	      int index;
646 
647 	      /* Find the branch edge.  It is possible that we do have fake
648 		 edges here.  */
649 	      for (e = bb->succ; e->flags & (EDGE_FAKE | EDGE_FALLTHRU);
650 		   e = e->succ_next)
651 		continue; /* Loop body has been intentionally left blank.  */
652 
653 	      prob = e->probability;
654 	      index = prob * 20 / REG_BR_PROB_BASE;
655 
656 	      if (index == 20)
657 		index = 19;
658 	      hist_br_prob[index]++;
659 
660 	      note = find_reg_note (bb->end, REG_BR_PROB, 0);
661 	      /* There may be already note put by some other pass, such
662 		 as builtin_expect expander.  */
663 	      if (note)
664 		XEXP (note, 0) = GEN_INT (prob);
665 	      else
666 		REG_NOTES (bb->end)
667 		  = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
668 				       REG_NOTES (bb->end));
669 	      num_branches++;
670 	    }
671 	}
672       /* Otherwise distribute the probabilities evenly so we get sane sum.
673 	 Use simple heuristics that if there are normal edges, give all abnormals
674 	 frequency of 0, otherwise distribute the frequency over abnormals
675 	 (this is the case of noreturn calls).  */
676       else
677 	{
678 	  for (e = bb->succ; e; e = e->succ_next)
679 	    if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
680 	      total ++;
681 	  if (total)
682 	    {
683 	      for (e = bb->succ; e; e = e->succ_next)
684 		if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
685 		  e->probability = REG_BR_PROB_BASE / total;
686 		else
687 		  e->probability = 0;
688 	    }
689 	  else
690 	    {
691 	      for (e = bb->succ; e; e = e->succ_next)
692 		total ++;
693 	      for (e = bb->succ; e; e = e->succ_next)
694 		e->probability = REG_BR_PROB_BASE / total;
695 	    }
696 	  if (bb->index >= 0
697 	      && any_condjump_p (bb->end)
698 	      && bb->succ->succ_next)
699 	    num_branches++, num_never_executed;
700 	}
701     }
702 
703   if (rtl_dump_file)
704     {
705       fprintf (rtl_dump_file, "%d branches\n", num_branches);
706       fprintf (rtl_dump_file, "%d branches never executed\n",
707 	       num_never_executed);
708       if (num_branches)
709 	for (i = 0; i < 10; i++)
710 	  fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
711 		   (hist_br_prob[i] + hist_br_prob[19-i]) * 100 / num_branches,
712 		   5 * i, 5 * i + 5);
713 
714       total_num_branches += num_branches;
715       total_num_never_executed += num_never_executed;
716       for (i = 0; i < 20; i++)
717 	total_hist_br_prob[i] += hist_br_prob[i];
718 
719       fputc ('\n', rtl_dump_file);
720       fputc ('\n', rtl_dump_file);
721     }
722 
723   free_aux_for_blocks ();
724   if (exec_counts)
725     free (exec_counts);
726 }
727 
728 /* Compute checksum for the current function.  */
729 
730 #define CHSUM_HASH	500000003
731 #define CHSUM_SHIFT	2
732 
733 static long
compute_checksum()734 compute_checksum ()
735 {
736   long chsum = 0;
737   basic_block bb;
738 
739   FOR_EACH_BB (bb)
740     {
741       edge e;
742 
743       for (e = bb->succ; e; e = e->succ_next)
744 	{
745 	  chsum = ((chsum << CHSUM_SHIFT) + (BB_TO_GCOV_INDEX (e->dest) + 1)) % CHSUM_HASH;
746 	}
747 
748       chsum = (chsum << CHSUM_SHIFT) % CHSUM_HASH;
749     }
750 
751   return chsum;
752 }
753 
754 /* Instrument and/or analyze program behavior based on program flow graph.
755    In either case, this function builds a flow graph for the function being
756    compiled.  The flow graph is stored in BB_GRAPH.
757 
758    When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
759    the flow graph that are needed to reconstruct the dynamic behavior of the
760    flow graph.
761 
762    When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
763    information from a data file containing edge count information from previous
764    executions of the function being compiled.  In this case, the flow graph is
765    annotated with actual execution counts, which are later propagated into the
766    rtl for optimization purposes.
767 
768    Main entry point of this file.  */
769 
770 void
branch_prob()771 branch_prob ()
772 {
773   basic_block bb;
774   int i;
775   int num_edges, ignored_edges;
776   struct edge_list *el;
777   const char *name = IDENTIFIER_POINTER
778 		       (DECL_ASSEMBLER_NAME (current_function_decl));
779 
780   profile_info.current_function_cfg_checksum = compute_checksum ();
781 
782   if (rtl_dump_file)
783     fprintf (rtl_dump_file, "CFG checksum is %ld\n",
784 	profile_info.current_function_cfg_checksum);
785 
786   /* Start of a function.  */
787   if (flag_test_coverage)
788     output_gcov_string (name, (long) -2);
789 
790   total_num_times_called++;
791 
792   flow_call_edges_add (NULL);
793   add_noreturn_fake_exit_edges ();
794 
795   /* We can't handle cyclic regions constructed using abnormal edges.
796      To avoid these we replace every source of abnormal edge by a fake
797      edge from entry node and every destination by fake edge to exit.
798      This keeps graph acyclic and our calculation exact for all normal
799      edges except for exit and entrance ones.
800 
801      We also add fake exit edges for each call and asm statement in the
802      basic, since it may not return.  */
803 
804   FOR_EACH_BB (bb)
805     {
806       int need_exit_edge = 0, need_entry_edge = 0;
807       int have_exit_edge = 0, have_entry_edge = 0;
808       rtx insn;
809       edge e;
810 
811       /* Add fake edges from entry block to the call insns that may return
812 	 twice.  The CFG is not quite correct then, as call insn plays more
813 	 role of CODE_LABEL, but for our purposes, everything should be OK,
814 	 as we never insert code to the beggining of basic block.  */
815       for (insn = bb->head; insn != NEXT_INSN (bb->end);
816 	   insn = NEXT_INSN (insn))
817 	{
818 	  if (GET_CODE (insn) == CALL_INSN
819 	      && find_reg_note (insn, REG_SETJMP, NULL))
820 	    {
821 	      if (GET_CODE (bb->head) == CODE_LABEL
822 		  || insn != NEXT_INSN (bb->head))
823 		{
824 		  e = split_block (bb, PREV_INSN (insn));
825 		  make_edge (ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE);
826 		  break;
827 		}
828 	      else
829 		{
830 		  /* We should not get abort here, as call to setjmp should not
831 		     be the very first instruction of function.  */
832 		  if (bb == ENTRY_BLOCK_PTR)
833 		    abort ();
834 		  make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
835 		}
836 	    }
837 	}
838 
839       for (e = bb->succ; e; e = e->succ_next)
840 	{
841 	  if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
842 	       && e->dest != EXIT_BLOCK_PTR)
843 	    need_exit_edge = 1;
844 	  if (e->dest == EXIT_BLOCK_PTR)
845 	    have_exit_edge = 1;
846 	}
847       for (e = bb->pred; e; e = e->pred_next)
848 	{
849 	  if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
850 	       && e->src != ENTRY_BLOCK_PTR)
851 	    need_entry_edge = 1;
852 	  if (e->src == ENTRY_BLOCK_PTR)
853 	    have_entry_edge = 1;
854 	}
855 
856       if (need_exit_edge && !have_exit_edge)
857 	{
858 	  if (rtl_dump_file)
859 	    fprintf (rtl_dump_file, "Adding fake exit edge to bb %i\n",
860 		     bb->index);
861 	  make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
862 	}
863       if (need_entry_edge && !have_entry_edge)
864 	{
865 	  if (rtl_dump_file)
866 	    fprintf (rtl_dump_file, "Adding fake entry edge to bb %i\n",
867 		     bb->index);
868 	  make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
869 	}
870     }
871 
872   el = create_edge_list ();
873   num_edges = NUM_EDGES (el);
874   alloc_aux_for_edges (sizeof (struct edge_info));
875 
876   /* The basic blocks are expected to be numbered sequentially.  */
877   compact_blocks ();
878 
879   ignored_edges = 0;
880   for (i = 0 ; i < num_edges ; i++)
881     {
882       edge e = INDEX_EDGE (el, i);
883       e->count = 0;
884 
885       /* Mark edges we've replaced by fake edges above as ignored.  */
886       if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
887 	  && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
888 	{
889 	  EDGE_INFO (e)->ignore = 1;
890 	  ignored_edges++;
891 	}
892     }
893 
894 #ifdef ENABLE_CHECKING
895   verify_flow_info ();
896 #endif
897 
898   /* Output line number information about each basic block for
899      GCOV utility.  */
900   if (flag_test_coverage)
901     {
902       FOR_EACH_BB (bb)
903 	{
904 	  rtx insn = bb->head;
905 	  static int ignore_next_note = 0;
906 
907 	  /* We are looking for line number notes.  Search backward before
908 	     basic block to find correct ones.  */
909 	  insn = prev_nonnote_insn (insn);
910 	  if (!insn)
911 	    insn = get_insns ();
912 	  else
913 	    insn = NEXT_INSN (insn);
914 
915 	  /* Output a zero to the .bb file to indicate that a new
916 	     block list is starting.  */
917 	  __write_long (0, bb_file, 4);
918 
919 	  while (insn != bb->end)
920 	    {
921 	      if (GET_CODE (insn) == NOTE)
922 		{
923 		  /* Must ignore the line number notes that immediately
924 		     follow the end of an inline function to avoid counting
925 		     it twice.  There is a note before the call, and one
926 		     after the call.  */
927 		  if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_REPEATED_LINE_NUMBER)
928 		    ignore_next_note = 1;
929 		  else if (NOTE_LINE_NUMBER (insn) > 0)
930 		    {
931 		      if (ignore_next_note)
932 			ignore_next_note = 0;
933 		      else
934 			{
935 			  /* If this is a new source file, then output the
936 			     file's name to the .bb file.  */
937 			  if (! last_bb_file_name
938 			      || strcmp (NOTE_SOURCE_FILE (insn),
939 					 last_bb_file_name))
940 			    {
941 			      if (last_bb_file_name)
942 				free (last_bb_file_name);
943 			      last_bb_file_name
944 				= xstrdup (NOTE_SOURCE_FILE (insn));
945 			      output_gcov_string (NOTE_SOURCE_FILE (insn),
946 						  (long)-1);
947 			    }
948 			  /* Output the line number to the .bb file.  Must be
949 			     done after the output_bb_profile_data() call, and
950 			     after the file name is written, to ensure that it
951 			     is correctly handled by gcov.  */
952 			  __write_long (NOTE_LINE_NUMBER (insn), bb_file, 4);
953 			}
954 		    }
955 		}
956 	      insn = NEXT_INSN (insn);
957 	    }
958 	}
959       __write_long (0, bb_file, 4);
960     }
961 
962   /* Create spanning tree from basic block graph, mark each edge that is
963      on the spanning tree.  We insert as many abnormal and critical edges
964      as possible to minimize number of edge splits necessary.  */
965 
966   find_spanning_tree (el);
967 
968   /* Fake edges that are not on the tree will not be instrumented, so
969      mark them ignored.  */
970   for (i = 0; i < num_edges; i++)
971     {
972       edge e = INDEX_EDGE (el, i);
973       struct edge_info *inf = EDGE_INFO (e);
974       if ((e->flags & EDGE_FAKE) && !inf->ignore && !inf->on_tree)
975 	{
976 	  inf->ignore = 1;
977 	  ignored_edges++;
978 	}
979     }
980 
981   total_num_blocks += n_basic_blocks + 2;
982   if (rtl_dump_file)
983     fprintf (rtl_dump_file, "%d basic blocks\n", n_basic_blocks);
984 
985   total_num_edges += num_edges;
986   if (rtl_dump_file)
987     fprintf (rtl_dump_file, "%d edges\n", num_edges);
988 
989   total_num_edges_ignored += ignored_edges;
990   if (rtl_dump_file)
991     fprintf (rtl_dump_file, "%d ignored edges\n", ignored_edges);
992 
993   /* Create a .bbg file from which gcov can reconstruct the basic block
994      graph.  First output the number of basic blocks, and then for every
995      edge output the source and target basic block numbers.
996      NOTE: The format of this file must be compatible with gcov.  */
997 
998   if (flag_test_coverage)
999     {
1000       int flag_bits;
1001 
1002       __write_gcov_string (name, strlen (name), bbg_file, -1);
1003 
1004       /* write checksum.  */
1005       __write_long (profile_info.current_function_cfg_checksum, bbg_file, 4);
1006 
1007       /* The plus 2 stands for entry and exit block.  */
1008       __write_long (n_basic_blocks + 2, bbg_file, 4);
1009       __write_long (num_edges - ignored_edges + 1, bbg_file, 4);
1010 
1011       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
1012 	{
1013 	  edge e;
1014 	  long count = 0;
1015 
1016 	  for (e = bb->succ; e; e = e->succ_next)
1017 	    if (!EDGE_INFO (e)->ignore)
1018 	      count++;
1019 	  __write_long (count, bbg_file, 4);
1020 
1021 	  for (e = bb->succ; e; e = e->succ_next)
1022 	    {
1023 	      struct edge_info *i = EDGE_INFO (e);
1024 	      if (!i->ignore)
1025 		{
1026 		  flag_bits = 0;
1027 		  if (i->on_tree)
1028 		    flag_bits |= 0x1;
1029 		  if (e->flags & EDGE_FAKE)
1030 		    flag_bits |= 0x2;
1031 		  if (e->flags & EDGE_FALLTHRU)
1032 		    flag_bits |= 0x4;
1033 
1034 		  __write_long (BB_TO_GCOV_INDEX (e->dest), bbg_file, 4);
1035 		  __write_long (flag_bits, bbg_file, 4);
1036 	        }
1037 	    }
1038 	}
1039       /* Emit fake loopback edge for EXIT block to maintain compatibility with
1040          old gcov format.  */
1041       __write_long (1, bbg_file, 4);
1042       __write_long (0, bbg_file, 4);
1043       __write_long (0x1, bbg_file, 4);
1044 
1045       /* Emit a -1 to separate the list of all edges from the list of
1046 	 loop back edges that follows.  */
1047       __write_long (-1, bbg_file, 4);
1048     }
1049 
1050   if (flag_branch_probabilities)
1051     compute_branch_probabilities ();
1052 
1053   /* For each edge not on the spanning tree, add counting code as rtl.  */
1054 
1055   if (profile_arc_flag)
1056     {
1057       instrument_edges (el);
1058       allocate_reg_info (max_reg_num (), FALSE, FALSE);
1059     }
1060 
1061   remove_fake_edges ();
1062   /* Re-merge split basic blocks and the mess introduced by
1063      insert_insn_on_edge.  */
1064   cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
1065   if (rtl_dump_file)
1066     dump_flow_info (rtl_dump_file);
1067 
1068   free_aux_for_edges ();
1069   free_edge_list (el);
1070 }
1071 
1072 /* Union find algorithm implementation for the basic blocks using
1073    aux fields.  */
1074 
1075 static basic_block
find_group(bb)1076 find_group (bb)
1077      basic_block bb;
1078 {
1079   basic_block group = bb, bb1;
1080 
1081   while ((basic_block) group->aux != group)
1082     group = (basic_block) group->aux;
1083 
1084   /* Compress path.  */
1085   while ((basic_block) bb->aux != group)
1086     {
1087       bb1 = (basic_block) bb->aux;
1088       bb->aux = (void *) group;
1089       bb = bb1;
1090     }
1091   return group;
1092 }
1093 
1094 static void
union_groups(bb1,bb2)1095 union_groups (bb1, bb2)
1096      basic_block bb1, bb2;
1097 {
1098   basic_block bb1g = find_group (bb1);
1099   basic_block bb2g = find_group (bb2);
1100 
1101   /* ??? I don't have a place for the rank field.  OK.  Lets go w/o it,
1102      this code is unlikely going to be performance problem anyway.  */
1103   if (bb1g == bb2g)
1104     abort ();
1105 
1106   bb1g->aux = bb2g;
1107 }
1108 
1109 /* This function searches all of the edges in the program flow graph, and puts
1110    as many bad edges as possible onto the spanning tree.  Bad edges include
1111    abnormals edges, which can't be instrumented at the moment.  Since it is
1112    possible for fake edges to form a cycle, we will have to develop some
1113    better way in the future.  Also put critical edges to the tree, since they
1114    are more expensive to instrument.  */
1115 
1116 static void
find_spanning_tree(el)1117 find_spanning_tree (el)
1118      struct edge_list *el;
1119 {
1120   int i;
1121   int num_edges = NUM_EDGES (el);
1122   basic_block bb;
1123 
1124   /* We use aux field for standard union-find algorithm.  */
1125   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1126     bb->aux = bb;
1127 
1128   /* Add fake edge exit to entry we can't instrument.  */
1129   union_groups (EXIT_BLOCK_PTR, ENTRY_BLOCK_PTR);
1130 
1131   /* First add all abnormal edges to the tree unless they form a cycle. Also
1132      add all edges to EXIT_BLOCK_PTR to avoid inserting profiling code behind
1133      setting return value from function.  */
1134   for (i = 0; i < num_edges; i++)
1135     {
1136       edge e = INDEX_EDGE (el, i);
1137       if (((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
1138 	   || e->dest == EXIT_BLOCK_PTR
1139 	   )
1140 	  && !EDGE_INFO (e)->ignore
1141 	  && (find_group (e->src) != find_group (e->dest)))
1142 	{
1143 	  if (rtl_dump_file)
1144 	    fprintf (rtl_dump_file, "Abnormal edge %d to %d put to tree\n",
1145 		     e->src->index, e->dest->index);
1146 	  EDGE_INFO (e)->on_tree = 1;
1147 	  union_groups (e->src, e->dest);
1148 	}
1149     }
1150 
1151   /* Now insert all critical edges to the tree unless they form a cycle.  */
1152   for (i = 0; i < num_edges; i++)
1153     {
1154       edge e = INDEX_EDGE (el, i);
1155       if ((EDGE_CRITICAL_P (e))
1156 	  && !EDGE_INFO (e)->ignore
1157 	  && (find_group (e->src) != find_group (e->dest)))
1158 	{
1159 	  if (rtl_dump_file)
1160 	    fprintf (rtl_dump_file, "Critical edge %d to %d put to tree\n",
1161 		     e->src->index, e->dest->index);
1162 	  EDGE_INFO (e)->on_tree = 1;
1163 	  union_groups (e->src, e->dest);
1164 	}
1165     }
1166 
1167   /* And now the rest.  */
1168   for (i = 0; i < num_edges; i++)
1169     {
1170       edge e = INDEX_EDGE (el, i);
1171       if (find_group (e->src) != find_group (e->dest)
1172 	  && !EDGE_INFO (e)->ignore)
1173 	{
1174 	  if (rtl_dump_file)
1175 	    fprintf (rtl_dump_file, "Normal edge %d to %d put to tree\n",
1176 		     e->src->index, e->dest->index);
1177 	  EDGE_INFO (e)->on_tree = 1;
1178 	  union_groups (e->src, e->dest);
1179 	}
1180     }
1181 
1182   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1183     bb->aux = NULL;
1184 }
1185 
1186 /* Perform file-level initialization for branch-prob processing.  */
1187 
1188 void
init_branch_prob(filename)1189 init_branch_prob (filename)
1190   const char *filename;
1191 {
1192   int len = strlen (filename);
1193   int i;
1194 
1195   if (flag_test_coverage)
1196     {
1197       char *data_file, *bbg_file_name;
1198 
1199       /* Open an output file for the basic block/line number map.  */
1200       data_file = (char *) alloca (len + 4);
1201       strcpy (data_file, filename);
1202       strcat (data_file, ".bb");
1203       if ((bb_file = fopen (data_file, "wb")) == 0)
1204 	fatal_io_error ("can't open %s", data_file);
1205 
1206       /* Open an output file for the program flow graph.  */
1207       bbg_file_name = (char *) alloca (len + 5);
1208       strcpy (bbg_file_name, filename);
1209       strcat (bbg_file_name, ".bbg");
1210       if ((bbg_file = fopen (bbg_file_name, "wb")) == 0)
1211 	fatal_io_error ("can't open %s", bbg_file_name);
1212 
1213       /* Initialize to zero, to ensure that the first file name will be
1214 	 written to the .bb file.  */
1215       last_bb_file_name = 0;
1216     }
1217 
1218   da_file_name = (char *) xmalloc (len + 4);
1219   strcpy (da_file_name, filename);
1220   strcat (da_file_name, ".da");
1221 
1222   if (flag_branch_probabilities)
1223     {
1224       da_file = fopen (da_file_name, "rb");
1225       if (!da_file)
1226 	warning ("file %s not found, execution counts assumed to be zero",
1227 		 da_file_name);
1228     }
1229 
1230   if (profile_arc_flag)
1231     init_edge_profiler ();
1232 
1233   total_num_blocks = 0;
1234   total_num_edges = 0;
1235   total_num_edges_ignored = 0;
1236   total_num_edges_instrumented = 0;
1237   total_num_blocks_created = 0;
1238   total_num_passes = 0;
1239   total_num_times_called = 0;
1240   total_num_branches = 0;
1241   total_num_never_executed = 0;
1242   for (i = 0; i < 20; i++)
1243     total_hist_br_prob[i] = 0;
1244 }
1245 
1246 /* Performs file-level cleanup after branch-prob processing
1247    is completed.  */
1248 
1249 void
end_branch_prob()1250 end_branch_prob ()
1251 {
1252   if (flag_test_coverage)
1253     {
1254       fclose (bb_file);
1255       fclose (bbg_file);
1256       unlink (da_file_name);
1257     }
1258 
1259   if (flag_branch_probabilities && da_file)
1260     fclose (da_file);
1261 
1262   if (rtl_dump_file)
1263     {
1264       fprintf (rtl_dump_file, "\n");
1265       fprintf (rtl_dump_file, "Total number of blocks: %d\n",
1266 	       total_num_blocks);
1267       fprintf (rtl_dump_file, "Total number of edges: %d\n", total_num_edges);
1268       fprintf (rtl_dump_file, "Total number of ignored edges: %d\n",
1269 	       total_num_edges_ignored);
1270       fprintf (rtl_dump_file, "Total number of instrumented edges: %d\n",
1271 	       total_num_edges_instrumented);
1272       fprintf (rtl_dump_file, "Total number of blocks created: %d\n",
1273 	       total_num_blocks_created);
1274       fprintf (rtl_dump_file, "Total number of graph solution passes: %d\n",
1275 	       total_num_passes);
1276       if (total_num_times_called != 0)
1277 	fprintf (rtl_dump_file, "Average number of graph solution passes: %d\n",
1278 		 (total_num_passes + (total_num_times_called  >> 1))
1279 		 / total_num_times_called);
1280       fprintf (rtl_dump_file, "Total number of branches: %d\n",
1281 	       total_num_branches);
1282       fprintf (rtl_dump_file, "Total number of branches never executed: %d\n",
1283 	       total_num_never_executed);
1284       if (total_num_branches)
1285 	{
1286 	  int i;
1287 
1288 	  for (i = 0; i < 10; i++)
1289 	    fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
1290 		     (total_hist_br_prob[i] + total_hist_br_prob[19-i]) * 100
1291 		     / total_num_branches, 5*i, 5*i+5);
1292 	}
1293     }
1294 }
1295 
1296 /* The label used by the edge profiling code.  */
1297 
1298 static GTY(()) rtx profiler_label;
1299 
1300 /* Initialize the profiler_label.  */
1301 
1302 static void
init_edge_profiler()1303 init_edge_profiler ()
1304 {
1305   /* Generate and save a copy of this so it can be shared.  */
1306   char buf[20];
1307   ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 2);
1308   profiler_label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
1309 }
1310 
1311 /* Output instructions as RTL to increment the edge execution count.  */
1312 
1313 static rtx
gen_edge_profiler(edgeno)1314 gen_edge_profiler (edgeno)
1315      int edgeno;
1316 {
1317   enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
1318   rtx mem_ref, tmp;
1319   rtx sequence;
1320 
1321   start_sequence ();
1322 
1323   tmp = force_reg (Pmode, profiler_label);
1324   tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
1325   mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
1326 
1327   set_mem_alias_set (mem_ref, new_alias_set ());
1328 
1329   tmp = expand_simple_binop (mode, PLUS, mem_ref, const1_rtx,
1330 			     mem_ref, 0, OPTAB_WIDEN);
1331 
1332   if (tmp != mem_ref)
1333     emit_move_insn (copy_rtx (mem_ref), tmp);
1334 
1335   sequence = get_insns ();
1336   end_sequence ();
1337   return sequence;
1338 }
1339 
1340 /* Output code for a constructor that will invoke __bb_init_func, if
1341    this has not already been done.  */
1342 
1343 void
output_func_start_profiler()1344 output_func_start_profiler ()
1345 {
1346   tree fnname, fndecl;
1347   char *name;
1348   char buf[20];
1349   const char *cfnname;
1350   rtx table_address;
1351   enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
1352   int save_flag_inline_functions = flag_inline_functions;
1353 
1354   /* It's either already been output, or we don't need it because we're
1355      not doing profile-edges.  */
1356   if (! need_func_profiler)
1357     return;
1358 
1359   need_func_profiler = 0;
1360 
1361   /* Synthesize a constructor function to invoke __bb_init_func with a
1362      pointer to this object file's profile block.  */
1363 
1364   /* Try and make a unique name given the "file function name".
1365 
1366      And no, I don't like this either.  */
1367 
1368   fnname = get_file_function_name ('I');
1369   cfnname = IDENTIFIER_POINTER (fnname);
1370   name = concat (cfnname, "GCOV", NULL);
1371   fnname = get_identifier (name);
1372   free (name);
1373 
1374   fndecl = build_decl (FUNCTION_DECL, fnname,
1375 		       build_function_type (void_type_node, NULL_TREE));
1376   DECL_EXTERNAL (fndecl) = 0;
1377 
1378   /* It can be a static function as long as collect2 does not have
1379      to scan the object file to find its ctor/dtor routine.  */
1380   TREE_PUBLIC (fndecl) = ! targetm.have_ctors_dtors;
1381 
1382   TREE_USED (fndecl) = 1;
1383 
1384   DECL_RESULT (fndecl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
1385 
1386   fndecl = (*lang_hooks.decls.pushdecl) (fndecl);
1387   rest_of_decl_compilation (fndecl, 0, 1, 0);
1388   announce_function (fndecl);
1389   current_function_decl = fndecl;
1390   DECL_INITIAL (fndecl) = error_mark_node;
1391   make_decl_rtl (fndecl, NULL);
1392   init_function_start (fndecl, input_filename, lineno);
1393   (*lang_hooks.decls.pushlevel) (0);
1394   expand_function_start (fndecl, 0);
1395   cfun->arc_profile = 0;
1396 
1397   /* Actually generate the code to call __bb_init_func.  */
1398   ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 0);
1399   table_address = force_reg (Pmode,
1400 			     gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf)));
1401   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__bb_init_func"), LCT_NORMAL,
1402 		     mode, 1, table_address, Pmode);
1403 
1404   expand_function_end (input_filename, lineno, 0);
1405   (*lang_hooks.decls.poplevel) (1, 0, 1);
1406 
1407   /* Since fndecl isn't in the list of globals, it would never be emitted
1408      when it's considered to be 'safe' for inlining, so turn off
1409      flag_inline_functions.  */
1410   flag_inline_functions = 0;
1411 
1412   rest_of_compilation (fndecl);
1413 
1414   /* Reset flag_inline_functions to its original value.  */
1415   flag_inline_functions = save_flag_inline_functions;
1416 
1417   if (! quiet_flag)
1418     fflush (asm_out_file);
1419   current_function_decl = NULL_TREE;
1420 
1421   if (targetm.have_ctors_dtors)
1422     (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
1423 				     DEFAULT_INIT_PRIORITY);
1424 }
1425 
1426 #include "gt-profile.h"
1427