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.
8 This file is part of GCC.
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
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
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
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.
42 The auxiliary file generated is <dumpbase>.bbg. The format is
43 described in full in gcov-io.h. */
45 /* ??? Register allocation should use basic block execution counts to
46 give preference to the most commonly executed blocks. */
48 /* ??? Should calculate branch probabilities before instrumenting code, since
49 then we can use arc counts to help decide which arcs to instrument. */
53 #include "coretypes.h"
58 #include "insn-config.h"
65 #include "hard-reg-set.h"
66 #include "basic-block.h"
71 #include "langhooks.h"
74 /* Additional information about the edges we need. */
76 unsigned int count_valid
: 1;
78 /* Is on the spanning tree. */
79 unsigned int on_tree
: 1;
81 /* Pretend this edge does not exist (it is abnormal and we've
82 inserted a fake to compensate). */
83 unsigned int ignore
: 1;
87 unsigned int count_valid
: 1;
89 /* Number of successor and predecessor edges. */
96 struct function_list
*next
; /* next function */
97 const char *name
; /* function name */
98 unsigned cfg_checksum
; /* function checksum */
99 unsigned count_edges
; /* number of intrumented edges */
102 static struct function_list
*functions_head
= 0;
103 static struct function_list
**functions_tail
= &functions_head
;
105 #define EDGE_INFO(e) ((struct edge_info *) (e)->aux)
106 #define BB_INFO(b) ((struct bb_info *) (b)->aux)
108 /* Keep all basic block indexes nonnegative in the gcov output. Index 0
109 is used for entry block, last block exit block. */
110 #define BB_TO_GCOV_INDEX(bb) ((bb) == ENTRY_BLOCK_PTR ? 0 \
111 : ((bb) == EXIT_BLOCK_PTR \
112 ? last_basic_block + 1 : (bb)->index + 1))
114 /* Instantiate the profile info structure. */
116 struct profile_info profile_info
;
118 /* Name and file pointer of the output file for the basic block graph. */
120 static FILE *bbg_file
;
121 static char *bbg_file_name
;
123 /* Name and file pointer of the input file for the arc count data. */
125 static FILE *da_file
;
126 static char *da_file_name
;
128 /* The name of the count table. Used by the edge profiling code. */
129 static GTY(()) rtx profiler_label
;
131 /* Collect statistics on the performance of this pass for the entire source
134 static int total_num_blocks
;
135 static int total_num_edges
;
136 static int total_num_edges_ignored
;
137 static int total_num_edges_instrumented
;
138 static int total_num_blocks_created
;
139 static int total_num_passes
;
140 static int total_num_times_called
;
141 static int total_hist_br_prob
[20];
142 static int total_num_never_executed
;
143 static int total_num_branches
;
145 /* Forward declarations. */
146 static void find_spanning_tree
PARAMS ((struct edge_list
*));
147 static rtx gen_edge_profiler
PARAMS ((int));
148 static void instrument_edges
PARAMS ((struct edge_list
*));
149 static void compute_branch_probabilities
PARAMS ((void));
150 static hashval_t htab_counts_index_hash
PARAMS ((const void *));
151 static int htab_counts_index_eq
PARAMS ((const void *, const void *));
152 static void htab_counts_index_del
PARAMS ((void *));
153 static void cleanup_counts_index
PARAMS ((int));
154 static int index_counts_file
PARAMS ((void));
155 static gcov_type
* get_exec_counts
PARAMS ((void));
156 static unsigned compute_checksum
PARAMS ((void));
157 static basic_block find_group
PARAMS ((basic_block
));
158 static void union_groups
PARAMS ((basic_block
, basic_block
));
161 /* Add edge instrumentation code to the entire insn chain.
163 F is the first insn of the chain.
164 NUM_BLOCKS is the number of basic blocks found in F. */
167 instrument_edges (el
)
168 struct edge_list
*el
;
170 int num_instr_edges
= 0;
171 int num_edges
= NUM_EDGES (el
);
173 remove_fake_edges ();
175 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, NULL
, next_bb
)
180 struct edge_info
*inf
= EDGE_INFO (e
);
181 if (!inf
->ignore
&& !inf
->on_tree
)
183 if (e
->flags
& EDGE_ABNORMAL
)
186 fprintf (rtl_dump_file
, "Edge %d to %d instrumented%s\n",
187 e
->src
->index
, e
->dest
->index
,
188 EDGE_CRITICAL_P (e
) ? " (and split)" : "");
189 insert_insn_on_edge (
190 gen_edge_profiler (total_num_edges_instrumented
191 + num_instr_edges
++), e
);
197 profile_info
.count_edges_instrumented_now
= num_instr_edges
;
198 total_num_edges_instrumented
+= num_instr_edges
;
199 profile_info
.count_instrumented_edges
= total_num_edges_instrumented
;
201 total_num_blocks_created
+= num_edges
;
203 fprintf (rtl_dump_file
, "%d edges instrumented\n", num_instr_edges
);
205 commit_edge_insertions_watch_calls ();
208 struct section_reference
215 struct da_index_entry
223 struct section_reference
*offsets
;
227 htab_counts_index_hash (of
)
230 const struct da_index_entry
*entry
= of
;
232 return htab_hash_string (entry
->function_name
) ^ entry
->section
;
236 htab_counts_index_eq (of1
, of2
)
240 const struct da_index_entry
*entry1
= of1
;
241 const struct da_index_entry
*entry2
= of2
;
243 return !strcmp (entry1
->function_name
, entry2
->function_name
)
244 && entry1
->section
== entry2
->section
;
248 htab_counts_index_del (what
)
251 struct da_index_entry
*entry
= what
;
254 for (i
= 0; i
< entry
->n_offsets
; i
++)
256 struct section_reference
*act
= entry
->offsets
+ i
;
257 if (act
->owns_summary
)
260 free (entry
->function_name
);
261 free (entry
->offsets
);
265 static char *counts_file_name
;
266 static htab_t counts_file_index
= NULL
;
269 cleanup_counts_index (close_file
)
272 if (da_file
&& close_file
)
277 if (counts_file_name
)
278 free (counts_file_name
);
279 counts_file_name
= NULL
;
280 if (counts_file_index
)
281 htab_delete (counts_file_index
);
282 counts_file_index
= NULL
;
288 char *function_name_buffer
= NULL
;
289 unsigned magic
, version
, ix
, checksum
;
294 counts_file_index
= htab_create (10, htab_counts_index_hash
, htab_counts_index_eq
, htab_counts_index_del
);
296 /* No .da file, no data. */
300 /* Now index all profile sections. */
306 if (gcov_read_unsigned (da_file
, &magic
) || magic
!= GCOV_DATA_MAGIC
)
308 warning ("`%s' is not a gcov data file", da_file_name
);
311 if (gcov_read_unsigned (da_file
, &version
) || version
!= GCOV_VERSION
)
314 magic
= GCOV_VERSION
;
316 for (ix
= 4; ix
--; magic
>>= 8, version
>>= 8)
321 warning ("`%s' is version `%.4s', expected version `%.4s'",
328 unsigned tag
, length
;
331 offset
= gcov_save_position (da_file
);
332 if (gcov_read_unsigned (da_file
, &tag
)
333 || gcov_read_unsigned (da_file
, &length
))
338 warning ("`%s' is corrupted", da_file_name
);
341 if (tag
== GCOV_TAG_FUNCTION
)
343 if (gcov_read_string (da_file
, &function_name_buffer
, NULL
)
344 || gcov_read_unsigned (da_file
, &checksum
))
348 if (tag
== GCOV_TAG_PROGRAM_SUMMARY
)
350 if (length
!= GCOV_SUMMARY_LENGTH
)
359 if (function_name_buffer
)
361 struct da_index_entry
**slot
, elt
;
362 elt
.function_name
= function_name_buffer
;
365 slot
= (struct da_index_entry
**)
366 htab_find_slot (counts_file_index
, &elt
, INSERT
);
369 if ((*slot
)->checksum
!= checksum
)
371 warning ("profile mismatch for `%s'", function_name_buffer
);
374 (*slot
)->n_offsets
++;
375 (*slot
)->offsets
= xrealloc ((*slot
)->offsets
,
376 sizeof (struct section_reference
) * (*slot
)->n_offsets
);
380 *slot
= xmalloc (sizeof (struct da_index_entry
));
381 (*slot
)->function_name
= xstrdup (function_name_buffer
);
382 (*slot
)->section
= tag
;
383 (*slot
)->checksum
= checksum
;
384 (*slot
)->n_offsets
= 1;
385 (*slot
)->offsets
= xmalloc (sizeof (struct section_reference
));
387 (*slot
)->offsets
[(*slot
)->n_offsets
- 1].offset
= offset
;
389 (*slot
)->offsets
[(*slot
)->n_offsets
- 1].owns_summary
= 0;
392 summary
= xmalloc (sizeof (long));
394 (*slot
)->offsets
[(*slot
)->n_offsets
- 1].owns_summary
= 1;
396 (*slot
)->offsets
[(*slot
)->n_offsets
- 1].summary
= summary
;
399 if (gcov_skip (da_file
, length
))
403 free (function_name_buffer
);
408 cleanup_counts_index (1);
409 if (function_name_buffer
)
410 free (function_name_buffer
);
414 /* Computes hybrid profile for all matching entries in da_file.
415 Sets max_counter_in_program as a side effect. */
420 unsigned num_edges
= 0;
424 unsigned ix
, i
, tag
, length
, num
;
425 const char *name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl
));
426 struct da_index_entry
*entry
, what
;
427 struct section_reference
*act
;
429 struct gcov_summary summ
;
431 profile_info
.max_counter_in_program
= 0;
432 profile_info
.count_profiles_merged
= 0;
434 /* No .da file, no execution counts. */
437 if (!counts_file_index
)
440 /* Count the edges to be (possibly) instrumented. */
442 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, NULL
, next_bb
)
445 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
446 if (!EDGE_INFO (e
)->ignore
&& !EDGE_INFO (e
)->on_tree
)
450 /* now read and combine all matching profiles. */
452 profile
= xmalloc (sizeof (gcov_type
) * num_edges
);
454 for (ix
= 0; ix
< num_edges
; ix
++)
457 what
.function_name
= (char *) name
;
458 what
.section
= GCOV_TAG_ARC_COUNTS
;
459 entry
= htab_find (counts_file_index
, &what
);
462 warning ("No profile for function '%s' found.", name
);
466 if (entry
->checksum
!= profile_info
.current_function_cfg_checksum
)
468 warning ("profile mismatch for `%s'", current_function_name
);
472 for (i
= 0; i
< entry
->n_offsets
; i
++)
474 act
= entry
->offsets
+ i
;
476 /* Read arc counters. */
478 gcov_resync (da_file
, act
->offset
, 0);
480 if (gcov_read_unsigned (da_file
, &tag
)
481 || gcov_read_unsigned (da_file
, &length
)
482 || tag
!= GCOV_TAG_ARC_COUNTS
)
484 /* We have already passed through file, so any error means
485 something is rotten. */
490 if (num
!= num_edges
)
492 warning ("profile mismatch for `%s'", current_function_name
);
496 for (ix
= 0; ix
!= num
; ix
++)
498 if (gcov_read_counter (da_file
, &count
))
500 if (count
> max_count
)
502 profile
[ix
] += count
;
505 /* Read program summary. */
506 if (*act
->summary
!= -1)
508 gcov_resync (da_file
, *act
->summary
, 0);
509 if (gcov_read_unsigned (da_file
, &tag
)
510 || gcov_read_unsigned (da_file
, &length
)
511 || tag
!= GCOV_TAG_PROGRAM_SUMMARY
512 || gcov_read_summary (da_file
, &summ
))
514 profile_info
.count_profiles_merged
+= summ
.runs
;
515 profile_info
.max_counter_in_program
+= summ
.arc_sum_max
;
521 profile_info
.count_profiles_merged
++;
522 profile_info
.max_counter_in_program
+= max_count
;
528 fprintf(rtl_dump_file
, "Merged %i profiles with maximal count %i.\n",
529 profile_info
.count_profiles_merged
,
530 (int)profile_info
.max_counter_in_program
);
537 cleanup_counts_index (1);
542 /* Compute the branch probabilities for the various branches.
543 Annotate them accordingly. */
546 compute_branch_probabilities ()
553 int hist_br_prob
[20];
554 int num_never_executed
;
556 gcov_type
*exec_counts
= get_exec_counts ();
557 int exec_counts_pos
= 0;
559 /* Attach extra info block to each bb. */
561 alloc_aux_for_blocks (sizeof (struct bb_info
));
562 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, NULL
, next_bb
)
566 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
567 if (!EDGE_INFO (e
)->ignore
)
568 BB_INFO (bb
)->succ_count
++;
569 for (e
= bb
->pred
; e
; e
= e
->pred_next
)
570 if (!EDGE_INFO (e
)->ignore
)
571 BB_INFO (bb
)->pred_count
++;
574 /* Avoid predicting entry on exit nodes. */
575 BB_INFO (EXIT_BLOCK_PTR
)->succ_count
= 2;
576 BB_INFO (ENTRY_BLOCK_PTR
)->pred_count
= 2;
578 /* For each edge not on the spanning tree, set its execution count from
581 /* The first count in the .da file is the number of times that the function
582 was entered. This is the exec_count for block zero. */
584 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, NULL
, next_bb
)
587 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
588 if (!EDGE_INFO (e
)->ignore
&& !EDGE_INFO (e
)->on_tree
)
593 e
->count
= exec_counts
[exec_counts_pos
++];
598 EDGE_INFO (e
)->count_valid
= 1;
599 BB_INFO (bb
)->succ_count
--;
600 BB_INFO (e
->dest
)->pred_count
--;
603 fprintf (rtl_dump_file
, "\nRead edge from %i to %i, count:",
604 bb
->index
, e
->dest
->index
);
605 fprintf (rtl_dump_file
, HOST_WIDEST_INT_PRINT_DEC
,
606 (HOST_WIDEST_INT
) e
->count
);
612 fprintf (rtl_dump_file
, "\n%d edge counts read\n", num_edges
);
614 /* For every block in the file,
615 - if every exit/entrance edge has a known count, then set the block count
616 - if the block count is known, and every exit/entrance edge but one has
617 a known execution count, then set the count of the remaining edge
619 As edge counts are set, decrement the succ/pred count, but don't delete
620 the edge, that way we can easily tell when all edges are known, or only
621 one edge is unknown. */
623 /* The order that the basic blocks are iterated through is important.
624 Since the code that finds spanning trees starts with block 0, low numbered
625 edges are put on the spanning tree in preference to high numbered edges.
626 Hence, most instrumented edges are at the end. Graph solving works much
627 faster if we propagate numbers from the end to the start.
629 This takes an average of slightly more than 3 passes. */
637 FOR_BB_BETWEEN (bb
, EXIT_BLOCK_PTR
, NULL
, prev_bb
)
639 struct bb_info
*bi
= BB_INFO (bb
);
640 if (! bi
->count_valid
)
642 if (bi
->succ_count
== 0)
647 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
653 else if (bi
->pred_count
== 0)
658 for (e
= bb
->pred
; e
; e
= e
->pred_next
)
667 if (bi
->succ_count
== 1)
672 /* One of the counts will be invalid, but it is zero,
673 so adding it in also doesn't hurt. */
674 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
677 /* Seedgeh for the invalid edge, and set its count. */
678 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
679 if (! EDGE_INFO (e
)->count_valid
&& ! EDGE_INFO (e
)->ignore
)
682 /* Calculate count for remaining edge by conservation. */
683 total
= bb
->count
- total
;
687 EDGE_INFO (e
)->count_valid
= 1;
691 BB_INFO (e
->dest
)->pred_count
--;
694 if (bi
->pred_count
== 1)
699 /* One of the counts will be invalid, but it is zero,
700 so adding it in also doesn't hurt. */
701 for (e
= bb
->pred
; e
; e
= e
->pred_next
)
704 /* Seedgeh for the invalid edge, and set its count. */
705 for (e
= bb
->pred
; e
; e
= e
->pred_next
)
706 if (! EDGE_INFO (e
)->count_valid
&& ! EDGE_INFO (e
)->ignore
)
709 /* Calculate count for remaining edge by conservation. */
710 total
= bb
->count
- total
+ e
->count
;
714 EDGE_INFO (e
)->count_valid
= 1;
718 BB_INFO (e
->src
)->succ_count
--;
725 dump_flow_info (rtl_dump_file
);
727 total_num_passes
+= passes
;
729 fprintf (rtl_dump_file
, "Graph solving took %d passes.\n\n", passes
);
731 /* If the graph has been correctly solved, every block will have a
732 succ and pred count of zero. */
735 if (BB_INFO (bb
)->succ_count
|| BB_INFO (bb
)->pred_count
)
739 /* For every edge, calculate its branch probability and add a reg_note
740 to the branch insn to indicate this. */
742 for (i
= 0; i
< 20; i
++)
744 num_never_executed
= 0;
747 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, NULL
, next_bb
)
756 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
758 e
->probability
= (e
->count
* REG_BR_PROB_BASE
+ total
/ 2) / total
;
759 if (e
->probability
< 0 || e
->probability
> REG_BR_PROB_BASE
)
761 error ("corrupted profile info: prob for %d-%d thought to be %d",
762 e
->src
->index
, e
->dest
->index
, e
->probability
);
763 e
->probability
= REG_BR_PROB_BASE
/ 2;
767 && any_condjump_p (bb
->end
)
768 && bb
->succ
->succ_next
)
774 /* Find the branch edge. It is possible that we do have fake
776 for (e
= bb
->succ
; e
->flags
& (EDGE_FAKE
| EDGE_FALLTHRU
);
778 continue; /* Loop body has been intentionally left blank. */
780 prob
= e
->probability
;
781 index
= prob
* 20 / REG_BR_PROB_BASE
;
785 hist_br_prob
[index
]++;
787 note
= find_reg_note (bb
->end
, REG_BR_PROB
, 0);
788 /* There may be already note put by some other pass, such
789 as builtin_expect expander. */
791 XEXP (note
, 0) = GEN_INT (prob
);
794 = gen_rtx_EXPR_LIST (REG_BR_PROB
, GEN_INT (prob
),
795 REG_NOTES (bb
->end
));
799 /* Otherwise distribute the probabilities evenly so we get sane
800 sum. Use simple heuristics that if there are normal edges,
801 give all abnormals frequency of 0, otherwise distribute the
802 frequency over abnormals (this is the case of noreturn
806 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
807 if (!(e
->flags
& (EDGE_COMPLEX
| EDGE_FAKE
)))
811 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
812 if (!(e
->flags
& (EDGE_COMPLEX
| EDGE_FAKE
)))
813 e
->probability
= REG_BR_PROB_BASE
/ total
;
819 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
821 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
822 e
->probability
= REG_BR_PROB_BASE
/ total
;
825 && any_condjump_p (bb
->end
)
826 && bb
->succ
->succ_next
)
827 num_branches
++, num_never_executed
;
833 fprintf (rtl_dump_file
, "%d branches\n", num_branches
);
834 fprintf (rtl_dump_file
, "%d branches never executed\n",
837 for (i
= 0; i
< 10; i
++)
838 fprintf (rtl_dump_file
, "%d%% branches in range %d-%d%%\n",
839 (hist_br_prob
[i
] + hist_br_prob
[19-i
]) * 100 / num_branches
,
842 total_num_branches
+= num_branches
;
843 total_num_never_executed
+= num_never_executed
;
844 for (i
= 0; i
< 20; i
++)
845 total_hist_br_prob
[i
] += hist_br_prob
[i
];
847 fputc ('\n', rtl_dump_file
);
848 fputc ('\n', rtl_dump_file
);
851 free_aux_for_blocks ();
856 /* Compute checksum for the current function. We generate a CRC32. */
870 unsigned value
= BB_TO_GCOV_INDEX (e
? e
->dest
: bb
);
873 /* No need to use all bits in value identically, nearly all
874 functions have less than 256 blocks. */
875 value
^= value
<< 16;
878 for (ix
= 8; ix
--; value
<<= 1)
882 feedback
= (value
^ chksum
) & 0x80000000 ? 0x04c11db7 : 0;
887 e
= e
? e
->succ_next
: bb
->succ
;
895 /* Instrument and/or analyze program behavior based on program flow graph.
896 In either case, this function builds a flow graph for the function being
897 compiled. The flow graph is stored in BB_GRAPH.
899 When FLAG_PROFILE_ARCS is nonzero, this function instruments the edges in
900 the flow graph that are needed to reconstruct the dynamic behavior of the
903 When FLAG_BRANCH_PROBABILITIES is nonzero, this function reads auxiliary
904 information from a data file containing edge count information from previous
905 executions of the function being compiled. In this case, the flow graph is
906 annotated with actual execution counts, which are later propagated into the
907 rtl for optimization purposes.
909 Main entry point of this file. */
916 int num_edges
, ignored_edges
;
917 struct edge_list
*el
;
918 const char *name
= IDENTIFIER_POINTER
919 (DECL_ASSEMBLER_NAME (current_function_decl
));
921 profile_info
.current_function_cfg_checksum
= compute_checksum ();
924 fprintf (rtl_dump_file
, "CFG checksum is %u\n",
925 profile_info
.current_function_cfg_checksum
);
927 total_num_times_called
++;
929 flow_call_edges_add (NULL
);
930 add_noreturn_fake_exit_edges ();
932 /* We can't handle cyclic regions constructed using abnormal edges.
933 To avoid these we replace every source of abnormal edge by a fake
934 edge from entry node and every destination by fake edge to exit.
935 This keeps graph acyclic and our calculation exact for all normal
936 edges except for exit and entrance ones.
938 We also add fake exit edges for each call and asm statement in the
939 basic, since it may not return. */
943 int need_exit_edge
= 0, need_entry_edge
= 0;
944 int have_exit_edge
= 0, have_entry_edge
= 0;
948 /* Add fake edges from entry block to the call insns that may return
949 twice. The CFG is not quite correct then, as call insn plays more
950 role of CODE_LABEL, but for our purposes, everything should be OK,
951 as we never insert code to the beginning of basic block. */
952 for (insn
= bb
->head
; insn
!= NEXT_INSN (bb
->end
);
953 insn
= NEXT_INSN (insn
))
955 if (GET_CODE (insn
) == CALL_INSN
956 && find_reg_note (insn
, REG_SETJMP
, NULL
))
958 if (GET_CODE (bb
->head
) == CODE_LABEL
959 || insn
!= NEXT_INSN (bb
->head
))
961 e
= split_block (bb
, PREV_INSN (insn
));
962 make_edge (ENTRY_BLOCK_PTR
, e
->dest
, EDGE_FAKE
);
967 /* We should not get abort here, as call to setjmp should not
968 be the very first instruction of function. */
969 if (bb
== ENTRY_BLOCK_PTR
)
971 make_edge (ENTRY_BLOCK_PTR
, bb
, EDGE_FAKE
);
976 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
978 if ((e
->flags
& (EDGE_ABNORMAL
| EDGE_ABNORMAL_CALL
))
979 && e
->dest
!= EXIT_BLOCK_PTR
)
981 if (e
->dest
== EXIT_BLOCK_PTR
)
984 for (e
= bb
->pred
; e
; e
= e
->pred_next
)
986 if ((e
->flags
& (EDGE_ABNORMAL
| EDGE_ABNORMAL_CALL
))
987 && e
->src
!= ENTRY_BLOCK_PTR
)
989 if (e
->src
== ENTRY_BLOCK_PTR
)
993 if (need_exit_edge
&& !have_exit_edge
)
996 fprintf (rtl_dump_file
, "Adding fake exit edge to bb %i\n",
998 make_edge (bb
, EXIT_BLOCK_PTR
, EDGE_FAKE
);
1000 if (need_entry_edge
&& !have_entry_edge
)
1003 fprintf (rtl_dump_file
, "Adding fake entry edge to bb %i\n",
1005 make_edge (ENTRY_BLOCK_PTR
, bb
, EDGE_FAKE
);
1009 el
= create_edge_list ();
1010 num_edges
= NUM_EDGES (el
);
1011 alloc_aux_for_edges (sizeof (struct edge_info
));
1013 /* The basic blocks are expected to be numbered sequentially. */
1017 for (i
= 0 ; i
< num_edges
; i
++)
1019 edge e
= INDEX_EDGE (el
, i
);
1022 /* Mark edges we've replaced by fake edges above as ignored. */
1023 if ((e
->flags
& (EDGE_ABNORMAL
| EDGE_ABNORMAL_CALL
))
1024 && e
->src
!= ENTRY_BLOCK_PTR
&& e
->dest
!= EXIT_BLOCK_PTR
)
1026 EDGE_INFO (e
)->ignore
= 1;
1031 #ifdef ENABLE_CHECKING
1032 verify_flow_info ();
1035 /* Create spanning tree from basic block graph, mark each edge that is
1036 on the spanning tree. We insert as many abnormal and critical edges
1037 as possible to minimize number of edge splits necessary. */
1039 find_spanning_tree (el
);
1041 /* Fake edges that are not on the tree will not be instrumented, so
1042 mark them ignored. */
1043 for (i
= 0; i
< num_edges
; i
++)
1045 edge e
= INDEX_EDGE (el
, i
);
1046 struct edge_info
*inf
= EDGE_INFO (e
);
1047 if ((e
->flags
& EDGE_FAKE
) && !inf
->ignore
&& !inf
->on_tree
)
1054 total_num_blocks
+= n_basic_blocks
+ 2;
1056 fprintf (rtl_dump_file
, "%d basic blocks\n", n_basic_blocks
);
1058 total_num_edges
+= num_edges
;
1060 fprintf (rtl_dump_file
, "%d edges\n", num_edges
);
1062 total_num_edges_ignored
+= ignored_edges
;
1064 fprintf (rtl_dump_file
, "%d ignored edges\n", ignored_edges
);
1066 /* Create a .bbg file from which gcov can reconstruct the basic block
1067 graph. First output the number of basic blocks, and then for every
1068 edge output the source and target basic block numbers.
1069 NOTE: The format of this file must be compatible with gcov. */
1071 if (flag_test_coverage
&& bbg_file
)
1075 /* Announce function */
1076 if (gcov_write_unsigned (bbg_file
, GCOV_TAG_FUNCTION
)
1077 || !(offset
= gcov_reserve_length (bbg_file
))
1078 || gcov_write_string (bbg_file
, name
,
1080 || gcov_write_unsigned (bbg_file
,
1081 profile_info
.current_function_cfg_checksum
)
1082 || gcov_write_length (bbg_file
, offset
))
1085 /* Basic block flags */
1086 if (gcov_write_unsigned (bbg_file
, GCOV_TAG_BLOCKS
)
1087 || !(offset
= gcov_reserve_length (bbg_file
)))
1089 for (i
= 0; i
!= n_basic_blocks
+ 2; i
++)
1090 if (gcov_write_unsigned (bbg_file
, 0))
1092 if (gcov_write_length (bbg_file
, offset
))
1096 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, EXIT_BLOCK_PTR
, next_bb
)
1100 if (gcov_write_unsigned (bbg_file
, GCOV_TAG_ARCS
)
1101 || !(offset
= gcov_reserve_length (bbg_file
))
1102 || gcov_write_unsigned (bbg_file
, BB_TO_GCOV_INDEX (bb
)))
1105 for (e
= bb
->succ
; e
; e
= e
->succ_next
)
1107 struct edge_info
*i
= EDGE_INFO (e
);
1110 unsigned flag_bits
= 0;
1113 flag_bits
|= GCOV_ARC_ON_TREE
;
1114 if (e
->flags
& EDGE_FAKE
)
1115 flag_bits
|= GCOV_ARC_FAKE
;
1116 if (e
->flags
& EDGE_FALLTHRU
)
1117 flag_bits
|= GCOV_ARC_FALLTHROUGH
;
1119 if (gcov_write_unsigned (bbg_file
,
1120 BB_TO_GCOV_INDEX (e
->dest
))
1121 || gcov_write_unsigned (bbg_file
, flag_bits
))
1125 if (gcov_write_length (bbg_file
, offset
))
1129 /* Output line number information about each basic block for
1132 char const *prev_file_name
= NULL
;
1136 rtx insn
= bb
->head
;
1137 int ignore_next_note
= 0;
1141 /* We are looking for line number notes. Search backward
1142 before basic block to find correct ones. */
1143 insn
= prev_nonnote_insn (insn
);
1145 insn
= get_insns ();
1147 insn
= NEXT_INSN (insn
);
1149 while (insn
!= bb
->end
)
1151 if (GET_CODE (insn
) == NOTE
)
1153 /* Must ignore the line number notes that immediately
1154 follow the end of an inline function to avoid counting
1155 it twice. There is a note before the call, and one
1157 if (NOTE_LINE_NUMBER (insn
)
1158 == NOTE_INSN_REPEATED_LINE_NUMBER
)
1159 ignore_next_note
= 1;
1160 else if (NOTE_LINE_NUMBER (insn
) <= 0)
1162 else if (ignore_next_note
)
1163 ignore_next_note
= 0;
1168 else if (gcov_write_unsigned (bbg_file
, GCOV_TAG_LINES
)
1169 || !(offset
= gcov_reserve_length (bbg_file
))
1170 || gcov_write_unsigned (bbg_file
,
1171 BB_TO_GCOV_INDEX (bb
)))
1173 /* If this is a new source file, then output
1174 the file's name to the .bb file. */
1176 || strcmp (NOTE_SOURCE_FILE (insn
),
1179 prev_file_name
= NOTE_SOURCE_FILE (insn
);
1180 if (gcov_write_unsigned (bbg_file
, 0)
1181 || gcov_write_string (bbg_file
, prev_file_name
,
1182 strlen (prev_file_name
)))
1185 if (gcov_write_unsigned (bbg_file
, NOTE_LINE_NUMBER (insn
)))
1189 insn
= NEXT_INSN (insn
);
1193 if (gcov_write_unsigned (bbg_file
, 0)
1194 || gcov_write_string (bbg_file
, NULL
, 0)
1195 || gcov_write_length (bbg_file
, offset
))
1198 warning ("error writing `%s'", bbg_file_name
);
1207 if (flag_branch_probabilities
)
1208 compute_branch_probabilities ();
1210 /* For each edge not on the spanning tree, add counting code as rtl. */
1212 if (cfun
->arc_profile
&& profile_arc_flag
)
1214 struct function_list
*item
;
1216 instrument_edges (el
);
1217 allocate_reg_info (max_reg_num (), FALSE
, FALSE
);
1219 /* ??? Probably should re-use the existing struct function. */
1220 item
= xmalloc (sizeof (struct function_list
));
1222 *functions_tail
= item
;
1223 functions_tail
= &item
->next
;
1226 item
->name
= xstrdup (name
);
1227 item
->cfg_checksum
= profile_info
.current_function_cfg_checksum
;
1228 item
->count_edges
= profile_info
.count_edges_instrumented_now
;
1231 remove_fake_edges ();
1232 /* Re-merge split basic blocks and the mess introduced by
1233 insert_insn_on_edge. */
1234 cleanup_cfg (profile_arc_flag
? CLEANUP_EXPENSIVE
: 0);
1236 dump_flow_info (rtl_dump_file
);
1238 free_aux_for_edges ();
1239 free_edge_list (el
);
1242 /* Union find algorithm implementation for the basic blocks using
1249 basic_block group
= bb
, bb1
;
1251 while ((basic_block
) group
->aux
!= group
)
1252 group
= (basic_block
) group
->aux
;
1254 /* Compress path. */
1255 while ((basic_block
) bb
->aux
!= group
)
1257 bb1
= (basic_block
) bb
->aux
;
1258 bb
->aux
= (void *) group
;
1265 union_groups (bb1
, bb2
)
1266 basic_block bb1
, bb2
;
1268 basic_block bb1g
= find_group (bb1
);
1269 basic_block bb2g
= find_group (bb2
);
1271 /* ??? I don't have a place for the rank field. OK. Lets go w/o it,
1272 this code is unlikely going to be performance problem anyway. */
1279 /* This function searches all of the edges in the program flow graph, and puts
1280 as many bad edges as possible onto the spanning tree. Bad edges include
1281 abnormals edges, which can't be instrumented at the moment. Since it is
1282 possible for fake edges to form a cycle, we will have to develop some
1283 better way in the future. Also put critical edges to the tree, since they
1284 are more expensive to instrument. */
1287 find_spanning_tree (el
)
1288 struct edge_list
*el
;
1291 int num_edges
= NUM_EDGES (el
);
1294 /* We use aux field for standard union-find algorithm. */
1295 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, NULL
, next_bb
)
1298 /* Add fake edge exit to entry we can't instrument. */
1299 union_groups (EXIT_BLOCK_PTR
, ENTRY_BLOCK_PTR
);
1301 /* First add all abnormal edges to the tree unless they form a cycle. Also
1302 add all edges to EXIT_BLOCK_PTR to avoid inserting profiling code behind
1303 setting return value from function. */
1304 for (i
= 0; i
< num_edges
; i
++)
1306 edge e
= INDEX_EDGE (el
, i
);
1307 if (((e
->flags
& (EDGE_ABNORMAL
| EDGE_ABNORMAL_CALL
| EDGE_FAKE
))
1308 || e
->dest
== EXIT_BLOCK_PTR
1310 && !EDGE_INFO (e
)->ignore
1311 && (find_group (e
->src
) != find_group (e
->dest
)))
1314 fprintf (rtl_dump_file
, "Abnormal edge %d to %d put to tree\n",
1315 e
->src
->index
, e
->dest
->index
);
1316 EDGE_INFO (e
)->on_tree
= 1;
1317 union_groups (e
->src
, e
->dest
);
1321 /* Now insert all critical edges to the tree unless they form a cycle. */
1322 for (i
= 0; i
< num_edges
; i
++)
1324 edge e
= INDEX_EDGE (el
, i
);
1325 if ((EDGE_CRITICAL_P (e
))
1326 && !EDGE_INFO (e
)->ignore
1327 && (find_group (e
->src
) != find_group (e
->dest
)))
1330 fprintf (rtl_dump_file
, "Critical edge %d to %d put to tree\n",
1331 e
->src
->index
, e
->dest
->index
);
1332 EDGE_INFO (e
)->on_tree
= 1;
1333 union_groups (e
->src
, e
->dest
);
1337 /* And now the rest. */
1338 for (i
= 0; i
< num_edges
; i
++)
1340 edge e
= INDEX_EDGE (el
, i
);
1341 if (find_group (e
->src
) != find_group (e
->dest
)
1342 && !EDGE_INFO (e
)->ignore
)
1345 fprintf (rtl_dump_file
, "Normal edge %d to %d put to tree\n",
1346 e
->src
->index
, e
->dest
->index
);
1347 EDGE_INFO (e
)->on_tree
= 1;
1348 union_groups (e
->src
, e
->dest
);
1352 FOR_BB_BETWEEN (bb
, ENTRY_BLOCK_PTR
, NULL
, next_bb
)
1356 /* Perform file-level initialization for branch-prob processing. */
1359 init_branch_prob (filename
)
1360 const char *filename
;
1362 int len
= strlen (filename
);
1365 if (flag_test_coverage
)
1367 /* Open the bbg output file. */
1368 bbg_file_name
= (char *) xmalloc (len
+ strlen (GCOV_GRAPH_SUFFIX
) + 1);
1369 strcpy (bbg_file_name
, filename
);
1370 strcat (bbg_file_name
, GCOV_GRAPH_SUFFIX
);
1371 bbg_file
= fopen (bbg_file_name
, "wb");
1373 fatal_io_error ("cannot open %s", bbg_file_name
);
1375 if (gcov_write_unsigned (bbg_file
, GCOV_GRAPH_MAGIC
)
1376 || gcov_write_unsigned (bbg_file
, GCOV_VERSION
))
1379 fatal_io_error ("cannot write `%s'", bbg_file_name
);
1383 da_file_name
= (char *) xmalloc (len
+ strlen (GCOV_DATA_SUFFIX
) + 1);
1384 strcpy (da_file_name
, filename
);
1385 strcat (da_file_name
, GCOV_DATA_SUFFIX
);
1387 if (flag_branch_probabilities
)
1389 da_file
= fopen (da_file_name
, "rb");
1391 warning ("file %s not found, execution counts assumed to be zero",
1393 if (counts_file_index
&& strcmp (da_file_name
, counts_file_name
))
1394 cleanup_counts_index (0);
1395 if (index_counts_file ())
1396 counts_file_name
= xstrdup (da_file_name
);
1399 if (profile_arc_flag
)
1401 /* Generate and save a copy of this so it can be shared. */
1404 ASM_GENERATE_INTERNAL_LABEL (buf
, "LPBX", 2);
1405 profiler_label
= gen_rtx_SYMBOL_REF (Pmode
, ggc_strdup (buf
));
1408 total_num_blocks
= 0;
1409 total_num_edges
= 0;
1410 total_num_edges_ignored
= 0;
1411 total_num_edges_instrumented
= 0;
1412 total_num_blocks_created
= 0;
1413 total_num_passes
= 0;
1414 total_num_times_called
= 0;
1415 total_num_branches
= 0;
1416 total_num_never_executed
= 0;
1417 for (i
= 0; i
< 20; i
++)
1418 total_hist_br_prob
[i
] = 0;
1421 /* Performs file-level cleanup after branch-prob processing
1427 if (flag_test_coverage
)
1432 /* If the compiler is instrumented, we should not remove the
1433 counts file, because we might be recompiling
1434 ourselves. The .da files are all removed during copying
1435 the stage1 files. */
1436 unlink (da_file_name
);
1442 unlink (bbg_file_name
);
1443 unlink (da_file_name
);
1452 fprintf (rtl_dump_file
, "\n");
1453 fprintf (rtl_dump_file
, "Total number of blocks: %d\n",
1455 fprintf (rtl_dump_file
, "Total number of edges: %d\n", total_num_edges
);
1456 fprintf (rtl_dump_file
, "Total number of ignored edges: %d\n",
1457 total_num_edges_ignored
);
1458 fprintf (rtl_dump_file
, "Total number of instrumented edges: %d\n",
1459 total_num_edges_instrumented
);
1460 fprintf (rtl_dump_file
, "Total number of blocks created: %d\n",
1461 total_num_blocks_created
);
1462 fprintf (rtl_dump_file
, "Total number of graph solution passes: %d\n",
1464 if (total_num_times_called
!= 0)
1465 fprintf (rtl_dump_file
, "Average number of graph solution passes: %d\n",
1466 (total_num_passes
+ (total_num_times_called
>> 1))
1467 / total_num_times_called
);
1468 fprintf (rtl_dump_file
, "Total number of branches: %d\n",
1469 total_num_branches
);
1470 fprintf (rtl_dump_file
, "Total number of branches never executed: %d\n",
1471 total_num_never_executed
);
1472 if (total_num_branches
)
1476 for (i
= 0; i
< 10; i
++)
1477 fprintf (rtl_dump_file
, "%d%% branches in range %d-%d%%\n",
1478 (total_hist_br_prob
[i
] + total_hist_br_prob
[19-i
]) * 100
1479 / total_num_branches
, 5*i
, 5*i
+5);
1484 /* Write out the structure which libgcc uses to locate all the arc
1485 counters. The structures used here must match those defined in
1486 gcov-io.h. Write out the constructor to call __gcov_init. */
1491 tree fields
, field
, value
= NULL_TREE
;
1494 tree gcov_type
, gcov_ptr_type
;
1497 tree structure
, ctor
;
1498 rtx structure_address
;
1499 int save_flag_inline_functions
= flag_inline_functions
;
1501 if (!profile_info
.count_instrumented_edges
)
1504 string_type
= build_pointer_type
1505 (build_qualified_type (char_type_node
, TYPE_QUAL_CONST
));
1506 gcov_type
= make_signed_type (GCOV_TYPE_SIZE
);
1508 = build_pointer_type (build_qualified_type
1509 (gcov_type
, TYPE_QUAL_CONST
));
1511 ginfo_type
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
1515 fields
= build_decl (FIELD_DECL
, NULL_TREE
, long_unsigned_type_node
);
1516 value
= tree_cons (fields
, convert (long_unsigned_type_node
, build_int_2
1517 (GCOV_VERSION
, 0)), value
);
1520 field
= build_decl (FIELD_DECL
, NULL_TREE
, build_pointer_type
1521 (build_qualified_type
1522 (ginfo_type
, TYPE_QUAL_CONST
)));
1523 TREE_CHAIN (field
) = fields
;
1525 value
= tree_cons (fields
, null_pointer_node
, value
);
1529 tree filename_string
;
1533 filename
= getpwd ();
1534 filename
= (filename
&& da_file_name
[0] != '/'
1535 ? concat (filename
, "/", da_file_name
, NULL
)
1537 filename_len
= strlen (filename
);
1538 filename_string
= build_string (filename_len
+ 1, filename
);
1539 if (filename
!= da_file_name
)
1541 TREE_TYPE (filename_string
) = build_array_type
1542 (char_type_node
, build_index_type
1543 (build_int_2 (filename_len
, 0)));
1545 field
= build_decl (FIELD_DECL
, NULL_TREE
, string_type
);
1546 TREE_CHAIN (field
) = fields
;
1548 value
= tree_cons (fields
, build1 (ADDR_EXPR
, string_type
,
1549 filename_string
), value
);
1553 field
= build_decl (FIELD_DECL
, NULL_TREE
, long_integer_type_node
);
1554 TREE_CHAIN (field
) = fields
;
1556 value
= tree_cons (fields
,
1557 convert (long_integer_type_node
, integer_zero_node
),
1560 /* function_info table */
1562 struct function_list
*item
;
1564 tree array_value
= NULL_TREE
;
1565 tree finfo_type
, finfo_ptr_type
;
1566 tree name
, checksum
, arcs
;
1568 finfo_type
= (*lang_hooks
.types
.make_type
) (RECORD_TYPE
);
1569 name
= build_decl (FIELD_DECL
, NULL_TREE
, string_type
);
1570 checksum
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
1571 TREE_CHAIN (checksum
) = name
;
1572 arcs
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
1573 TREE_CHAIN (arcs
) = checksum
;
1574 finish_builtin_struct (finfo_type
, "__function_info",
1576 finfo_ptr_type
= build_pointer_type
1577 (build_qualified_type (finfo_type
, TYPE_QUAL_CONST
));
1579 for (item
= functions_head
; item
!= 0; item
= item
->next
, num_nodes
++)
1581 size_t name_len
= strlen (item
->name
);
1582 tree finfo_value
= NULL_TREE
;
1583 tree fname
= build_string (name_len
+ 1, item
->name
);
1585 TREE_TYPE (fname
) = build_array_type
1586 (char_type_node
, build_index_type (build_int_2 (name_len
, 0)));
1587 finfo_value
= tree_cons (name
, build1
1588 (ADDR_EXPR
, string_type
,
1589 fname
), finfo_value
);
1590 finfo_value
= tree_cons (checksum
, convert
1591 (unsigned_type_node
,
1592 build_int_2 (item
->cfg_checksum
, 0)),
1594 finfo_value
= tree_cons (arcs
, convert
1595 (unsigned_type_node
,
1596 build_int_2 (item
->count_edges
, 0)),
1598 array_value
= tree_cons (NULL_TREE
, build
1599 (CONSTRUCTOR
, finfo_type
, NULL_TREE
,
1600 nreverse (finfo_value
)), array_value
);
1603 /* Create constructor for array. */
1608 array_type
= build_array_type (finfo_type
, build_index_type
1609 (build_int_2 (num_nodes
- 1, 0)));
1610 array_value
= build (CONSTRUCTOR
, array_type
,
1611 NULL_TREE
, nreverse (array_value
));
1612 array_value
= build1
1613 (ADDR_EXPR
, finfo_ptr_type
, array_value
);
1616 array_value
= null_pointer_node
;
1618 field
= build_decl (FIELD_DECL
, NULL_TREE
, finfo_ptr_type
);
1619 TREE_CHAIN (field
) = fields
;
1621 value
= tree_cons (fields
, array_value
, value
);
1623 /* number of functions */
1624 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
1625 TREE_CHAIN (field
) = fields
;
1627 value
= tree_cons (fields
, convert (unsigned_type_node
, build_int_2
1628 (num_nodes
, 0)), value
);
1631 /* arc count table */
1633 tree counts_table
= null_pointer_node
;
1635 if (profile_info
.count_instrumented_edges
)
1637 tree gcov_type_array_type
1638 = build_array_type (gcov_type
, build_index_type
1639 (build_int_2 (profile_info
.
1640 count_instrumented_edges
- 1, 0)));
1643 = build (VAR_DECL
, gcov_type_array_type
, NULL_TREE
, NULL_TREE
);
1644 TREE_STATIC (counts_table
) = 1;
1645 DECL_NAME (counts_table
) = get_identifier (XSTR (profiler_label
, 0));
1646 assemble_variable (counts_table
, 0, 0, 0);
1647 counts_table
= build1 (ADDR_EXPR
, gcov_ptr_type
, counts_table
);
1650 field
= build_decl (FIELD_DECL
, NULL_TREE
, gcov_ptr_type
);
1651 TREE_CHAIN (field
) = fields
;
1653 value
= tree_cons (fields
, counts_table
, value
);
1656 /* number of arc counts */
1657 field
= build_decl (FIELD_DECL
, NULL_TREE
, unsigned_type_node
);
1658 TREE_CHAIN (field
) = fields
;
1660 value
= tree_cons (fields
, convert
1661 (unsigned_type_node
,
1662 build_int_2 (profile_info
1663 .count_instrumented_edges
, 0)),
1666 finish_builtin_struct (ginfo_type
, "__gcov_info", fields
, NULL_TREE
);
1667 structure
= build (VAR_DECL
, ginfo_type
, NULL_TREE
, NULL_TREE
);
1668 DECL_INITIAL (structure
)
1669 = build (CONSTRUCTOR
, ginfo_type
, NULL_TREE
, nreverse (value
));
1670 TREE_STATIC (structure
) = 1;
1671 ASM_GENERATE_INTERNAL_LABEL (name
, "LPBX", 0);
1672 DECL_NAME (structure
) = get_identifier (name
);
1674 /* Build structure. */
1675 assemble_variable (structure
, 0, 0, 0);
1677 /* Build the constructor function to invoke __gcov_init. */
1678 ctor_name
= concat (IDENTIFIER_POINTER (get_file_function_name ('I')),
1680 ctor
= build_decl (FUNCTION_DECL
, get_identifier (ctor_name
),
1681 build_function_type (void_type_node
, NULL_TREE
));
1683 DECL_EXTERNAL (ctor
) = 0;
1685 /* It can be a static function as long as collect2 does not have
1686 to scan the object file to find its ctor/dtor routine. */
1687 TREE_PUBLIC (ctor
) = ! targetm
.have_ctors_dtors
;
1688 TREE_USED (ctor
) = 1;
1689 DECL_RESULT (ctor
) = build_decl (RESULT_DECL
, NULL_TREE
, void_type_node
);
1691 ctor
= (*lang_hooks
.decls
.pushdecl
) (ctor
);
1692 rest_of_decl_compilation (ctor
, 0, 1, 0);
1693 announce_function (ctor
);
1694 current_function_decl
= ctor
;
1695 DECL_INITIAL (ctor
) = error_mark_node
;
1696 make_decl_rtl (ctor
, NULL
);
1697 init_function_start (ctor
, input_filename
, lineno
);
1698 (*lang_hooks
.decls
.pushlevel
) (0);
1699 expand_function_start (ctor
, 0);
1700 cfun
->arc_profile
= 0;
1702 /* Actually generate the code to call __gcov_init. */
1703 structure_address
= force_reg (Pmode
, gen_rtx_SYMBOL_REF
1704 (Pmode
, IDENTIFIER_POINTER
1705 (DECL_NAME (structure
))));
1706 emit_library_call (gen_rtx_SYMBOL_REF (Pmode
, "__gcov_init"),
1707 LCT_NORMAL
, VOIDmode
, 1,
1708 structure_address
, Pmode
);
1710 expand_function_end (input_filename
, lineno
, 0);
1711 (*lang_hooks
.decls
.poplevel
) (1, 0, 1);
1713 /* Since ctor isn't in the list of globals, it would never be emitted
1714 when it's considered to be 'safe' for inlining, so turn off
1715 flag_inline_functions. */
1716 flag_inline_functions
= 0;
1718 rest_of_compilation (ctor
);
1720 /* Reset flag_inline_functions to its original value. */
1721 flag_inline_functions
= save_flag_inline_functions
;
1724 fflush (asm_out_file
);
1725 current_function_decl
= NULL_TREE
;
1727 if (targetm
.have_ctors_dtors
)
1728 (* targetm
.asm_out
.constructor
) (XEXP (DECL_RTL (ctor
), 0),
1729 DEFAULT_INIT_PRIORITY
);
1732 /* Output instructions as RTL to increment the edge execution count. */
1735 gen_edge_profiler (edgeno
)
1738 enum machine_mode mode
= mode_for_size (GCOV_TYPE_SIZE
, MODE_INT
, 0);
1744 tmp
= force_reg (Pmode
, profiler_label
);
1745 tmp
= plus_constant (tmp
, GCOV_TYPE_SIZE
/ BITS_PER_UNIT
* edgeno
);
1746 mem_ref
= validize_mem (gen_rtx_MEM (mode
, tmp
));
1748 set_mem_alias_set (mem_ref
, new_alias_set ());
1750 tmp
= expand_simple_binop (mode
, PLUS
, mem_ref
, const1_rtx
,
1751 mem_ref
, 0, OPTAB_WIDEN
);
1754 emit_move_insn (copy_rtx (mem_ref
), tmp
);
1756 sequence
= get_insns ();
1761 #include "gt-profile.h"