OSDN Git Service

* tree-inline.c (find_builtin_longjmp_call): Save and restore
[pf3gnuchains/gcc-fork.git] / gcc / profile.c
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 auxiliary file generated is <dumpbase>.bbg. The format is
43    described in full in gcov-io.h.  */
44
45 /* ??? Register allocation should use basic block execution counts to
46    give preference to the most commonly executed blocks.  */
47
48 /* ??? Should calculate branch probabilities before instrumenting code, since
49    then we can use arc counts to help decide which arcs to instrument.  */
50
51 #include "config.h"
52 #include "system.h"
53 #include "coretypes.h"
54 #include "tm.h"
55 #include "rtl.h"
56 #include "tree.h"
57 #include "flags.h"
58 #include "insn-config.h"
59 #include "output.h"
60 #include "regs.h"
61 #include "expr.h"
62 #include "function.h"
63 #include "toplev.h"
64 #include "ggc.h"
65 #include "hard-reg-set.h"
66 #include "basic-block.h"
67 #include "gcov-io.h"
68 #include "target.h"
69 #include "profile.h"
70 #include "libfuncs.h"
71 #include "langhooks.h"
72 #include "hashtab.h"
73
74 /* Additional information about the edges we need.  */
75 struct edge_info {
76   unsigned int count_valid : 1;
77   
78   /* Is on the spanning tree.  */
79   unsigned int on_tree : 1;
80   
81   /* Pretend this edge does not exist (it is abnormal and we've
82      inserted a fake to compensate).  */
83   unsigned int ignore : 1;
84 };
85
86 struct bb_info {
87   unsigned int count_valid : 1;
88
89   /* Number of successor and predecessor edges.  */
90   gcov_type succ_count;
91   gcov_type pred_count;
92 };
93
94 struct function_list
95 {
96   struct function_list *next;   /* next function */
97   const char *name;             /* function name */
98   unsigned cfg_checksum;        /* function checksum */
99   unsigned n_counter_sections;  /* number of counter sections */
100   struct counter_section counter_sections[MAX_COUNTER_SECTIONS];
101                                 /* the sections */
102 };
103
104 static struct function_list *functions_head = 0;
105 static struct function_list **functions_tail = &functions_head;
106
107 #define EDGE_INFO(e)  ((struct edge_info *) (e)->aux)
108 #define BB_INFO(b)  ((struct bb_info *) (b)->aux)
109
110 /* Keep all basic block indexes nonnegative in the gcov output.  Index 0
111    is used for entry block, last block exit block.  */
112 #define BB_TO_GCOV_INDEX(bb)  ((bb) == ENTRY_BLOCK_PTR ? 0              \
113                                : ((bb) == EXIT_BLOCK_PTR                \
114                                   ? last_basic_block + 1 : (bb)->index + 1))
115
116 /* Instantiate the profile info structure.  */
117
118 struct profile_info profile_info;
119
120 /* Name and file pointer of the output file for the basic block graph.  */
121
122 static FILE *bbg_file;
123 static char *bbg_file_name;
124
125 /* Name and file pointer of the input file for the arc count data.  */
126
127 static FILE *da_file;
128 static char *da_file_name;
129
130 /* The name of the count table. Used by the edge profiling code.  */
131 static GTY(()) rtx profiler_label;
132
133 /* Collect statistics on the performance of this pass for the entire source
134    file.  */
135
136 static int total_num_blocks;
137 static int total_num_edges;
138 static int total_num_edges_ignored;
139 static int total_num_edges_instrumented;
140 static int total_num_blocks_created;
141 static int total_num_passes;
142 static int total_num_times_called;
143 static int total_hist_br_prob[20];
144 static int total_num_never_executed;
145 static int total_num_branches;
146
147 /* Forward declarations.  */
148 static void find_spanning_tree PARAMS ((struct edge_list *));
149 static rtx gen_edge_profiler PARAMS ((int));
150 static void instrument_edges PARAMS ((struct edge_list *));
151 static void compute_branch_probabilities PARAMS ((void));
152 static hashval_t htab_counts_index_hash PARAMS ((const void *));
153 static int htab_counts_index_eq PARAMS ((const void *, const void *));
154 static void htab_counts_index_del PARAMS ((void *));
155 static void cleanup_counts_index PARAMS ((int));
156 static int index_counts_file PARAMS ((void));
157 static gcov_type * get_exec_counts PARAMS ((void));
158 static unsigned compute_checksum PARAMS ((void));
159 static basic_block find_group PARAMS ((basic_block));
160 static void union_groups PARAMS ((basic_block, basic_block));
161 static void set_purpose PARAMS ((tree, tree));
162 static rtx label_for_tag PARAMS ((unsigned));
163 static tree build_counter_section_fields PARAMS ((void));
164 static tree build_counter_section_value PARAMS ((unsigned, unsigned));
165 static tree build_counter_section_data_fields PARAMS ((void));
166 static tree build_counter_section_data_value PARAMS ((unsigned, unsigned));
167 static tree build_function_info_fields PARAMS ((void));
168 static tree build_function_info_value PARAMS ((struct function_list *));
169 static tree build_gcov_info_fields PARAMS ((tree));
170 static tree build_gcov_info_value PARAMS ((void));
171
172 \f
173 /* Add edge instrumentation code to the entire insn chain.
174
175    F is the first insn of the chain.
176    NUM_BLOCKS is the number of basic blocks found in F.  */
177
178 static void
179 instrument_edges (el)
180      struct edge_list *el;
181 {
182   int num_instr_edges = 0;
183   int num_edges = NUM_EDGES (el);
184   basic_block bb;
185   struct section_info *section_info;
186   remove_fake_edges ();
187
188   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
189     {
190       edge e = bb->succ;
191       while (e)
192         {
193           struct edge_info *inf = EDGE_INFO (e);
194           if (!inf->ignore && !inf->on_tree)
195             {
196               if (e->flags & EDGE_ABNORMAL)
197                 abort ();
198               if (rtl_dump_file)
199                 fprintf (rtl_dump_file, "Edge %d to %d instrumented%s\n",
200                          e->src->index, e->dest->index,
201                          EDGE_CRITICAL_P (e) ? " (and split)" : "");
202               insert_insn_on_edge (
203                          gen_edge_profiler (total_num_edges_instrumented
204                                             + num_instr_edges++), e);
205             }
206           e = e->succ_next;
207         }
208     }
209
210   section_info = find_counters_section (GCOV_TAG_ARC_COUNTS);
211   section_info->n_counters_now = num_instr_edges;
212   total_num_edges_instrumented += num_instr_edges;
213   section_info->n_counters = total_num_edges_instrumented;
214
215   total_num_blocks_created += num_edges;
216   if (rtl_dump_file)
217     fprintf (rtl_dump_file, "%d edges instrumented\n", num_instr_edges);
218 }
219 \f
220 struct section_reference
221 {
222   long offset;
223   int owns_summary;
224   long *summary;
225 };
226
227 struct da_index_entry
228 {
229   /* We hash by  */
230   char *function_name;
231   unsigned section;
232   /* and store  */
233   unsigned checksum;
234   unsigned n_offsets;
235   struct section_reference *offsets;
236 };
237
238 static hashval_t
239 htab_counts_index_hash (of)
240      const void *of;
241 {
242   const struct da_index_entry *entry = of;
243
244   return htab_hash_string (entry->function_name) ^ entry->section;
245 }
246
247 static int
248 htab_counts_index_eq (of1, of2)
249      const void *of1;
250      const void *of2;
251 {
252   const struct da_index_entry *entry1 = of1;
253   const struct da_index_entry *entry2 = of2;
254
255   return !strcmp (entry1->function_name, entry2->function_name)
256           && entry1->section == entry2->section;
257 }
258
259 static void
260 htab_counts_index_del (what)
261      void *what;
262 {
263   struct da_index_entry *entry = what;
264   unsigned i;
265
266   for (i = 0; i < entry->n_offsets; i++)
267     {
268       struct section_reference *act = entry->offsets + i;
269       if (act->owns_summary)
270         free (act->summary);
271     }
272   free (entry->function_name);
273   free (entry->offsets);
274   free (entry);
275 }
276
277 static char *counts_file_name;
278 static htab_t counts_file_index = NULL;
279
280 static void
281 cleanup_counts_index (close_file)
282      int close_file;
283 {
284   if (da_file && close_file)
285     {
286       fclose (da_file);
287       da_file = NULL;
288     }
289   if (counts_file_name)
290     free (counts_file_name);
291   counts_file_name = NULL;
292   if (counts_file_index)
293     htab_delete (counts_file_index);
294   counts_file_index = NULL;
295 }
296
297 static int
298 index_counts_file ()
299 {
300   char *function_name_buffer = NULL;
301   unsigned magic, version, ix, checksum;
302   long *summary;
303
304   /* No .da file, no data.  */
305   if (!da_file)
306     return 0;
307   counts_file_index = htab_create (10, htab_counts_index_hash, htab_counts_index_eq, htab_counts_index_del);
308
309   /* Now index all profile sections.  */
310   rewind (da_file);
311
312   summary = NULL;
313
314   if (gcov_read_unsigned (da_file, &magic) || magic != GCOV_DATA_MAGIC)
315     {
316       warning ("`%s' is not a gcov data file", da_file_name);
317       goto cleanup;
318     }
319   if (gcov_read_unsigned (da_file, &version) || version != GCOV_VERSION)
320     {
321       char v[4], e[4];
322       magic = GCOV_VERSION;
323       
324       for (ix = 4; ix--; magic >>= 8, version >>= 8)
325         {
326           v[ix] = version;
327           e[ix] = magic;
328         }
329       warning ("`%s' is version `%.4s', expected version `%.4s'",
330                da_file_name, v, e);
331       goto cleanup;
332     }
333   
334   while (1)
335     {
336       unsigned tag, length;
337       long offset;
338       
339       offset = gcov_save_position (da_file);
340       if (gcov_read_unsigned (da_file, &tag)
341           || gcov_read_unsigned (da_file, &length))
342         {
343           if (feof (da_file))
344             break;
345         corrupt:;
346           warning ("`%s' is corrupted", da_file_name);
347           goto cleanup;
348         }
349       if (tag == GCOV_TAG_FUNCTION)
350         {
351           if (gcov_read_string (da_file, &function_name_buffer, NULL)
352               || gcov_read_unsigned (da_file, &checksum))
353             goto corrupt;
354           continue;
355         }
356       if (tag == GCOV_TAG_PROGRAM_SUMMARY)
357         {
358           if (length != GCOV_SUMMARY_LENGTH)
359             goto corrupt;
360
361           if (summary)
362             *summary = offset;
363           summary = NULL;
364         }
365       else
366         {
367           if (function_name_buffer)
368             {
369               struct da_index_entry **slot, elt;
370               elt.function_name = function_name_buffer;
371               elt.section = tag;
372
373               slot = (struct da_index_entry **)
374                 htab_find_slot (counts_file_index, &elt, INSERT);
375               if (*slot)
376                 {
377                   if ((*slot)->checksum != checksum)
378                     {
379                       warning ("profile mismatch for `%s'", function_name_buffer);
380                       goto cleanup;
381                     }
382                   (*slot)->n_offsets++;
383                   (*slot)->offsets = xrealloc ((*slot)->offsets,
384                                                sizeof (struct section_reference) * (*slot)->n_offsets);
385                 }
386               else
387                 {
388                   *slot = xmalloc (sizeof (struct da_index_entry));
389                   (*slot)->function_name = xstrdup (function_name_buffer);
390                   (*slot)->section = tag;
391                   (*slot)->checksum = checksum;
392                   (*slot)->n_offsets = 1;
393                   (*slot)->offsets = xmalloc (sizeof (struct section_reference));
394                 }
395               (*slot)->offsets[(*slot)->n_offsets - 1].offset = offset;
396               if (summary)
397                 (*slot)->offsets[(*slot)->n_offsets - 1].owns_summary = 0;
398               else
399                 {
400                   summary = xmalloc (sizeof (long));
401                   *summary = -1;
402                   (*slot)->offsets[(*slot)->n_offsets - 1].owns_summary = 1;
403                 }
404               (*slot)->offsets[(*slot)->n_offsets - 1].summary = summary;
405             }
406         }
407       if (gcov_skip (da_file, length))
408         goto corrupt;
409     }
410
411   free (function_name_buffer);
412
413   return 1;
414
415 cleanup:
416   cleanup_counts_index (1);
417   if (function_name_buffer)
418     free (function_name_buffer);
419   return 0;
420 }
421
422 /* Computes hybrid profile for all matching entries in da_file.
423    Sets max_counter_in_program as a side effect.  */
424
425 static gcov_type *
426 get_exec_counts ()
427 {
428   unsigned num_edges = 0;
429   basic_block bb;
430   gcov_type *profile;
431   gcov_type max_count;
432   unsigned ix, i, tag, length, num;
433   const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
434   struct da_index_entry *entry, what;
435   struct section_reference *act;
436   gcov_type count;
437   struct gcov_summary summ;
438
439   profile_info.max_counter_in_program = 0;
440   profile_info.count_profiles_merged = 0;
441
442   /* No .da file, no execution counts.  */
443   if (!da_file)
444     return NULL;
445   if (!counts_file_index)
446     abort ();
447
448   /* Count the edges to be (possibly) instrumented.  */
449
450   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
451     {
452       edge e;
453       for (e = bb->succ; e; e = e->succ_next)
454         if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
455           num_edges++;
456     }
457
458   /* now read and combine all matching profiles.  */
459
460   profile = xmalloc (sizeof (gcov_type) * num_edges);
461
462   for (ix = 0; ix < num_edges; ix++)
463     profile[ix] = 0;
464
465   what.function_name = (char *) name;
466   what.section = GCOV_TAG_ARC_COUNTS;
467   entry = htab_find (counts_file_index, &what);
468   if (!entry)
469     {
470       warning ("No profile for function '%s' found.", name);
471       goto cleanup;
472     }
473   
474   if (entry->checksum != profile_info.current_function_cfg_checksum)
475     {
476       warning ("profile mismatch for `%s'", current_function_name);
477       goto cleanup;
478     }
479
480   for (i = 0; i < entry->n_offsets; i++)
481     {
482       act = entry->offsets + i;
483
484       /* Read arc counters.  */
485       max_count = 0;
486       gcov_resync (da_file, act->offset, 0);
487
488       if (gcov_read_unsigned (da_file, &tag)
489           || gcov_read_unsigned (da_file, &length)
490           || tag != GCOV_TAG_ARC_COUNTS)
491         {
492           /* We have already passed through file, so any error means
493              something is rotten.  */
494           abort ();
495         }
496       num = length / 8;
497
498       if (num != num_edges)
499         {
500           warning ("profile mismatch for `%s'", current_function_name);
501           goto cleanup;
502         }
503           
504       for (ix = 0; ix != num; ix++)
505         {
506           if (gcov_read_counter (da_file, &count))
507             abort ();
508           if (count > max_count)
509             max_count = count;
510           profile[ix] += count;
511         }
512
513       /* Read program summary.  */
514       if (*act->summary != -1)
515         {
516           gcov_resync (da_file, *act->summary, 0);
517           if (gcov_read_unsigned (da_file, &tag)
518               || gcov_read_unsigned (da_file, &length)
519               || tag != GCOV_TAG_PROGRAM_SUMMARY
520               || gcov_read_summary (da_file, &summ))
521             abort ();
522           profile_info.count_profiles_merged += summ.runs;
523           profile_info.max_counter_in_program += summ.arc_sum_max;
524         }
525       else
526         summ.runs = 0;
527       if (!summ.runs)
528         {
529           profile_info.count_profiles_merged++;
530           profile_info.max_counter_in_program += max_count;
531         }
532     }
533
534   if (rtl_dump_file)
535     {
536       fprintf(rtl_dump_file, "Merged %i profiles with maximal count %i.\n",
537               profile_info.count_profiles_merged,
538               (int)profile_info.max_counter_in_program);
539     }
540
541   return profile;
542
543 cleanup:;
544   free (profile);
545   cleanup_counts_index (1);
546   return NULL;
547 }
548 \f
549
550 /* Compute the branch probabilities for the various branches.
551    Annotate them accordingly.  */
552
553 static void
554 compute_branch_probabilities ()
555 {
556   basic_block bb;
557   int i;
558   int num_edges = 0;
559   int changes;
560   int passes;
561   int hist_br_prob[20];
562   int num_never_executed;
563   int num_branches;
564   gcov_type *exec_counts = get_exec_counts ();
565   int exec_counts_pos = 0;
566
567   /* Attach extra info block to each bb.  */
568
569   alloc_aux_for_blocks (sizeof (struct bb_info));
570   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
571     {
572       edge e;
573
574       for (e = bb->succ; e; e = e->succ_next)
575         if (!EDGE_INFO (e)->ignore)
576           BB_INFO (bb)->succ_count++;
577       for (e = bb->pred; e; e = e->pred_next)
578         if (!EDGE_INFO (e)->ignore)
579           BB_INFO (bb)->pred_count++;
580     }
581
582   /* Avoid predicting entry on exit nodes.  */
583   BB_INFO (EXIT_BLOCK_PTR)->succ_count = 2;
584   BB_INFO (ENTRY_BLOCK_PTR)->pred_count = 2;
585
586   /* For each edge not on the spanning tree, set its execution count from
587      the .da file.  */
588
589   /* The first count in the .da file is the number of times that the function
590      was entered.  This is the exec_count for block zero.  */
591
592   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
593     {
594       edge e;
595       for (e = bb->succ; e; e = e->succ_next)
596         if (!EDGE_INFO (e)->ignore && !EDGE_INFO (e)->on_tree)
597           {
598             num_edges++;
599             if (exec_counts)
600               {
601                 e->count = exec_counts[exec_counts_pos++];
602               }
603             else
604               e->count = 0;
605
606             EDGE_INFO (e)->count_valid = 1;
607             BB_INFO (bb)->succ_count--;
608             BB_INFO (e->dest)->pred_count--;
609             if (rtl_dump_file)
610               {
611                 fprintf (rtl_dump_file, "\nRead edge from %i to %i, count:",
612                          bb->index, e->dest->index);
613                 fprintf (rtl_dump_file, HOST_WIDEST_INT_PRINT_DEC,
614                          (HOST_WIDEST_INT) e->count);
615               }
616           }
617     }
618
619   if (rtl_dump_file)
620     fprintf (rtl_dump_file, "\n%d edge counts read\n", num_edges);
621
622   /* For every block in the file,
623      - if every exit/entrance edge has a known count, then set the block count
624      - if the block count is known, and every exit/entrance edge but one has
625      a known execution count, then set the count of the remaining edge
626
627      As edge counts are set, decrement the succ/pred count, but don't delete
628      the edge, that way we can easily tell when all edges are known, or only
629      one edge is unknown.  */
630
631   /* The order that the basic blocks are iterated through is important.
632      Since the code that finds spanning trees starts with block 0, low numbered
633      edges are put on the spanning tree in preference to high numbered edges.
634      Hence, most instrumented edges are at the end.  Graph solving works much
635      faster if we propagate numbers from the end to the start.
636
637      This takes an average of slightly more than 3 passes.  */
638
639   changes = 1;
640   passes = 0;
641   while (changes)
642     {
643       passes++;
644       changes = 0;
645       FOR_BB_BETWEEN (bb, EXIT_BLOCK_PTR, NULL, prev_bb)
646         {
647           struct bb_info *bi = BB_INFO (bb);
648           if (! bi->count_valid)
649             {
650               if (bi->succ_count == 0)
651                 {
652                   edge e;
653                   gcov_type total = 0;
654
655                   for (e = bb->succ; e; e = e->succ_next)
656                     total += e->count;
657                   bb->count = total;
658                   bi->count_valid = 1;
659                   changes = 1;
660                 }
661               else if (bi->pred_count == 0)
662                 {
663                   edge e;
664                   gcov_type total = 0;
665
666                   for (e = bb->pred; e; e = e->pred_next)
667                     total += e->count;
668                   bb->count = total;
669                   bi->count_valid = 1;
670                   changes = 1;
671                 }
672             }
673           if (bi->count_valid)
674             {
675               if (bi->succ_count == 1)
676                 {
677                   edge e;
678                   gcov_type total = 0;
679
680                   /* One of the counts will be invalid, but it is zero,
681                      so adding it in also doesn't hurt.  */
682                   for (e = bb->succ; e; e = e->succ_next)
683                     total += e->count;
684
685                   /* Seedgeh for the invalid edge, and set its count.  */
686                   for (e = bb->succ; e; e = e->succ_next)
687                     if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
688                       break;
689
690                   /* Calculate count for remaining edge by conservation.  */
691                   total = bb->count - total;
692
693                   if (! e)
694                     abort ();
695                   EDGE_INFO (e)->count_valid = 1;
696                   e->count = total;
697                   bi->succ_count--;
698
699                   BB_INFO (e->dest)->pred_count--;
700                   changes = 1;
701                 }
702               if (bi->pred_count == 1)
703                 {
704                   edge e;
705                   gcov_type total = 0;
706
707                   /* One of the counts will be invalid, but it is zero,
708                      so adding it in also doesn't hurt.  */
709                   for (e = bb->pred; e; e = e->pred_next)
710                     total += e->count;
711
712                   /* Seedgeh for the invalid edge, and set its count.  */
713                   for (e = bb->pred; e; e = e->pred_next)
714                     if (! EDGE_INFO (e)->count_valid && ! EDGE_INFO (e)->ignore)
715                       break;
716
717                   /* Calculate count for remaining edge by conservation.  */
718                   total = bb->count - total + e->count;
719
720                   if (! e)
721                     abort ();
722                   EDGE_INFO (e)->count_valid = 1;
723                   e->count = total;
724                   bi->pred_count--;
725
726                   BB_INFO (e->src)->succ_count--;
727                   changes = 1;
728                 }
729             }
730         }
731     }
732   if (rtl_dump_file)
733     dump_flow_info (rtl_dump_file);
734
735   total_num_passes += passes;
736   if (rtl_dump_file)
737     fprintf (rtl_dump_file, "Graph solving took %d passes.\n\n", passes);
738
739   /* If the graph has been correctly solved, every block will have a
740      succ and pred count of zero.  */
741   FOR_EACH_BB (bb)
742     {
743       if (BB_INFO (bb)->succ_count || BB_INFO (bb)->pred_count)
744         abort ();
745     }
746
747   /* For every edge, calculate its branch probability and add a reg_note
748      to the branch insn to indicate this.  */
749
750   for (i = 0; i < 20; i++)
751     hist_br_prob[i] = 0;
752   num_never_executed = 0;
753   num_branches = 0;
754
755   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
756     {
757       edge e;
758       gcov_type total;
759       rtx note;
760
761       total = bb->count;
762       if (total)
763         {
764           for (e = bb->succ; e; e = e->succ_next)
765             {
766                 e->probability = (e->count * REG_BR_PROB_BASE + total / 2) / total;
767                 if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
768                   {
769                     error ("corrupted profile info: prob for %d-%d thought to be %d",
770                            e->src->index, e->dest->index, e->probability);
771                     e->probability = REG_BR_PROB_BASE / 2;
772                   }
773             }
774           if (bb->index >= 0
775               && any_condjump_p (bb->end)
776               && bb->succ->succ_next)
777             {
778               int prob;
779               edge e;
780               int index;
781
782               /* Find the branch edge.  It is possible that we do have fake
783                  edges here.  */
784               for (e = bb->succ; e->flags & (EDGE_FAKE | EDGE_FALLTHRU);
785                    e = e->succ_next)
786                 continue; /* Loop body has been intentionally left blank.  */
787
788               prob = e->probability;
789               index = prob * 20 / REG_BR_PROB_BASE;
790
791               if (index == 20)
792                 index = 19;
793               hist_br_prob[index]++;
794
795               note = find_reg_note (bb->end, REG_BR_PROB, 0);
796               /* There may be already note put by some other pass, such
797                  as builtin_expect expander.  */
798               if (note)
799                 XEXP (note, 0) = GEN_INT (prob);
800               else
801                 REG_NOTES (bb->end)
802                   = gen_rtx_EXPR_LIST (REG_BR_PROB, GEN_INT (prob),
803                                        REG_NOTES (bb->end));
804               num_branches++;
805             }
806         }
807       /* Otherwise distribute the probabilities evenly so we get sane
808          sum.  Use simple heuristics that if there are normal edges,
809          give all abnormals frequency of 0, otherwise distribute the
810          frequency over abnormals (this is the case of noreturn
811          calls).  */
812       else
813         {
814           for (e = bb->succ; e; e = e->succ_next)
815             if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
816               total ++;
817           if (total)
818             {
819               for (e = bb->succ; e; e = e->succ_next)
820                 if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
821                   e->probability = REG_BR_PROB_BASE / total;
822                 else
823                   e->probability = 0;
824             }
825           else
826             {
827               for (e = bb->succ; e; e = e->succ_next)
828                 total ++;
829               for (e = bb->succ; e; e = e->succ_next)
830                 e->probability = REG_BR_PROB_BASE / total;
831             }
832           if (bb->index >= 0
833               && any_condjump_p (bb->end)
834               && bb->succ->succ_next)
835             num_branches++, num_never_executed;
836         }
837     }
838
839   if (rtl_dump_file)
840     {
841       fprintf (rtl_dump_file, "%d branches\n", num_branches);
842       fprintf (rtl_dump_file, "%d branches never executed\n",
843                num_never_executed);
844       if (num_branches)
845         for (i = 0; i < 10; i++)
846           fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
847                    (hist_br_prob[i] + hist_br_prob[19-i]) * 100 / num_branches,
848                    5 * i, 5 * i + 5);
849
850       total_num_branches += num_branches;
851       total_num_never_executed += num_never_executed;
852       for (i = 0; i < 20; i++)
853         total_hist_br_prob[i] += hist_br_prob[i];
854
855       fputc ('\n', rtl_dump_file);
856       fputc ('\n', rtl_dump_file);
857     }
858
859   free_aux_for_blocks ();
860   if (exec_counts)
861     free (exec_counts);
862   find_counters_section (GCOV_TAG_ARC_COUNTS)->present = 1;
863 }
864
865 /* Compute checksum for the current function.  We generate a CRC32.  */
866
867 static unsigned
868 compute_checksum ()
869 {
870   unsigned chksum = 0;
871   basic_block bb;
872   
873   FOR_EACH_BB (bb)
874     {
875       edge e = NULL;
876       
877       do
878         {
879           unsigned value = BB_TO_GCOV_INDEX (e ? e->dest : bb);
880           unsigned ix;
881
882           /* No need to use all bits in value identically, nearly all
883              functions have less than 256 blocks.  */
884           value ^= value << 16;
885           value ^= value << 8;
886           
887           for (ix = 8; ix--; value <<= 1)
888             {
889               unsigned feedback;
890
891               feedback = (value ^ chksum) & 0x80000000 ? 0x04c11db7 : 0;
892               chksum <<= 1;
893               chksum ^= feedback;
894             }
895           
896           e = e ? e->succ_next : bb->succ;
897         }
898       while (e);
899     }
900
901   return chksum;
902 }
903
904 /* Instrument and/or analyze program behavior based on program flow graph.
905    In either case, this function builds a flow graph for the function being
906    compiled.  The flow graph is stored in BB_GRAPH.
907
908    When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
909    the flow graph that are needed to reconstruct the dynamic behavior of the
910    flow graph.
911
912    When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
913    information from a data file containing edge count information from previous
914    executions of the function being compiled.  In this case, the flow graph is
915    annotated with actual execution counts, which are later propagated into the
916    rtl for optimization purposes.
917
918    Main entry point of this file.  */
919
920 void
921 branch_prob ()
922 {
923   basic_block bb;
924   unsigned i;
925   unsigned num_edges, ignored_edges;
926   struct edge_list *el;
927   const char *name = IDENTIFIER_POINTER
928                       (DECL_ASSEMBLER_NAME (current_function_decl));
929
930   profile_info.current_function_cfg_checksum = compute_checksum ();
931   for (i = 0; i < profile_info.n_sections; i++)
932     {
933       profile_info.section_info[i].n_counters_now = 0;
934       profile_info.section_info[i].present = 0;
935     }
936
937   if (rtl_dump_file)
938     fprintf (rtl_dump_file, "CFG checksum is %u\n",
939         profile_info.current_function_cfg_checksum);
940
941   total_num_times_called++;
942
943   flow_call_edges_add (NULL);
944   add_noreturn_fake_exit_edges ();
945
946   /* We can't handle cyclic regions constructed using abnormal edges.
947      To avoid these we replace every source of abnormal edge by a fake
948      edge from entry node and every destination by fake edge to exit.
949      This keeps graph acyclic and our calculation exact for all normal
950      edges except for exit and entrance ones.
951
952      We also add fake exit edges for each call and asm statement in the
953      basic, since it may not return.  */
954
955   FOR_EACH_BB (bb)
956     {
957       int need_exit_edge = 0, need_entry_edge = 0;
958       int have_exit_edge = 0, have_entry_edge = 0;
959       rtx insn;
960       edge e;
961
962       /* Add fake edges from entry block to the call insns that may return
963          twice.  The CFG is not quite correct then, as call insn plays more
964          role of CODE_LABEL, but for our purposes, everything should be OK,
965          as we never insert code to the beginning of basic block.  */
966       for (insn = bb->head; insn != NEXT_INSN (bb->end);
967            insn = NEXT_INSN (insn))
968         {
969           if (GET_CODE (insn) == CALL_INSN
970               && find_reg_note (insn, REG_SETJMP, NULL))
971             {
972               if (GET_CODE (bb->head) == CODE_LABEL
973                   || insn != NEXT_INSN (bb->head))
974                 {
975                   e = split_block (bb, PREV_INSN (insn));
976                   make_edge (ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE);
977                   break;
978                 }
979               else
980                 {
981                   /* We should not get abort here, as call to setjmp should not
982                      be the very first instruction of function.  */
983                   if (bb == ENTRY_BLOCK_PTR)
984                     abort ();
985                   make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
986                 }
987             }
988         }
989
990       for (e = bb->succ; e; e = e->succ_next)
991         {
992           if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
993                && e->dest != EXIT_BLOCK_PTR)
994             need_exit_edge = 1;
995           if (e->dest == EXIT_BLOCK_PTR)
996             have_exit_edge = 1;
997         }
998       for (e = bb->pred; e; e = e->pred_next)
999         {
1000           if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
1001                && e->src != ENTRY_BLOCK_PTR)
1002             need_entry_edge = 1;
1003           if (e->src == ENTRY_BLOCK_PTR)
1004             have_entry_edge = 1;
1005         }
1006
1007       if (need_exit_edge && !have_exit_edge)
1008         {
1009           if (rtl_dump_file)
1010             fprintf (rtl_dump_file, "Adding fake exit edge to bb %i\n",
1011                      bb->index);
1012           make_edge (bb, EXIT_BLOCK_PTR, EDGE_FAKE);
1013         }
1014       if (need_entry_edge && !have_entry_edge)
1015         {
1016           if (rtl_dump_file)
1017             fprintf (rtl_dump_file, "Adding fake entry edge to bb %i\n",
1018                      bb->index);
1019           make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
1020         }
1021     }
1022
1023   el = create_edge_list ();
1024   num_edges = NUM_EDGES (el);
1025   alloc_aux_for_edges (sizeof (struct edge_info));
1026
1027   /* The basic blocks are expected to be numbered sequentially.  */
1028   compact_blocks ();
1029
1030   ignored_edges = 0;
1031   for (i = 0 ; i < num_edges ; i++)
1032     {
1033       edge e = INDEX_EDGE (el, i);
1034       e->count = 0;
1035
1036       /* Mark edges we've replaced by fake edges above as ignored.  */
1037       if ((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL))
1038           && e->src != ENTRY_BLOCK_PTR && e->dest != EXIT_BLOCK_PTR)
1039         {
1040           EDGE_INFO (e)->ignore = 1;
1041           ignored_edges++;
1042         }
1043     }
1044
1045 #ifdef ENABLE_CHECKING
1046   verify_flow_info ();
1047 #endif
1048
1049   /* Create spanning tree from basic block graph, mark each edge that is
1050      on the spanning tree.  We insert as many abnormal and critical edges
1051      as possible to minimize number of edge splits necessary.  */
1052
1053   find_spanning_tree (el);
1054
1055   /* Fake edges that are not on the tree will not be instrumented, so
1056      mark them ignored.  */
1057   for (i = 0; i < num_edges; i++)
1058     {
1059       edge e = INDEX_EDGE (el, i);
1060       struct edge_info *inf = EDGE_INFO (e);
1061       if ((e->flags & EDGE_FAKE) && !inf->ignore && !inf->on_tree)
1062         {
1063           inf->ignore = 1;
1064           ignored_edges++;
1065         }
1066     }
1067
1068   total_num_blocks += n_basic_blocks + 2;
1069   if (rtl_dump_file)
1070     fprintf (rtl_dump_file, "%d basic blocks\n", n_basic_blocks);
1071
1072   total_num_edges += num_edges;
1073   if (rtl_dump_file)
1074     fprintf (rtl_dump_file, "%d edges\n", num_edges);
1075
1076   total_num_edges_ignored += ignored_edges;
1077   if (rtl_dump_file)
1078     fprintf (rtl_dump_file, "%d ignored edges\n", ignored_edges);
1079
1080   /* Create a .bbg file from which gcov can reconstruct the basic block
1081      graph.  First output the number of basic blocks, and then for every
1082      edge output the source and target basic block numbers.
1083      NOTE: The format of this file must be compatible with gcov.  */
1084
1085   if (flag_test_coverage && bbg_file)
1086     {
1087       long offset;
1088       
1089       /* Announce function */
1090       if (gcov_write_unsigned (bbg_file, GCOV_TAG_FUNCTION)
1091           || !(offset = gcov_reserve_length (bbg_file))
1092           || gcov_write_string (bbg_file, name,
1093                              strlen (name))
1094           || gcov_write_unsigned (bbg_file,
1095                             profile_info.current_function_cfg_checksum)
1096           || gcov_write_length (bbg_file, offset))
1097         goto bbg_error;
1098
1099       /* Basic block flags */
1100       if (gcov_write_unsigned (bbg_file, GCOV_TAG_BLOCKS)
1101           || !(offset = gcov_reserve_length (bbg_file)))
1102         goto bbg_error;
1103       for (i = 0; i != (unsigned) (n_basic_blocks + 2); i++)
1104         if (gcov_write_unsigned (bbg_file, 0))
1105           goto bbg_error;
1106       if (gcov_write_length (bbg_file, offset))
1107         goto bbg_error;
1108       
1109       /* Arcs */
1110       FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
1111         {
1112           edge e;
1113
1114           if (gcov_write_unsigned (bbg_file, GCOV_TAG_ARCS)
1115               || !(offset = gcov_reserve_length (bbg_file))
1116               || gcov_write_unsigned (bbg_file, BB_TO_GCOV_INDEX (bb)))
1117             goto bbg_error;
1118
1119           for (e = bb->succ; e; e = e->succ_next)
1120             {
1121               struct edge_info *i = EDGE_INFO (e);
1122               if (!i->ignore)
1123                 {
1124                   unsigned flag_bits = 0;
1125                   
1126                   if (i->on_tree)
1127                     flag_bits |= GCOV_ARC_ON_TREE;
1128                   if (e->flags & EDGE_FAKE)
1129                     flag_bits |= GCOV_ARC_FAKE;
1130                   if (e->flags & EDGE_FALLTHRU)
1131                     flag_bits |= GCOV_ARC_FALLTHROUGH;
1132
1133                   if (gcov_write_unsigned (bbg_file,
1134                                            BB_TO_GCOV_INDEX (e->dest))
1135                       || gcov_write_unsigned (bbg_file, flag_bits))
1136                     goto bbg_error;
1137                 }
1138             }
1139
1140           if (gcov_write_length (bbg_file, offset))
1141             goto bbg_error;
1142         }
1143
1144       /* Output line number information about each basic block for
1145          GCOV utility.  */
1146       {
1147         char const *prev_file_name = NULL;
1148         
1149         FOR_EACH_BB (bb)
1150           {
1151             rtx insn = bb->head;
1152             int ignore_next_note = 0;
1153             
1154             offset = 0;
1155             
1156             /* We are looking for line number notes.  Search backward
1157                before basic block to find correct ones.  */
1158             insn = prev_nonnote_insn (insn);
1159             if (!insn)
1160               insn = get_insns ();
1161             else
1162               insn = NEXT_INSN (insn);
1163
1164             while (insn != bb->end)
1165               {
1166                 if (GET_CODE (insn) == NOTE)
1167                   {
1168                      /* Must ignore the line number notes that immediately
1169                         follow the end of an inline function to avoid counting
1170                         it twice.  There is a note before the call, and one
1171                         after the call.  */
1172                     if (NOTE_LINE_NUMBER (insn)
1173                         == NOTE_INSN_REPEATED_LINE_NUMBER)
1174                       ignore_next_note = 1;
1175                     else if (NOTE_LINE_NUMBER (insn) <= 0)
1176                       /*NOP*/;
1177                     else if (ignore_next_note)
1178                       ignore_next_note = 0;
1179                     else
1180                       {
1181                         if (offset)
1182                           /*NOP*/;
1183                         else if (gcov_write_unsigned (bbg_file, GCOV_TAG_LINES)
1184                                  || !(offset = gcov_reserve_length (bbg_file))
1185                                  || gcov_write_unsigned (bbg_file,
1186                                                    BB_TO_GCOV_INDEX (bb)))
1187                           goto bbg_error;
1188                         /* If this is a new source file, then output
1189                            the file's name to the .bb file.  */
1190                         if (!prev_file_name
1191                             || strcmp (NOTE_SOURCE_FILE (insn),
1192                                        prev_file_name))
1193                           {
1194                             prev_file_name = NOTE_SOURCE_FILE (insn);
1195                             if (gcov_write_unsigned (bbg_file, 0)
1196                                 || gcov_write_string (bbg_file, prev_file_name,
1197                                                       strlen (prev_file_name)))
1198                               goto bbg_error;
1199                           }
1200                         if (gcov_write_unsigned (bbg_file, NOTE_LINE_NUMBER (insn)))
1201                           goto bbg_error;
1202                       }
1203                   }
1204                 insn = NEXT_INSN (insn);
1205               }
1206
1207             if (offset)
1208               {
1209                 if (gcov_write_unsigned (bbg_file, 0)
1210                     || gcov_write_string (bbg_file, NULL, 0)
1211                     || gcov_write_length (bbg_file, offset))
1212                   {
1213                   bbg_error:;
1214                     warning ("error writing `%s'", bbg_file_name);
1215                     fclose (bbg_file);
1216                     bbg_file = NULL;
1217                   }
1218               }
1219           }
1220       }
1221     }
1222
1223   if (flag_branch_probabilities)
1224     compute_branch_probabilities ();
1225
1226   /* For each edge not on the spanning tree, add counting code as rtl.  */
1227
1228   if (cfun->arc_profile && profile_arc_flag)
1229     {
1230       struct function_list *item;
1231       
1232       instrument_edges (el);
1233
1234       /* Commit changes done by instrumentation.  */
1235       commit_edge_insertions_watch_calls ();
1236       allocate_reg_info (max_reg_num (), FALSE, FALSE);
1237
1238       /* ??? Probably should re-use the existing struct function.  */
1239       item = xmalloc (sizeof (struct function_list));
1240       
1241       *functions_tail = item;
1242       functions_tail = &item->next;
1243       
1244       item->next = 0;
1245       item->name = xstrdup (name);
1246       item->cfg_checksum = profile_info.current_function_cfg_checksum;
1247       item->n_counter_sections = 0;
1248       for (i = 0; i < profile_info.n_sections; i++)
1249         if (profile_info.section_info[i].n_counters_now)
1250           {
1251             item->counter_sections[item->n_counter_sections].tag = 
1252                     profile_info.section_info[i].tag;
1253             item->counter_sections[item->n_counter_sections].n_counters =
1254                     profile_info.section_info[i].n_counters_now;
1255             item->n_counter_sections++;
1256           }
1257     }
1258
1259   remove_fake_edges ();
1260   free_aux_for_edges ();
1261   /* Re-merge split basic blocks and the mess introduced by
1262      insert_insn_on_edge.  */
1263   cleanup_cfg (profile_arc_flag ? CLEANUP_EXPENSIVE : 0);
1264   if (rtl_dump_file)
1265     dump_flow_info (rtl_dump_file);
1266
1267   free_edge_list (el);
1268 }
1269 \f
1270 /* Union find algorithm implementation for the basic blocks using
1271    aux fields.  */
1272
1273 static basic_block
1274 find_group (bb)
1275      basic_block bb;
1276 {
1277   basic_block group = bb, bb1;
1278
1279   while ((basic_block) group->aux != group)
1280     group = (basic_block) group->aux;
1281
1282   /* Compress path.  */
1283   while ((basic_block) bb->aux != group)
1284     {
1285       bb1 = (basic_block) bb->aux;
1286       bb->aux = (void *) group;
1287       bb = bb1;
1288     }
1289   return group;
1290 }
1291
1292 static void
1293 union_groups (bb1, bb2)
1294      basic_block bb1, bb2;
1295 {
1296   basic_block bb1g = find_group (bb1);
1297   basic_block bb2g = find_group (bb2);
1298
1299   /* ??? I don't have a place for the rank field.  OK.  Lets go w/o it,
1300      this code is unlikely going to be performance problem anyway.  */
1301   if (bb1g == bb2g)
1302     abort ();
1303
1304   bb1g->aux = bb2g;
1305 }
1306 \f
1307 /* This function searches all of the edges in the program flow graph, and puts
1308    as many bad edges as possible onto the spanning tree.  Bad edges include
1309    abnormals edges, which can't be instrumented at the moment.  Since it is
1310    possible for fake edges to form a cycle, we will have to develop some
1311    better way in the future.  Also put critical edges to the tree, since they
1312    are more expensive to instrument.  */
1313
1314 static void
1315 find_spanning_tree (el)
1316      struct edge_list *el;
1317 {
1318   int i;
1319   int num_edges = NUM_EDGES (el);
1320   basic_block bb;
1321
1322   /* We use aux field for standard union-find algorithm.  */
1323   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1324     bb->aux = bb;
1325
1326   /* Add fake edge exit to entry we can't instrument.  */
1327   union_groups (EXIT_BLOCK_PTR, ENTRY_BLOCK_PTR);
1328
1329   /* First add all abnormal edges to the tree unless they form a cycle. Also
1330      add all edges to EXIT_BLOCK_PTR to avoid inserting profiling code behind
1331      setting return value from function.  */
1332   for (i = 0; i < num_edges; i++)
1333     {
1334       edge e = INDEX_EDGE (el, i);
1335       if (((e->flags & (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_FAKE))
1336            || e->dest == EXIT_BLOCK_PTR
1337            )
1338           && !EDGE_INFO (e)->ignore
1339           && (find_group (e->src) != find_group (e->dest)))
1340         {
1341           if (rtl_dump_file)
1342             fprintf (rtl_dump_file, "Abnormal edge %d to %d put to tree\n",
1343                      e->src->index, e->dest->index);
1344           EDGE_INFO (e)->on_tree = 1;
1345           union_groups (e->src, e->dest);
1346         }
1347     }
1348
1349   /* Now insert all critical edges to the tree unless they form a cycle.  */
1350   for (i = 0; i < num_edges; i++)
1351     {
1352       edge e = INDEX_EDGE (el, i);
1353       if ((EDGE_CRITICAL_P (e))
1354           && !EDGE_INFO (e)->ignore
1355           && (find_group (e->src) != find_group (e->dest)))
1356         {
1357           if (rtl_dump_file)
1358             fprintf (rtl_dump_file, "Critical edge %d to %d put to tree\n",
1359                      e->src->index, e->dest->index);
1360           EDGE_INFO (e)->on_tree = 1;
1361           union_groups (e->src, e->dest);
1362         }
1363     }
1364
1365   /* And now the rest.  */
1366   for (i = 0; i < num_edges; i++)
1367     {
1368       edge e = INDEX_EDGE (el, i);
1369       if (find_group (e->src) != find_group (e->dest)
1370           && !EDGE_INFO (e)->ignore)
1371         {
1372           if (rtl_dump_file)
1373             fprintf (rtl_dump_file, "Normal edge %d to %d put to tree\n",
1374                      e->src->index, e->dest->index);
1375           EDGE_INFO (e)->on_tree = 1;
1376           union_groups (e->src, e->dest);
1377         }
1378     }
1379
1380   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
1381     bb->aux = NULL;
1382 }
1383 \f
1384 /* Perform file-level initialization for branch-prob processing.  */
1385
1386 void
1387 init_branch_prob (filename)
1388   const char *filename;
1389 {
1390   int len = strlen (filename);
1391   int i;
1392
1393   if (flag_test_coverage)
1394     {
1395       /* Open the bbg output file.  */
1396       bbg_file_name = (char *) xmalloc (len + strlen (GCOV_GRAPH_SUFFIX) + 1);
1397       strcpy (bbg_file_name, filename);
1398       strcat (bbg_file_name, GCOV_GRAPH_SUFFIX);
1399       bbg_file = fopen (bbg_file_name, "wb");
1400       if (!bbg_file)
1401         fatal_io_error ("cannot open %s", bbg_file_name);
1402
1403       if (gcov_write_unsigned (bbg_file, GCOV_GRAPH_MAGIC)
1404           || gcov_write_unsigned (bbg_file, GCOV_VERSION))
1405         {
1406           fclose (bbg_file);
1407           fatal_io_error ("cannot write `%s'", bbg_file_name);
1408         }
1409     }
1410
1411   da_file_name = (char *) xmalloc (len + strlen (GCOV_DATA_SUFFIX) + 1);
1412   strcpy (da_file_name, filename);
1413   strcat (da_file_name, GCOV_DATA_SUFFIX);
1414   
1415   if (flag_branch_probabilities)
1416     {
1417       da_file = fopen (da_file_name, "rb");
1418       if (!da_file)
1419         warning ("file %s not found, execution counts assumed to be zero",
1420                  da_file_name);
1421       if (counts_file_index && strcmp (da_file_name, counts_file_name))
1422         cleanup_counts_index (0);
1423       if (index_counts_file ())
1424         counts_file_name = xstrdup (da_file_name);
1425     }
1426
1427   if (profile_arc_flag)
1428     {
1429       /* Generate and save a copy of this so it can be shared.  */
1430       char buf[20];
1431       
1432       ASM_GENERATE_INTERNAL_LABEL (buf, "LPBX", 2);
1433       profiler_label = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
1434     }
1435   
1436   total_num_blocks = 0;
1437   total_num_edges = 0;
1438   total_num_edges_ignored = 0;
1439   total_num_edges_instrumented = 0;
1440   total_num_blocks_created = 0;
1441   total_num_passes = 0;
1442   total_num_times_called = 0;
1443   total_num_branches = 0;
1444   total_num_never_executed = 0;
1445   for (i = 0; i < 20; i++)
1446     total_hist_br_prob[i] = 0;
1447 }
1448
1449 /* Performs file-level cleanup after branch-prob processing
1450    is completed.  */
1451
1452 void
1453 end_branch_prob ()
1454 {
1455   if (flag_test_coverage)
1456     {
1457       if (bbg_file)
1458         {
1459 #if !SELF_COVERAGE
1460           /* If the compiler is instrumented, we should not remove the
1461              counts file, because we might be recompiling
1462              ourselves. The .da files are all removed during copying
1463              the stage1 files.  */
1464           unlink (da_file_name);
1465 #endif
1466           fclose (bbg_file);
1467         }
1468       else
1469         {
1470           unlink (bbg_file_name);
1471           unlink (da_file_name);
1472         }
1473     }
1474
1475   if (da_file)
1476     fclose (da_file);
1477
1478   if (rtl_dump_file)
1479     {
1480       fprintf (rtl_dump_file, "\n");
1481       fprintf (rtl_dump_file, "Total number of blocks: %d\n",
1482                total_num_blocks);
1483       fprintf (rtl_dump_file, "Total number of edges: %d\n", total_num_edges);
1484       fprintf (rtl_dump_file, "Total number of ignored edges: %d\n",
1485                total_num_edges_ignored);
1486       fprintf (rtl_dump_file, "Total number of instrumented edges: %d\n",
1487                total_num_edges_instrumented);
1488       fprintf (rtl_dump_file, "Total number of blocks created: %d\n",
1489                total_num_blocks_created);
1490       fprintf (rtl_dump_file, "Total number of graph solution passes: %d\n",
1491                total_num_passes);
1492       if (total_num_times_called != 0)
1493         fprintf (rtl_dump_file, "Average number of graph solution passes: %d\n",
1494                  (total_num_passes + (total_num_times_called  >> 1))
1495                  / total_num_times_called);
1496       fprintf (rtl_dump_file, "Total number of branches: %d\n",
1497                total_num_branches);
1498       fprintf (rtl_dump_file, "Total number of branches never executed: %d\n",
1499                total_num_never_executed);
1500       if (total_num_branches)
1501         {
1502           int i;
1503
1504           for (i = 0; i < 10; i++)
1505             fprintf (rtl_dump_file, "%d%% branches in range %d-%d%%\n",
1506                      (total_hist_br_prob[i] + total_hist_br_prob[19-i]) * 100
1507                      / total_num_branches, 5*i, 5*i+5);
1508         }
1509     }
1510 }
1511
1512 /* Find (and create if not present) a section with TAG.  */
1513 struct section_info *
1514 find_counters_section (tag)
1515      unsigned tag;
1516 {
1517   unsigned i;
1518
1519   for (i = 0; i < profile_info.n_sections; i++)
1520     if (profile_info.section_info[i].tag == tag)
1521       return profile_info.section_info + i;
1522
1523   if (i == MAX_COUNTER_SECTIONS)
1524     abort ();
1525
1526   profile_info.section_info[i].tag = tag;
1527   profile_info.section_info[i].present = 0;
1528   profile_info.section_info[i].n_counters = 0;
1529   profile_info.section_info[i].n_counters_now = 0;
1530   profile_info.n_sections++;
1531
1532   return profile_info.section_info + i;
1533 }
1534
1535 /* Set FIELDS as purpose to VALUE.  */
1536 static void
1537 set_purpose (value, fields)
1538      tree value;
1539      tree fields;
1540 {
1541   tree act_field, act_value;
1542   
1543   for (act_field = fields, act_value = value;
1544        act_field;
1545        act_field = TREE_CHAIN (act_field), act_value = TREE_CHAIN (act_value))
1546     TREE_PURPOSE (act_value) = act_field;
1547 }
1548
1549 /* Returns label for base of counters inside TAG section.  */
1550 static rtx
1551 label_for_tag (tag)
1552      unsigned tag;
1553 {
1554   switch (tag)
1555     {
1556     case GCOV_TAG_ARC_COUNTS:
1557       return profiler_label;
1558     default:
1559       abort ();
1560     }
1561 }
1562
1563 /* Creates fields of struct counter_section (in gcov-io.h).  */
1564 static tree
1565 build_counter_section_fields ()
1566 {
1567   tree field, fields;
1568
1569   /* tag */
1570   fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1571
1572   /* n_counters */
1573   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1574   TREE_CHAIN (field) = fields;
1575   fields = field;
1576
1577   return fields;
1578 }
1579
1580 /* Creates value of struct counter_section (in gcov-io.h).  */
1581 static tree
1582 build_counter_section_value (tag, n_counters)
1583      unsigned tag;
1584      unsigned n_counters;
1585 {
1586   tree value = NULL_TREE;
1587
1588   /* tag */
1589   value = tree_cons (NULL_TREE,
1590                      convert (unsigned_type_node,
1591                               build_int_2 (tag, 0)),
1592                      value);
1593   
1594   /* n_counters */
1595   value = tree_cons (NULL_TREE,
1596                      convert (unsigned_type_node,
1597                               build_int_2 (n_counters, 0)),
1598                      value);
1599
1600   return value;
1601 }
1602
1603 /* Creates fields of struct counter_section_data (in gcov-io.h).  */
1604 static tree
1605 build_counter_section_data_fields ()
1606 {
1607   tree field, fields, gcov_type, gcov_ptr_type;
1608
1609   gcov_type = make_signed_type (GCOV_TYPE_SIZE);
1610   gcov_ptr_type =
1611           build_pointer_type (build_qualified_type (gcov_type,
1612                                                     TYPE_QUAL_CONST));
1613
1614   /* tag */
1615   fields = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1616
1617   /* n_counters */
1618   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1619   TREE_CHAIN (field) = fields;
1620   fields = field;
1621
1622   /* counters */
1623   field = build_decl (FIELD_DECL, NULL_TREE, gcov_ptr_type);
1624   TREE_CHAIN (field) = fields;
1625   fields = field;
1626
1627   return fields;
1628 }
1629
1630 /* Creates value of struct counter_section_data (in gcov-io.h).  */
1631 static tree
1632 build_counter_section_data_value (tag, n_counters)
1633      unsigned tag;
1634      unsigned n_counters;
1635 {
1636   tree value = NULL_TREE, counts_table, gcov_type, gcov_ptr_type;
1637
1638   gcov_type = make_signed_type (GCOV_TYPE_SIZE);
1639   gcov_ptr_type
1640     = build_pointer_type (build_qualified_type
1641                           (gcov_type, TYPE_QUAL_CONST));
1642
1643   /* tag */
1644   value = tree_cons (NULL_TREE,
1645                      convert (unsigned_type_node,
1646                               build_int_2 (tag, 0)),
1647                      value);
1648   
1649   /* n_counters */
1650   value = tree_cons (NULL_TREE,
1651                      convert (unsigned_type_node,
1652                               build_int_2 (n_counters, 0)),
1653                      value);
1654
1655   /* counters */
1656   if (n_counters)
1657     {
1658       tree gcov_type_array_type =
1659               build_array_type (gcov_type,
1660                                 build_index_type (build_int_2 (n_counters - 1,
1661                                                                0)));
1662       counts_table =
1663               build (VAR_DECL, gcov_type_array_type, NULL_TREE, NULL_TREE);
1664       TREE_STATIC (counts_table) = 1;
1665       DECL_NAME (counts_table) = get_identifier (XSTR (label_for_tag (tag), 0));
1666       assemble_variable (counts_table, 0, 0, 0);
1667       counts_table = build1 (ADDR_EXPR, gcov_ptr_type, counts_table);
1668     }
1669   else
1670     counts_table = null_pointer_node;
1671
1672   value = tree_cons (NULL_TREE, counts_table, value);
1673
1674   return value;
1675 }
1676
1677 /* Creates fields for struct function_info type (in gcov-io.h).  */
1678 static tree
1679 build_function_info_fields ()
1680 {
1681   tree field, fields, counter_section_fields, counter_section_type;
1682   tree counter_sections_ptr_type;
1683   tree string_type =
1684           build_pointer_type (build_qualified_type (char_type_node,
1685                                                     TYPE_QUAL_CONST));
1686   /* name */
1687   fields = build_decl (FIELD_DECL, NULL_TREE, string_type);
1688
1689   /* checksum */
1690   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1691   TREE_CHAIN (field) = fields;
1692   fields = field;
1693
1694   /* n_counter_sections */
1695   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1696   TREE_CHAIN (field) = fields;
1697   fields = field;
1698
1699   /* counter_sections */
1700   counter_section_fields = build_counter_section_fields ();
1701   counter_section_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1702   finish_builtin_struct (counter_section_type, "__counter_section",
1703                          counter_section_fields, NULL_TREE);
1704   counter_sections_ptr_type =
1705           build_pointer_type
1706                 (build_qualified_type (counter_section_type,
1707                                        TYPE_QUAL_CONST));
1708   field = build_decl (FIELD_DECL, NULL_TREE, counter_sections_ptr_type);
1709   TREE_CHAIN (field) = fields;
1710   fields = field;
1711
1712   return fields;
1713 }
1714
1715 /* Creates value for struct function_info (in gcov-io.h).  */
1716 static tree
1717 build_function_info_value (function)
1718      struct function_list *function;
1719 {
1720   tree value = NULL_TREE;
1721   size_t name_len = strlen (function->name);
1722   tree fname = build_string (name_len + 1, function->name);
1723   tree string_type =
1724           build_pointer_type (build_qualified_type (char_type_node,
1725                                                     TYPE_QUAL_CONST));
1726   tree counter_section_fields, counter_section_type, counter_sections_value;
1727   tree counter_sections_ptr_type, counter_sections_array_type;
1728   unsigned i;
1729
1730   /* name */
1731   TREE_TYPE (fname) =
1732           build_array_type (char_type_node,
1733                             build_index_type (build_int_2 (name_len, 0)));
1734   value = tree_cons (NULL_TREE,
1735                      build1 (ADDR_EXPR,
1736                              string_type,
1737                              fname),
1738                      value);
1739
1740   /* checksum */
1741   value = tree_cons (NULL_TREE,
1742                      convert (unsigned_type_node,
1743                               build_int_2 (function->cfg_checksum, 0)),
1744                      value);
1745
1746   /* n_counter_sections */
1747
1748   value = tree_cons (NULL_TREE,
1749                      convert (unsigned_type_node,
1750                               build_int_2 (function->n_counter_sections, 0)),
1751                     value);
1752
1753   /* counter_sections */
1754   counter_section_fields = build_counter_section_fields ();
1755   counter_section_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1756   counter_sections_ptr_type =
1757           build_pointer_type
1758                 (build_qualified_type (counter_section_type,
1759                                        TYPE_QUAL_CONST));
1760   counter_sections_array_type =
1761           build_array_type (counter_section_type,
1762                             build_index_type (
1763                                 build_int_2 (function->n_counter_sections - 1,
1764                                              0)));
1765
1766   counter_sections_value = NULL_TREE;
1767   for (i = 0; i < function->n_counter_sections; i++)
1768     {
1769       tree counter_section_value =
1770               build_counter_section_value (function->counter_sections[i].tag,
1771                                            function->counter_sections[i].n_counters);
1772       set_purpose (counter_section_value, counter_section_fields);
1773       counter_sections_value = tree_cons (NULL_TREE,
1774                                           build (CONSTRUCTOR,
1775                                                  counter_section_type,
1776                                                  NULL_TREE,
1777                                                  nreverse (counter_section_value)),
1778                                           counter_sections_value);
1779     }
1780   finish_builtin_struct (counter_section_type, "__counter_section",
1781                          counter_section_fields, NULL_TREE);
1782
1783   if (function->n_counter_sections)
1784     {
1785       counter_sections_value = 
1786               build (CONSTRUCTOR,
1787                      counter_sections_array_type,
1788                      NULL_TREE,
1789                      nreverse (counter_sections_value)),
1790       counter_sections_value = build1 (ADDR_EXPR,
1791                                        counter_sections_ptr_type,
1792                                        counter_sections_value);
1793     }
1794   else
1795     counter_sections_value = null_pointer_node;
1796
1797   value = tree_cons (NULL_TREE, counter_sections_value, value);
1798
1799   return value;
1800 }
1801
1802 /* Creates fields of struct gcov_info type (in gcov-io.h).  */
1803 static tree
1804 build_gcov_info_fields (gcov_info_type)
1805      tree gcov_info_type;
1806 {
1807   tree field, fields;
1808   char *filename;
1809   int filename_len;
1810   tree string_type =
1811           build_pointer_type (build_qualified_type (char_type_node,
1812                                                     TYPE_QUAL_CONST));
1813   tree function_info_fields, function_info_type, function_info_ptr_type;
1814   tree counter_section_data_fields, counter_section_data_type;
1815   tree counter_section_data_ptr_type;
1816
1817   /* Version ident */
1818   fields = build_decl (FIELD_DECL, NULL_TREE, long_unsigned_type_node);
1819
1820   /* next -- NULL */
1821   field = build_decl (FIELD_DECL, NULL_TREE,
1822                       build_pointer_type (build_qualified_type (gcov_info_type,
1823                                                                 TYPE_QUAL_CONST)));
1824   TREE_CHAIN (field) = fields;
1825   fields = field;
1826   
1827   /* Filename */
1828   filename = getpwd ();
1829   filename = (filename && da_file_name[0] != '/'
1830               ? concat (filename, "/", da_file_name, NULL)
1831               : da_file_name);
1832   filename_len = strlen (filename);
1833   if (filename != da_file_name)
1834     free (filename);
1835
1836   field = build_decl (FIELD_DECL, NULL_TREE, string_type);
1837   TREE_CHAIN (field) = fields;
1838   fields = field;
1839   
1840   /* Workspace */
1841   field = build_decl (FIELD_DECL, NULL_TREE, long_integer_type_node);
1842   TREE_CHAIN (field) = fields;
1843   fields = field;
1844
1845   /* number of functions */
1846   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1847   TREE_CHAIN (field) = fields;
1848   fields = field;
1849       
1850   /* function_info table */
1851   function_info_fields = build_function_info_fields ();
1852   function_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1853   finish_builtin_struct (function_info_type, "__function_info",
1854                          function_info_fields, NULL_TREE);
1855   function_info_ptr_type =
1856           build_pointer_type
1857                 (build_qualified_type (function_info_type,
1858                                        TYPE_QUAL_CONST));
1859   field = build_decl (FIELD_DECL, NULL_TREE, function_info_ptr_type);
1860   TREE_CHAIN (field) = fields;
1861   fields = field;
1862     
1863   /* n_counter_sections  */
1864   field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node);
1865   TREE_CHAIN (field) = fields;
1866   fields = field;
1867   
1868   /* counter sections */
1869   counter_section_data_fields = build_counter_section_data_fields ();
1870   counter_section_data_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1871   finish_builtin_struct (counter_section_data_type, "__counter_section_data",
1872                          counter_section_data_fields, NULL_TREE);
1873   counter_section_data_ptr_type =
1874           build_pointer_type
1875                 (build_qualified_type (counter_section_data_type,
1876                                        TYPE_QUAL_CONST));
1877   field = build_decl (FIELD_DECL, NULL_TREE, counter_section_data_ptr_type);
1878   TREE_CHAIN (field) = fields;
1879   fields = field;
1880
1881   return fields;
1882 }
1883
1884 /* Creates struct gcov_info value (in gcov-io.h).  */
1885 static tree
1886 build_gcov_info_value ()
1887 {
1888   tree value = NULL_TREE;
1889   tree filename_string;
1890   char *filename;
1891   int filename_len;
1892   unsigned n_functions, i;
1893   struct function_list *item;
1894   tree string_type =
1895           build_pointer_type (build_qualified_type (char_type_node,
1896                                                     TYPE_QUAL_CONST));
1897   tree function_info_fields, function_info_type, function_info_ptr_type;
1898   tree functions;
1899   tree counter_section_data_fields, counter_section_data_type;
1900   tree counter_section_data_ptr_type, counter_sections;
1901
1902   /* Version ident */
1903   value = tree_cons (NULL_TREE,
1904                      convert (long_unsigned_type_node,
1905                               build_int_2 (GCOV_VERSION, 0)),
1906                      value);
1907
1908   /* next -- NULL */
1909   value = tree_cons (NULL_TREE, null_pointer_node, value);
1910   
1911   /* Filename */
1912   filename = getpwd ();
1913   filename = (filename && da_file_name[0] != '/'
1914               ? concat (filename, "/", da_file_name, NULL)
1915               : da_file_name);
1916   filename_len = strlen (filename);
1917   filename_string = build_string (filename_len + 1, filename);
1918   if (filename != da_file_name)
1919     free (filename);
1920   TREE_TYPE (filename_string) =
1921           build_array_type (char_type_node,
1922                             build_index_type (build_int_2 (filename_len, 0)));
1923   value = tree_cons (NULL_TREE,
1924                      build1 (ADDR_EXPR,
1925                              string_type,
1926                              filename_string),
1927                      value);
1928   
1929   /* Workspace */
1930   value = tree_cons (NULL_TREE,
1931                      convert (long_integer_type_node, integer_zero_node),
1932                      value);
1933       
1934   /* number of functions */
1935   n_functions = 0;
1936   for (item = functions_head; item != 0; item = item->next, n_functions++)
1937     continue;
1938   value = tree_cons (NULL_TREE,
1939                      convert (unsigned_type_node,
1940                               build_int_2 (n_functions, 0)),
1941                      value);
1942
1943   /* function_info table */
1944   function_info_fields = build_function_info_fields ();
1945   function_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1946   function_info_ptr_type =
1947           build_pointer_type (
1948                 build_qualified_type (function_info_type,
1949                                       TYPE_QUAL_CONST));
1950   functions = NULL_TREE;
1951   for (item = functions_head; item != 0; item = item->next)
1952     {
1953       tree function_info_value = build_function_info_value (item);
1954       set_purpose (function_info_value, function_info_fields);
1955       functions = tree_cons (NULL_TREE,
1956                              build (CONSTRUCTOR,
1957                                     function_info_type,
1958                                     NULL_TREE,
1959                                     nreverse (function_info_value)),
1960                              functions);
1961     }
1962   finish_builtin_struct (function_info_type, "__function_info",
1963                          function_info_fields, NULL_TREE);
1964
1965   /* Create constructor for array.  */
1966   if (n_functions)
1967     {
1968       tree array_type;
1969
1970       array_type = build_array_type (
1971                         function_info_type,
1972                         build_index_type (build_int_2 (n_functions - 1, 0)));
1973       functions = build (CONSTRUCTOR,
1974                          array_type,
1975                          NULL_TREE,
1976                          nreverse (functions));
1977       functions = build1 (ADDR_EXPR,
1978                           function_info_ptr_type,
1979                           functions);
1980     }
1981   else
1982     functions = null_pointer_node;
1983
1984   value = tree_cons (NULL_TREE, functions, value);
1985
1986   /* n_counter_sections  */
1987   value = tree_cons (NULL_TREE,
1988                      convert (unsigned_type_node,
1989                               build_int_2 (profile_info.n_sections, 0)),
1990                      value);
1991   
1992   /* counter sections */
1993   counter_section_data_fields = build_counter_section_data_fields ();
1994   counter_section_data_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
1995   counter_sections = NULL_TREE;
1996   for (i = 0; i < profile_info.n_sections; i++)
1997     {
1998       tree counter_sections_value =
1999               build_counter_section_data_value (
2000                 profile_info.section_info[i].tag,
2001                 profile_info.section_info[i].n_counters);
2002       set_purpose (counter_sections_value, counter_section_data_fields);
2003       counter_sections = tree_cons (NULL_TREE,
2004                                     build (CONSTRUCTOR,
2005                                            counter_section_data_type,
2006                                            NULL_TREE,
2007                                            nreverse (counter_sections_value)),
2008                                     counter_sections);
2009     }
2010   finish_builtin_struct (counter_section_data_type, "__counter_section_data",
2011                          counter_section_data_fields, NULL_TREE);
2012   counter_section_data_ptr_type =
2013           build_pointer_type
2014                 (build_qualified_type (counter_section_data_type,
2015                                        TYPE_QUAL_CONST));
2016
2017   if (profile_info.n_sections)
2018     {
2019       counter_sections =
2020               build (CONSTRUCTOR,
2021                      build_array_type (
2022                                        counter_section_data_type,
2023                                        build_index_type (build_int_2 (profile_info.n_sections - 1, 0))),
2024                      NULL_TREE,
2025                      nreverse (counter_sections));
2026       counter_sections = build1 (ADDR_EXPR,
2027                                  counter_section_data_ptr_type,
2028                                  counter_sections);
2029     }
2030   else
2031     counter_sections = null_pointer_node;
2032   value = tree_cons (NULL_TREE, counter_sections, value);
2033
2034   return value;
2035 }
2036
2037 /* Write out the structure which libgcc uses to locate all the arc
2038    counters.  The structures used here must match those defined in
2039    gcov-io.h.  Write out the constructor to call __gcov_init.  */
2040
2041 void
2042 create_profiler ()
2043 {
2044   tree gcov_info_fields, gcov_info_type, gcov_info_value, gcov_info;
2045   char name[20];
2046   char *ctor_name;
2047   tree ctor;
2048   rtx gcov_info_address;
2049   int save_flag_inline_functions = flag_inline_functions;
2050   unsigned i;
2051
2052   for (i = 0; i < profile_info.n_sections; i++)
2053     if (profile_info.section_info[i].n_counters_now)
2054       break;
2055   if (i == profile_info.n_sections)
2056     return;
2057   
2058   gcov_info_type = (*lang_hooks.types.make_type) (RECORD_TYPE);
2059   gcov_info_fields = build_gcov_info_fields (gcov_info_type);
2060   gcov_info_value = build_gcov_info_value ();
2061   set_purpose (gcov_info_value, gcov_info_fields);
2062   finish_builtin_struct (gcov_info_type, "__gcov_info",
2063                          gcov_info_fields, NULL_TREE);
2064
2065   gcov_info = build (VAR_DECL, gcov_info_type, NULL_TREE, NULL_TREE);
2066   DECL_INITIAL (gcov_info) =
2067           build (CONSTRUCTOR, gcov_info_type, NULL_TREE,
2068                  nreverse (gcov_info_value));
2069
2070   TREE_STATIC (gcov_info) = 1;
2071   ASM_GENERATE_INTERNAL_LABEL (name, "LPBX", 0);
2072   DECL_NAME (gcov_info) = get_identifier (name);
2073   
2074   /* Build structure.  */
2075   assemble_variable (gcov_info, 0, 0, 0);
2076
2077   /* Build the constructor function to invoke __gcov_init.  */
2078   ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
2079                       "_GCOV", NULL);
2080   ctor = build_decl (FUNCTION_DECL, get_identifier (ctor_name),
2081                      build_function_type (void_type_node, NULL_TREE));
2082   free (ctor_name);
2083   DECL_EXTERNAL (ctor) = 0;
2084
2085   /* It can be a static function as long as collect2 does not have
2086      to scan the object file to find its ctor/dtor routine.  */
2087   TREE_PUBLIC (ctor) = ! targetm.have_ctors_dtors;
2088   TREE_USED (ctor) = 1;
2089   DECL_RESULT (ctor) = build_decl (RESULT_DECL, NULL_TREE, void_type_node);
2090
2091   ctor = (*lang_hooks.decls.pushdecl) (ctor);
2092   rest_of_decl_compilation (ctor, 0, 1, 0);
2093   announce_function (ctor);
2094   current_function_decl = ctor;
2095   DECL_INITIAL (ctor) = error_mark_node;
2096   make_decl_rtl (ctor, NULL);
2097   init_function_start (ctor, input_filename, lineno);
2098   (*lang_hooks.decls.pushlevel) (0);
2099   expand_function_start (ctor, 0);
2100   cfun->arc_profile = 0;
2101
2102   /* Actually generate the code to call __gcov_init.  */
2103   gcov_info_address = force_reg (Pmode,
2104                                  gen_rtx_SYMBOL_REF (
2105                                         Pmode,
2106                                         IDENTIFIER_POINTER (
2107                                                 DECL_NAME (gcov_info))));
2108   emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__gcov_init"),
2109                      LCT_NORMAL, VOIDmode, 1,
2110                      gcov_info_address, Pmode);
2111
2112   expand_function_end (input_filename, lineno, 0);
2113   (*lang_hooks.decls.poplevel) (1, 0, 1);
2114
2115   /* Since ctor isn't in the list of globals, it would never be emitted
2116      when it's considered to be 'safe' for inlining, so turn off
2117      flag_inline_functions.  */
2118   flag_inline_functions = 0;
2119
2120   rest_of_compilation (ctor);
2121
2122   /* Reset flag_inline_functions to its original value.  */
2123   flag_inline_functions = save_flag_inline_functions;
2124
2125   if (! quiet_flag)
2126     fflush (asm_out_file);
2127   current_function_decl = NULL_TREE;
2128
2129   if (targetm.have_ctors_dtors)
2130     (* targetm.asm_out.constructor) (XEXP (DECL_RTL (ctor), 0),
2131                                      DEFAULT_INIT_PRIORITY);
2132 }
2133 \f
2134 /* Output instructions as RTL to increment the edge execution count.  */
2135
2136 static rtx
2137 gen_edge_profiler (edgeno)
2138      int edgeno;
2139 {
2140   enum machine_mode mode = mode_for_size (GCOV_TYPE_SIZE, MODE_INT, 0);
2141   rtx mem_ref, tmp;
2142   rtx sequence;
2143
2144   start_sequence ();
2145
2146   tmp = force_reg (Pmode, profiler_label);
2147   tmp = plus_constant (tmp, GCOV_TYPE_SIZE / BITS_PER_UNIT * edgeno);
2148   mem_ref = validize_mem (gen_rtx_MEM (mode, tmp));
2149
2150   set_mem_alias_set (mem_ref, new_alias_set ());
2151
2152   tmp = expand_simple_binop (mode, PLUS, mem_ref, const1_rtx,
2153                              mem_ref, 0, OPTAB_WIDEN);
2154
2155   if (tmp != mem_ref)
2156     emit_move_insn (copy_rtx (mem_ref), tmp);
2157
2158   sequence = get_insns ();
2159   end_sequence ();
2160   return sequence;
2161 }
2162
2163 #include "gt-profile.h"