profile.c revision 117395
1333347Speter/* Calculate branch probabilities, and basic block execution counts.
2333347Speter   Copyright (C) 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998, 1999,
3333347Speter   2000, 2001  Free Software Foundation, Inc.
4333347Speter   Contributed by James E. Wilson, UC Berkeley/Cygnus Support;
5333347Speter   based on some ideas from Dain Samples of UC Berkeley.
6333347Speter   Further mangling by Bob Manson, Cygnus Support.
7333347Speter
8333347SpeterThis file is part of GCC.
9333347Speter
10333347SpeterGCC is free software; you can redistribute it and/or modify it under
11333347Speterthe terms of the GNU General Public License as published by the Free
12333347SpeterSoftware Foundation; either version 2, or (at your option) any later
13333347Speterversion.
14333347Speter
15333347SpeterGCC is distributed in the hope that it will be useful, but WITHOUT ANY
16333347SpeterWARRANTY; without even the implied warranty of MERCHANTABILITY or
17333347SpeterFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18333347Speterfor more details.
19333347Speter
20333347SpeterYou should have received a copy of the GNU General Public License
21333347Speteralong with GCC; see the file COPYING.  If not, write to the Free
22333347SpeterSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
23333347Speter02111-1307, USA.  */
24333347Speter
25333347Speter/* Generate basic block profile instrumentation and auxiliary files.
26333347Speter   Profile generation is optimized, so that not all arcs in the basic
27333347Speter   block graph need instrumenting. First, the BB graph is closed with
28333347Speter   one entry (function start), and one exit (function exit).  Any
29333347Speter   ABNORMAL_EDGE cannot be instrumented (because there is no control
30333347Speter   path to place the code). We close the graph by inserting fake
31333347Speter   EDGE_FAKE edges to the EXIT_BLOCK, from the sources of abnormal
32333347Speter   edges that do not go to the exit_block. We ignore such abnormal
33333347Speter   edges.  Naturally these fake edges are never directly traversed,
34333347Speter   and so *cannot* be directly instrumented.  Some other graph
35333347Speter   massaging is done. To optimize the instrumentation we generate the
36333347Speter   BB minimal span tree, only edges that are not on the span tree
37333347Speter   (plus the entry point) need instrumenting. From that information
38333347Speter   all other edge counts can be deduced.  By construction all fake
39333347Speter   edges must be on the spanning tree. We also attempt to place
40333347Speter   EDGE_CRITICAL edges on the spanning tree.
41333347Speter
42333347Speter   The two auxiliary files generated are <dumpbase>.bb and
43333347Speter   <dumpbase>.bbg. The former contains the BB->linenumber
44333347Speter   mappings, and the latter describes the BB graph.
45333347Speter
46333347Speter   The BB file contains line numbers for each block. For each basic
47333347Speter   block, a zero count is output (to mark the start of a block), then
48333347Speter   the line numbers of that block are listed. A zero ends the file
49333347Speter   too.
50333347Speter
51333347Speter   The BBG file contains a count of the blocks, followed by edge
52333347Speter   information, for every edge in the graph. The edge information
53333347Speter   lists the source and target block numbers, and a bit mask
54333347Speter   describing the type of edge.
55333347Speter
56333347Speter   The BB and BBG file formats are fully described in the gcov
57333347Speter   documentation.  */
58333347Speter
59333347Speter/* ??? Register allocation should use basic block execution counts to
60333347Speter   give preference to the most commonly executed blocks.  */
61333347Speter
62333347Speter/* ??? The .da files are not safe.  Changing the program after creating .da
63333347Speter   files or using different options when compiling with -fbranch-probabilities
64333347Speter   can result the arc data not matching the program.  Maybe add instrumented
65333347Speter   arc count to .bbg file?  Maybe check whether PFG matches the .bbg file?  */
66333347Speter
67333347Speter/* ??? Should calculate branch probabilities before instrumenting code, since
68333347Speter   then we can use arc counts to help decide which arcs to instrument.  */
69333347Speter
70333347Speter#include "config.h"
71333347Speter#include "system.h"
72333347Speter#include "rtl.h"
73333347Speter#include "tree.h"
74333347Speter#include "flags.h"
75333347Speter#include "insn-config.h"
76333347Speter#include "output.h"
77333347Speter#include "regs.h"
78333347Speter#include "expr.h"
79333347Speter#include "function.h"
80333347Speter#include "toplev.h"
81333347Speter#include "ggc.h"
82333347Speter#include "hard-reg-set.h"
83333347Speter#include "basic-block.h"
84333347Speter#include "gcov-io.h"
85333347Speter#include "target.h"
86333347Speter#include "profile.h"
87333347Speter#include "libfuncs.h"
88333347Speter#include "langhooks.h"
89333347Speter
90333347Speter/* Additional information about the edges we need.  */
91333347Speterstruct edge_info {
92333347Speter  unsigned int count_valid : 1;
93333347Speter
94333347Speter  /* Is on the spanning tree.  */
95333347Speter  unsigned int on_tree : 1;
96333347Speter
97333347Speter  /* Pretend this edge does not exist (it is abnormal and we've
98333347Speter     inserted a fake to compensate).  */
99333347Speter  unsigned int ignore : 1;
100333347Speter};
101333347Speter
102333347Speterstruct bb_info {
103333347Speter  unsigned int count_valid : 1;
104333347Speter
105333347Speter  /* Number of successor and predecessor edges.  */
106333347Speter  gcov_type succ_count;
107333347Speter  gcov_type pred_count;
108333347Speter};
109333347Speter
110333347Speter#define EDGE_INFO(e)  ((struct edge_info *) (e)->aux)
111333347Speter#define BB_INFO(b)  ((struct bb_info *) (b)->aux)
112333347Speter
113333347Speter/* Keep all basic block indexes nonnegative in the gcov output.  Index 0
114333347Speter   is used for entry block, last block exit block.  */
115333347Speter#define BB_TO_GCOV_INDEX(bb)  ((bb) == ENTRY_BLOCK_PTR ? 0		\
116333347Speter			       : ((bb) == EXIT_BLOCK_PTR		\
117333347Speter				  ? last_basic_block + 1 : (bb)->index + 1))
118333347Speter
119333347Speter/* Instantiate the profile info structure.  */
120333347Speter
121333347Speterstruct profile_info profile_info;
122333347Speter
123333347Speter/* Name and file pointer of the output file for the basic block graph.  */
124333347Speter
125333347Speterstatic FILE *bbg_file;
126333347Speter
127333347Speter/* Name and file pointer of the input file for the arc count data.  */
128333347Speter
129333347Speterstatic FILE *da_file;
130333347Speterstatic char *da_file_name;
131333347Speter
132333347Speter/* Pointer of the output file for the basic block/line number map.  */
133333347Speterstatic FILE *bb_file;
134333347Speter
135333347Speter/* Last source file name written to bb_file.  */
136333347Speter
137333347Speterstatic char *last_bb_file_name;
138333347Speter
139333347Speter/* Collect statistics on the performance of this pass for the entire source
140333347Speter   file.  */
141333347Speter
142333347Speterstatic int total_num_blocks;
143333347Speterstatic int total_num_edges;
144333347Speterstatic int total_num_edges_ignored;
145333347Speterstatic int total_num_edges_instrumented;
146333347Speterstatic int total_num_blocks_created;
147333347Speterstatic int total_num_passes;
148333347Speterstatic int total_num_times_called;
149333347Speterstatic int total_hist_br_prob[20];
150333347Speterstatic int total_num_never_executed;
151362181Sdimstatic int total_num_branches;
152362181Sdim
153362181Sdim/* Forward declarations.  */
154362181Sdimstatic void find_spanning_tree PARAMS ((struct edge_list *));
155362181Sdimstatic void init_edge_profiler PARAMS ((void));
156362181Sdimstatic rtx gen_edge_profiler PARAMS ((int));
157362181Sdimstatic void instrument_edges PARAMS ((struct edge_list *));
158362181Sdimstatic void output_gcov_string PARAMS ((const char *, long));
159362181Sdimstatic void compute_branch_probabilities PARAMS ((void));
160362181Sdimstatic gcov_type * get_exec_counts PARAMS ((void));
161333347Speterstatic long compute_checksum PARAMS ((void));
162333347Speterstatic basic_block find_group PARAMS ((basic_block));
163333347Speterstatic void union_groups PARAMS ((basic_block, basic_block));
164362181Sdim
165362181Sdim/* If nonzero, we need to output a constructor to set up the
166362181Sdim   per-object-file data.  */
167333347Speterstatic int need_func_profiler = 0;
168333347Speter
169333347Speter/* Add edge instrumentation code to the entire insn chain.
170333347Speter
171333347Speter   F is the first insn of the chain.
172333347Speter   NUM_BLOCKS is the number of basic blocks found in F.  */
173362181Sdim
174362181Sdimstatic void
175362181Sdiminstrument_edges (el)
176362181Sdim     struct edge_list *el;
177362181Sdim{
178362181Sdim  int num_instr_edges = 0;
179362181Sdim  int num_edges = NUM_EDGES (el);
180362181Sdim  basic_block bb;
181362181Sdim  remove_fake_edges ();
182333347Speter
183362181Sdim  FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
184362181Sdim    {
185362181Sdim      edge e = bb->succ;
186362181Sdim      while (e)
187362181Sdim	{
188362181Sdim	  struct edge_info *inf = EDGE_INFO (e);
189362181Sdim	  if (!inf->ignore && !inf->on_tree)
190362181Sdim	    {
191362181Sdim	      if (e->flags & EDGE_ABNORMAL)
192362181Sdim		abort ();
193333347Speter	      if (rtl_dump_file)
194333347Speter		fprintf (rtl_dump_file, "Edge %d to %d instrumented%s\n",
195362181Sdim			 e->src->index, e->dest->index,
196333347Speter			 EDGE_CRITICAL_P (e) ? " (and split)" : "");
197333347Speter	      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
219static void
220output_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
252static gcov_type *
253get_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
418static void
419compute_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
733static long
734compute_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
770void
771branch_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
1075static basic_block
1076find_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
1094static void
1095union_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
1116static void
1117find_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
1188void
1189init_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
1249void
1250end_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
1298static GTY(()) rtx profiler_label;
1299
1300/* Initialize the profiler_label.  */
1301
1302static void
1303init_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
1313static rtx
1314gen_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
1343void
1344output_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